Files
HiveGrid-Wireframes/hivegrid-cloud/docs/env-access-inventory.md
T

163 lines
73 KiB
Markdown

# Environment Access Inventory
This document is the environment-access baseline human-readable source of truth for direct environment access migration. It records key names, source locations, target runtimes, catalog classification, and follow-up owners only; it intentionally excludes values from `.env*` files and test fixtures.
## Scan command
Evidence was gathered with targeted source scans equivalent to:
```sh
grep -R "process\.env\|env(" apps/web/app apps/api apps/worker packages server prisma.config.ts .env.example .env.local.example .env.production.example .env.fly.example
```
Follow-up scans should prefer exact key extraction from source files and examples, then compare results against `packages/config/src/catalog.ts`.
## env drift gate contract
S02 wires the env catalog contract into CI with `pnpm run verify:env-drift`, implemented by `scripts/check-env-drift.mjs`. The gate scans the five versioned fixture/example surfaces `.env.example`, `.env.local.example`, `.env.production.example`, `.env.fly.example`, and `.env.test`, then compares their key names against `packages/config/src` catalog definitions, including dynamic-prefix handling such as `SITE_KEY_*`. In `.gitea/workflows/ci.yml`, the quality job runs `pnpm run verify:env-drift` immediately after `pnpm run verify:ci-baseline` and before `pnpm typecheck`, `pnpm lint`, `pnpm test`, and `pnpm build` so env-contract drift fails before more expensive checks.
`.env.test` is a committed, non-secret test fixture for deterministic local and CI validation; it must remain safe to read and version, even though real `.env*` files stay ignored. Drift diagnostics may print only file paths, line numbers, diagnostic categories, and key names. No secret values, placeholder values, or raw `.env` assignments may be emitted by `scripts/check-env-drift.mjs`, CI logs, or this inventory.
## Classification legend
| Classification | Meaning | Migration expectation |
| ------------------------ | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `required-core` | Required platform/core configuration used across runtimes. | Load through the shared config catalog before runtime startup. |
| `required-per-app` | Required for specific apps/web/app/API capabilities. | Migrate to the owning runtime loader and fail clearly when active feature paths require it. |
| `production-only` | Supplied by Node/platform or only needed in deployed environments. | Keep normalized behind runtime loaders; local defaults are acceptable where cataloged. |
| `optional-provider` | Optional third-party provider/integration settings. | Runtime loader should expose capability state and avoid hard failures until the provider feature is used. |
| `local-development-only` | Local/demo convenience only. | Keep out of production required groups. |
| `deprecated-remove` | Present in examples/catalog for audit history but no active source usage. | Remove from examples/docs unless a later slice finds active usage. |
| `dynamic` | Pattern-based key family rather than a single literal key. | Loader/enforcement must support prefix matching. |
| `test-only` | Test fixture mutation/read. | Not a runtime migration target. |
## Source-access table
| Key or family | Active source locations | Target runtime(s) | Catalog classification | Follow-up owner | Notes |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | ------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `APP_NAME` | `apps/web/app/routes/**/*.tsx`, `apps/web/app/modules/**/*.ts`, `apps/api/src/app.ts`; core web loader usage adopted in `apps/web/app/utils/data/.server/rootData.ts` and `apps/web/app/utils/db/appConfiguration.db.server.ts` | web, api, worker/shared | `required-core` | S03 api, S05 docs, S06 enforcement | adopted root data/app-configuration reads through `loadWebConfig`; broad web route/module metadata reads remain direct and should be handled as later docs/enforcement cleanup rather than claimed complete here. |
| `DATABASE_URL` | `packages/db/src/client.server.ts`, `prisma.config.ts` | shared, web, api, worker | `required-core` | web, S03 api, S04 worker | Prisma runtime and Prisma config both need catalog-backed loading. |
| `SESSION_SECRET` | `apps/web/app/locale/i18next.server.ts`, `apps/web/app/utils/session.server.ts`, `apps/web/app/utils/analyticsCookie.server.ts` | web, api | `required-core` | web | Cookie/session signing secret; current fallback strings should be reviewed during loader migration. |
| `APP_BASE_DOMAIN` | `packages/config/src/routing.ts`, `apps/api/src/app.test.ts` | shared, web, api, worker | `required-core` | web, S03 api | Runtime routing helper currently accepts env object and defaults to `process.env`. Test mutation is fixture-only. |
| `WEB_APP_HOST` | `packages/config/src/routing.ts` via env object | web, api | `required-per-app` | web, S03 api | Canonical tenant app host. |
| `APP_URL` | `apps/web/app/routes/app.$tenant/forms*.tsx`, `apps/worker/src/jobs/email-sequence-runtime.ts`, `apps/worker/src/jobs/workflow-trigger-http-executor.ts` | web, worker | `optional-provider` | S02 web, S04 worker | Public app origin used for embed fallback URLs, email sequence links, and the workflow-trigger execution bridge fallback. |
| `ADMIN_APP_HOST` | `packages/config/src/routing.ts` via env object | web, api | `required-per-app` | web, S03 api | Canonical admin host. |
| `API_HOST` | `packages/config/src/routing.ts` via env object | api, web | `required-per-app` | web, S03 api | Canonical API host. |
| `APP_PROTOCOL` | `packages/config/src/routing.ts` via env object | shared, web, api, worker | `production-only` | web, S03 api | Defaults to `http` locally; production should provide `https`. |
| `CRYPTO_SECRET` | `apps/web/app/utils/api/.server/CryptoApi.ts` | web, api | `required-per-app` | web, S03 api | Used for credential encryption/decryption. |
| `API_ACCESS_TOKEN` | `apps/web/app/utils/services/apiService.ts`, `apps/api/src/app.ts`, `apps/api/src/app.test.ts`, `apps/worker/src/jobs/workflow-trigger-http-executor.ts` | web, api, worker | `required-per-app` | web, S03 api, S04 worker | Service token for authenticated API calls and the worker-to-web workflow execution bridge; API tests mutate it as fixtures. |
| `JWT_SECRET` | `apps/web/app/utils/services/apiService.ts`, `apps/api/src/app.ts`, `apps/api/src/app.test.ts` | web, api | `required-per-app` | web, S03 api | Legacy JWT signing/verification secret; API test mutations are fixtures. |
| `NODE_ENV` | `apps/web/app/locale/i18next.server.ts`, `apps/web/app/utils/url.server.ts`, `apps/web/app/utils/loaders.middleware.ts`, `apps/web/app/utils/stream/emitter.server.ts`, `apps/web/app/utils/session.server.ts`, `apps/web/app/utils/analyticsCookie.server.ts`, `apps/web/app/utils/db/seed/SeedService.ts`, `apps/web/app/utils/data/.server/rootData.ts`, `apps/web/app/routes/admin/**/*.tsx`, `packages/db/src/client.server.ts`, `server/server.ts` | shared, web, api, worker | `production-only` | web, S03 api, S04 worker | Supplied by runtime/platform. `server/server.ts` sets a production default before creating the React Router handler. |
| `APP_REVISION` | `packages/config/src/api.ts`, web/worker health loaders via runtime env | shared, web, api, worker | `production-only` | S03 api, S04 worker, S06 enforcement | Immutable deploy revision injected by image build or runtime platform; defaults to `unknown` locally. |
| `WEB_BUILD_DIRECTORY` | `server/server.ts` | web | `production-only` | web, S06 enforcement | Optional server-runtime override for smoke tests and non-standard runtime layouts; Docker images normally use `apps/web/build`. |
| `PORT` | `server/server.ts`, `apps/api/src/server.ts` | web, api | `production-only` | web, S03 api, S06 enforcement | Platform listener port; web usage is catalog-backed and API usage remains a catalog/exemption follow-up. |
| `HOST` | web listen usage adopted in `server/server.ts` | web | `local-development-only` | S06 enforcement | cataloged and adopted optional Node listen host through `loadWebConfig`; enforcement should keep it platform-owned and non-secret. |
| `DIRECT_URL` | `packages/config/src/catalog.ts` plus commented env examples such as `.env.example` and `.env.production.example` | shared, web, api, worker | `production-only` | S05 docs | No active runtime source read found in scanned TS/TSX; keep as optional Prisma future candidate. |
| `SERVER_URL` | `apps/web/app/utils/url.server.ts` commented code; examples list it commented | web, api | `production-only` | S05 docs | Commented-out URL helper candidate, not active runtime access. |
| `VERCEL_URL` | `apps/web/app/locale/i18next.server.ts` comment, `apps/web/app/utils/url.server.ts` commented code | web | `production-only` | S05 docs | Platform candidate only; no active runtime read. |
| `WEBHOOKS_URL` | `apps/web/app/utils/url.server.ts` | web, api | `optional-provider` | web, S03 api | Public webhook callback override, commonly local tunnel URL. |
| `STRIPE_SK` | `apps/web/app/utils/stripe.server.ts`, `apps/api/src/app.ts`, `apps/web/app/utils/services/authService.ts`, `apps/web/app/utils/api/.server/TenantsApi.ts`, `apps/web/app/utils/data/.server/rootData.ts`, `apps/worker/src/jobs/ai-cost-stripe-submitter.ts`, `apps/worker/src/jobs/ai-cost-reconciliation-bootstrap.ts` | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Server secret; root data only checks test-mode prefix for UI state. Worker uses it for AI-overage meter event submission and reconciliation. |
| `STRIPE_WEBHOOK_SIGNING_SECRET` | `apps/api/src/app.ts` | api | `optional-provider` | S03 api | Stripe webhook signature verification secret. |
| `MAILJET_API_KEY` | `packages/mail/src/mailjet.ts` via env object | api, worker | `optional-provider` | S03 api, S04 worker | Default transactional provider. |
| `MAILJET_FROM_EMAIL` | `packages/mail/src/mailjet.ts` via env object | api, worker | `optional-provider` | S03 api, S04 worker | Default Mailjet sender address. |
| `MAILJET_FROM_NAME` | examples/catalog only | api, worker | `optional-provider` | S05 docs | Example-only optional display name; no active direct source read found. |
| `INTEGRATIONS_CONTACT_FORMSPREE` | `apps/web/app/modules/crm/services/CrmService.ts`, examples/catalog | web | `optional-provider` | S05 docs | Optional CRM contact form endpoint. |
| `CONVERTKIT_APIKEY` | `apps/web/app/modules/crm/services/CrmService.ts`, examples/catalog | web | `optional-provider` | S05 docs | Optional CRM/newsletter provider key; active web CRM usage. |
| `CONVERTKIT_FORM` | `apps/web/app/modules/crm/services/CrmService.ts`, examples/catalog | web | `optional-provider` | S05 docs | Optional CRM/newsletter form id; active web CRM usage. |
| `CONVERTKIT_API_SECRET` | `apps/web/app/modules/crm/services/CrmService.ts`, examples/catalog | web | `optional-provider` | S05 docs | Optional CRM/newsletter subscriber lookup/update secret; active web CRM usage. |
| `ANALYTICS_GA_TRACKING_ID` | `apps/web/app/utils/db/appConfiguration.db.server.ts` | web | `optional-provider` | web | Exposed through app configuration for Google Analytics. |
| `ANALYTICS_TOKEN` | `apps/api/src/app.ts`, `apps/api/src/app.test.ts` | api | `required-per-app` | S03 api | Public analytics endpoint rejects missing/default token. Test mutations are fixtures. |
| `AUTH_RECAPTCHA_SITE_KEY` | `apps/web/app/utils/db/appConfiguration.db.server.ts` | web | `optional-provider` | web | Public reCAPTCHA site key exposed through app configuration. |
| `NOTIFICATIONS_NOVU_API_KEY` | `apps/web/app/modules/notifications/services/.server/NotificationService.ts` | web | `optional-provider` | web | Optional admin diagnostics for the external notification provider; product sends use the internal queue. |
| `AI_GENERATION_MAX_ESTIMATED_INPUT_COST_CENTS` | `apps/web/app/modules/ai-gen/services/ai-generation-guards.server.ts` | web | `optional-provider` | web | Optional guardrail for denying generation requests above the configured estimated input-cost budget. |
| `AI_GENERATION_RATE_LIMIT` | `apps/web/app/modules/ai-gen/services/ai-generation-guards.server.ts` | web | `optional-provider` | web | Optional per-user generation request limit for the in-memory guard window. |
| `AI_GENERATION_RATE_LIMIT_WINDOW_MS` | `apps/web/app/modules/ai-gen/services/ai-generation-guards.server.ts` | web | `optional-provider` | web | Optional generation rate-limit window in milliseconds. |
| `MISTRAL_API_KEY` | `packages/ai/src/providers/mistral.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Primary AI provider key for deployments that select this provider. |
| `MISTRAL_MODEL` | `packages/ai/src/providers/mistral.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Primary Mistral model override; defaults to `mistral-large-latest`. |
| `SCALEWAY_API_KEY` | `packages/ai/src/providers/scaleway.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | AI fallback provider key for deployments that select this provider. |
| `SCALEWAY_MODEL` | `packages/ai/src/providers/scaleway.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Scaleway fallback model override. |
| `SCALEWAY_BASE_URL` | `packages/ai/src/providers/scaleway.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Scaleway Generative APIs base URL; defaults to `https://api.scaleway.ai/v1`. |
| `ALEPH_ALPHA_API_KEY` | `packages/ai/src/providers/aleph-alpha.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Additional AI fallback provider key for deployments that select this provider. |
| `ALEPH_ALPHA_MODEL` | `packages/ai/src/providers/aleph-alpha.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Aleph Alpha fallback model override. |
| `ALEPH_ALPHA_BASE_URL` | `packages/ai/src/providers/aleph-alpha.ts`, examples/catalog; web AI generation imports `@toolctrl/ai` server-side | web, api, worker | `optional-provider` | web, S03 api, S04 worker | Aleph Alpha compatible base URL. |
| `WORKER_ENABLED` | `apps/worker/src/runtime.ts`, `apps/worker/src/health.ts` | worker | `optional-provider` | S04 worker | Worker runtime starts queues only when exactly `true`. |
| `EMAIL_QUEUE_NAME` | `packages/config/src/worker.ts` | worker | `optional-provider` | S04 worker | Optional transactional-email queue-name override; defaults to `toolctrl.email`. |
| `WORKFLOW_QUEUE_NAME` | `packages/config/src/worker.ts` | worker | `optional-provider` | S04 worker | Optional workflow queue-name override; defaults to `toolctrl.workflows`. |
| `WORKFLOW_TRIGGER_EXECUTOR_URL` | `apps/worker/src/jobs/workflow-trigger-http-executor.ts` | worker | `optional-provider` | S04 worker | Optional internal web-runtime origin for `outbox.workflow`; falls back to `APP_URL` or `WEB_ORIGIN`. |
| `WORKFLOW_TRIGGER_EXECUTOR_MODE` | `apps/worker/src/jobs/workflow-trigger-executor-factory.ts`, `apps/worker/src/jobs/workflow-trigger-native-executor.ts` | worker | `optional-provider` | S04 worker | Selects the `outbox.workflow` executor adapter; default `http`, `hybrid` canaries native safe-core execution with HTTP fallback, and `native` is an opt-in safe-core MVP for `event`, `manual`, `if`, `switch`, `doNothing`, `log`, `variable`, `alertUser`, `httpRequest`, plus tenant-scoped `rowGet` and `email` blocks. |
| `WORKFLOW_TRIGGER_EXECUTOR_TIMEOUT_MS` | `apps/worker/src/jobs/workflow-trigger-http-executor.ts` | worker | `optional-provider` | S04 worker | HTTP timeout for the worker-to-web workflow execution bridge. |
| `WORKFLOW_TRIGGER_OUTBOX_ENABLED` | `apps/worker/src/jobs/workflow-trigger-bootstrap.ts` | worker | `optional-provider` | S04 worker | Escape hatch for the general worker's `outbox.workflow` subscriber; set to `false` only for controlled maintenance. |
| `WORKFLOW_TRIGGER_OUTBOX_CONCURRENCY` | `apps/worker/src/jobs/workflow-trigger-bootstrap.ts` | worker | `optional-provider` | S04 worker | BullMQ concurrency for the general worker's `outbox.workflow` subscriber. |
| `WORKFLOW_TRIGGER_OUTBOX_REQUIRED` | `apps/worker/src/jobs/workflow-trigger-bootstrap.ts`, `apps/worker/src/index.ts` | worker | `optional-provider` | S04 worker | Optional fail-loud guard for production general workers; set to `true` once the workflow trigger bridge and Redis must be present. |
| `OUTBOX_DISPATCHER_REQUIRED` | `apps/worker/src/outbox/bootstrap.ts`, `apps/worker/src/outbox/dispatcher.ts`, `apps/worker/src/index.ts` | worker | `optional-provider` | S04 worker | Optional fail-loud guard for production general workers; set to `true` once the outbox dispatcher must be active so queued outbox rows cannot silently pile up. |
| `IMPORT_QUEUE_ENABLED` | `apps/web/app/routes/app.$tenant/internal/imports/submit.tsx`, `apps/worker/src/queues.ts`, `apps/worker/src/health.ts` | web, worker | `optional-provider` | S03 api, S04 worker | Queued imports remain disabled unless import and scan services are wired for the worker. |
| `BULLMQ_REDIS_URL` | `packages/queue/src/connection.ts`, `apps/web/app/routes/app.$tenant/internal/imports/submit.tsx`, `apps/worker/src/health.ts` via env object | web, api, worker | `optional-provider` | web, S03 api, S04 worker, S05 docs | Primary BullMQ Redis URL for web/API enqueue and worker queues; optional unless the worker/queue path is enabled. |
| `REDIS_URL` | `packages/queue/src/connection.ts`, `apps/web/app/routes/app.$tenant/internal/imports/submit.tsx`, `apps/worker/src/health.ts` via env object | web, api, worker | `optional-provider` | web, S03 api, S04 worker, S05 docs | BullMQ fallback only when `BULLMQ_REDIS_URL` is absent; do not document as an independent required key. |
| `BROWSER_RUNTIME_URL` | `packages/config/src/worker.ts`, examples/catalog | api, worker | `optional-provider` | S04 worker, S05 docs | Optional browser-backed worker runtime endpoint. |
| `BROWSER_RUNTIME_API_KEY` | `packages/config/src/worker.ts`, examples/catalog | api, worker | `optional-provider` | S04 worker, S05 docs | Optional browser runtime secret for server-side worker use. |
| `BROWSER_SESSION_TIMEOUT_MS` | `packages/config/src/worker.ts`, examples/catalog | api, worker | `optional-provider` | S04 worker, S05 docs | Optional browser runtime timeout policy. |
| `TOOLCTRL_API_MAINTENANCE_MODE` | `apps/api/src/platform/maintenance/maintenance.ts` | api | `production-only` | S03 api | Set to `1` to serve maintenance responses from non-health API routes. |
| `TOOLCTRL_API_MAINTENANCE_RETRY_AFTER_SECONDS` | `apps/api/src/platform/maintenance/maintenance.ts` | api | `production-only` | S03 api | Optional `Retry-After` seconds value for API maintenance responses. |
| `IPSTACK_API_KEY` | `apps/web/app/utils/helpers/.server/IpService.ts` | api, worker | `optional-provider` | S03 api | IP enrichment provider key. |
| `IPAPIIS_API_KEY` | examples/catalog only in targeted scan | api, worker | `optional-provider` | S05 docs | IP enrichment provider candidate. |
| `PORTAL_SERVER_URL` | `apps/web/app/routes/app.$tenant/__portals/portals.tsx`, examples/catalog | web, api | `optional-provider` | web, S03 api | External portal server URL; current route throws when absent. |
| `PORTAL_SERVER_FLY_TOKEN` | `apps/web/app/modules/domains/services/Domains.server.ts`, examples/catalog | web, api, worker | `optional-provider` | web, S05 docs | Portal automation token candidate. |
| `DEMO_USER` | `apps/web/app/routes/login.tsx`, `packages/config/src/web.ts` | web | `local-development-only` | web | Local login hint in `email:password` shape; ignored outside `NODE_ENV=development`. |
| `SEED_ADMIN_EMAIL` | `apps/web/app/utils/db/seed/SeedService.ts`, examples/catalog | web | `production-only` | web | Production bootstrap admin email for guarded seed runs; local defaults are refused in production. |
| `SEED_ADMIN_PASSWORD` | `apps/web/app/utils/db/seed/SeedService.ts`, examples/catalog | web | `production-only` | web | Production bootstrap admin password for guarded seed runs; local default password is refused in production. |
| `SEED_DEMO_DATA` | `apps/web/app/utils/db/seed/SeedService.ts`, `apps/web/app/modules/users/services/AuthService.ts`, examples/catalog | web | `local-development-only` | web | Local demo seed opt-in; staging may enable it only with `ALLOW_STAGING_DEMO_SEED=true` for disposable CRM SaaS demo data and login. |
| `ALLOW_STAGING_DEMO_SEED` | `apps/web/app/utils/db/seed/SeedService.ts`, `apps/web/app/modules/users/services/AuthService.ts`, examples/catalog | web | `production-only` | web | Guard for disposable staging CRM SaaS demo seed and login; never set on production resources. |
| `SITE_KEY_*` | dynamic API-owned key family; catalog prefix `SITE_KEY_`; examples include `SITE_KEY_EXAMPLE_SITE` | api | `optional-provider` / `dynamic` | S03 api, S06 enforcement | Must be matched by prefix, not enumerated as one literal key. |
| `WEB_ORIGIN` | `apps/api/src/app.ts`, `apps/worker/src/jobs/workflow-trigger-http-executor.ts`, `apps/worker/src/health.ts`, `packages/config/src/catalog.ts` | api, worker | `optional-provider` | S03 api, S04 worker | Cataloged API CORS allow-list override and worker workflow HTTP bridge fallback when `WORKFLOW_TRIGGER_EXECUTOR_URL`/`APP_URL` are absent. |
| `ADMIN_ORIGIN` | `apps/api/src/app.ts`, `packages/config/src/catalog.ts` | api | `optional-provider` | S03 api | Cataloged API-only optional CORS allow-list override. |
<!-- Stable inventory tokens for env-access tests: | `BULLMQ_REDIS_URL` | | `REDIS_URL` | | `SITE_KEY_*` | | `WEB_ORIGIN` | | `ADMIN_ORIGIN` | -->
## Example-file-only keys
The following keys appear in `.env.example`, `.env.local.example`, `.env.production.example`, or `.env.fly.example` but no active direct runtime read was found in the targeted source scan:
| Key | Example files | Catalog status | Follow-up owner | Notes |
| -------------------------------- | ----------------------------------------------------------------------------------- | ----------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `MAILJET_FROM_NAME` | `.env.example`, `.env.local.example`, `.env.production.example`, `.env.fly.example` | `optional-provider` | S05 docs | Optional display name; package mail provider should confirm whether it reads through typed env object only. |
| `INTEGRATIONS_CONTACT_FORMSPREE` | `.env.example`, `.env.production.example`, `.env.fly.example` | `optional-provider` | S05 docs | Keep as optional docs entry unless contact-form source is restored. |
| `IPAPIIS_API_KEY` | `.env.example`, `.env.production.example` | `optional-provider` | S05 docs | Alternative IP enrichment provider candidate. |
| `PORTAL_SERVER_FLY_TOKEN` | `.env.example`, `.env.production.example`, `.env.fly.example` | `optional-provider` | S05 docs | Portal automation token candidate. |
| `SITE_KEY_EXAMPLE_SITE` | commented examples | covered by `SITE_KEY_*` | S03 api, S06 enforcement | Example literal for dynamic prefix matching only. |
| `DIRECT_URL` | commented examples | `production-only` | S05 docs | Prisma direct URL candidate; no active TS/TSX read found. |
| `SERVER_URL` | commented examples | `production-only` | S05 docs | Commented URL helper candidate. |
| `VERCEL_URL` | commented examples | `production-only` | S05 docs | Platform candidate. |
## Deprecated/remove candidates
| Key | Evidence | Recommendation |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AUTH_RECAPTCHA_SECRET_KEY` | Historical catalog tombstone with `deprecated-remove`; no current active source or example usage found. | Keep out of examples/docs unless a later migration reintroduces server-side reCAPTCHA verification. |
| `CRISP_CHAT_WEBSITE_ID` | Active read exists in `apps/web/app/utils/data/.server/rootData.ts` and legacy Fly examples list it. | Not a removal candidate while active source usage remains; either keep cataloged as web optional provider or remove the root-data integration first. |
| `CONVERTKIT_*` example keys | Active web reads remain in `apps/web/app/modules/crm/services/CrmService.ts`. | Keep catalog/examples as web-scoped optional provider config until CRM/newsletter extraction removes or replaces ConvertKit usage. |
## Tests and test-only mutations
`apps/api/src/app.test.ts` mutates `process.env` extensively to exercise API auth, analytics, CORS, and redaction behavior. These keys are test fixtures, not runtime migration targets: `APP_NAME`, `APP_BASE_DOMAIN`, `API_ACCESS_TOKEN`, `JWT_SECRET`, and `ANALYTICS_TOKEN`.
`packages/db/src/index.test.ts` sets a fallback `DATABASE_URL` before importing `prisma.config.ts`; this is also test-only. Later enforcement should allow isolated test mutation helpers while blocking new production runtime direct reads.
## Assumptions and safety notes
- No secret values were copied from `.env*` files; this inventory includes key names and paths only.
- `REDIS_URL` is a BullMQ fallback when `BULLMQ_REDIS_URL` is absent, not an independent required key.
- `SITE_KEY_*` is a dynamic API-owned key family and must be cataloged/enforced by prefix.
- `PORT`, `HOST`, `WEB_ORIGIN`, and `ADMIN_ORIGIN` are cataloged. `PORT` and `HOST` are adopted for the web listener through `loadWebConfig`; `WEB_ORIGIN` and `ADMIN_ORIGIN` are API CORS overrides, and `WEB_ORIGIN` is also the worker workflow bridge fallback after `WORKFLOW_TRIGGER_EXECUTOR_URL` and `APP_URL`.
- Commented source references are recorded as examples/docs follow-up, not active runtime dependencies.
- Where package helpers accept an `env` parameter defaulting to `process.env`, the package remains a migration target even if individual key reads happen through the passed object.
## Follow-up mapping
| Slice | Owner scope | Inventory items |
| --------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| S02 web | React Router/web loaders, sessions, root data, web route direct reads, Node server listen config | `APP_NAME`, `SESSION_SECRET`, routing host/protocol keys, `CRYPTO_SECRET`, `API_ACCESS_TOKEN`, `JWT_SECRET`, `NODE_ENV`, `HOST`, `PORT`, `WEBHOOKS_URL`, Supabase web keys, Stripe keys, OAuth keys, reCAPTCHA site key, Novu web state, `PORTAL_SERVER_URL`, `DEMO_USER`, `SEED_ADMIN_EMAIL`, `SEED_ADMIN_PASSWORD` |
| S03 api | Hono API runtime, API auth/JWT/analytics/CORS, API storage, enqueue/provider settings | `APP_NAME`, routing host/protocol keys, `APP_REVISION`, `API_ACCESS_TOKEN`, `JWT_SECRET`, `ANALYTICS_TOKEN`, `WEB_ORIGIN`, `ADMIN_ORIGIN`, Supabase server keys, Stripe webhook secret, queue Redis keys, `MISTRAL_API_KEY`, `MISTRAL_MODEL`, `SCALEWAY_*`, `ALEPH_ALPHA_*`, `SITE_KEY_*`, API provider keys |
| S04 worker | Standalone worker runtime, worker health, BullMQ Redis, browser runtime settings | `WORKER_ENABLED`, `APP_REVISION`, `APP_URL`, `WEB_ORIGIN`, `API_ACCESS_TOKEN`, `EMAIL_QUEUE_NAME`, `WORKFLOW_QUEUE_NAME`, `WORKFLOW_TRIGGER_EXECUTOR_MODE`, `WORKFLOW_TRIGGER_EXECUTOR_URL`, `WORKFLOW_TRIGGER_EXECUTOR_TIMEOUT_MS`, `WORKFLOW_TRIGGER_OUTBOX_ENABLED`, `WORKFLOW_TRIGGER_OUTBOX_CONCURRENCY`, `WORKFLOW_TRIGGER_OUTBOX_REQUIRED`, `OUTBOX_DISPATCHER_REQUIRED`, `BULLMQ_REDIS_URL`, `REDIS_URL`, `BROWSER_RUNTIME_URL`, `BROWSER_RUNTIME_API_KEY`, `BROWSER_SESSION_TIMEOUT_MS`, `MISTRAL_API_KEY`, `MISTRAL_MODEL`, `SCALEWAY_*`, `ALEPH_ALPHA_API_KEY`, worker-owned provider keys |
| S05 docs | Example and documentation alignment, fallback wording, deprecated/example-only cleanup | Env examples and docs for `BULLMQ_REDIS_URL` as primary, `REDIS_URL` as fallback only when `BULLMQ_REDIS_URL` is absent, browser-runtime docs alignment, web-scoped ConvertKit CRM/newsletter keys, `DIRECT_URL`, `SERVER_URL`, `VERCEL_URL`, `AUTH_RECAPTCHA_SECRET_KEY`, dormant GitHub candidates |
| S06 enforcement | Future direct-read guardrails and drift tests | Prefix support for `SITE_KEY_*`, allow-list for test-only mutations, regression checks for S02-adopted web core keys (`PORT`, `HOST`, core URL/root/session/middleware reads), CORS-origin catalog drift checks for `WEB_ORIGIN` and `ADMIN_ORIGIN`, APP_REVISION catalog checks, no-value leakage checks for inventory docs |