Skip to content

[Feature Request] varlock audit: detect cloudflare:workers, IaC bindings, and framework env usage #736

Description

@PrinceD96

Description

varlock audit compares keys defined in .env.schema against environment-variable references found in source code. Today it works well for direct process.env.VAR usage and ENV.VAR from varlock/env, but it reports false positives ("unused in schema") for several common deployment patterns — especially Cloudflare Workers deployed via IaC tools other than varlock-wrangler.

In a monorepo using Alchemy for Cloudflare Workers + D1 + Astro:

  1. Deploy time: secrets and vars are declared as Worker bindings via alchemy.env.VAR / alchemy.secret.env.VAR in alchemy.run.ts. Alchemy reads resolved values from process.env (injected by varlock run --), but audit does not scan those binding declarations.
  2. Worker runtime: application code reads env.VAR from cloudflare:workers (sometimes via a thin package re-export). Audit does not trace property access on that import.
  3. Astro marketing site: public vars are consumed via astro:env/client imports, not process.env.

Running varlock audit from the infra package entry point flags every binding key (e.g. BETTER_AUTH_SECRET, PUBLIC_SERVER_URL, ALCHEMY_PASSWORD) as unused, even though they are actively used.

We currently work around Alchemy-only keys with # @auditIgnore per the audit hint ("If this is used by an external tool…"), but Worker and Astro keys are genuinely referenced in code — audit just cannot see them yet.

Motivation

Accurate varlock audit is important for:

  • Solo developers using AI coding agents (detecting drift between schema and code)
  • Monorepos where schema lives in packages/infra but consumption is spread across apps/packages
  • Alchemy / better-t-stack adopters who use varlock run -- <deploy> without varlock-wrangler

Without improved detection, audit either fails noisily or teams blanket @auditIgnore, which defeats the purpose.

Proposed Solution

Extend varlock audit (and/or document first-class patterns) for:

  1. cloudflare:workers env access — detect env.VAR, destructuring from cloudflare:workers, and common re-export wrappers (e.g. @talkiva/env/server).
  2. IaC binding declarations — optional detectors for known patterns such as alchemy.env.VAR, alchemy.secret.env.VAR, and potentially SST/Pulumi equivalents.
  3. Framework env modules — e.g. import { VAR } from "astro:env/client" mapped back to schema keys.
  4. Monorepo-aware scanning — when varlock.loadPath spans multiple packages, default audit scan roots could include sibling app/package directories referenced by the schema entry point.

If full static analysis is out of scope for some patterns, documenting recommended @auditIgnore categories (external CLI tools vs. runtime bindings) would still help.

Alternatives

  • @auditIgnore on all binding keys — works today but removes audit coverage for real drift.
  • Wait for @varlock/cloudflare-integration + varlock-wrangler only — does not help Alchemy/SST/Pulumi deploy paths where Worker code still uses cloudflare:workers without migrating imports to varlock/env.
  • Custom audit scripts — possible but duplicates logic Varlock already owns.

Additional Information

Example binding declaration audit should recognize:

export const server = await Worker("server", {
  bindings: {
    BETTER_AUTH_SECRET: alchemy.secret.env.BETTER_AUTH_SECRET!,
    CORS_ORIGIN: alchemy.env.CORS_ORIGIN!,
  },
});

Example runtime usage audit should recognize:

import { env } from "cloudflare:workers";
// or: import { env } from "@talkiva/env/server";
const origin = env.CORS_ORIGIN;

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions