Skip to content

docs: add the environment variable reference - #606

Closed
jarik2014 wants to merge 1 commit into
codebestia:devfrom
jarik2014:docs/542-environment-variables
Closed

jarik2014 wants to merge 1 commit into
codebestia:devfrom
jarik2014:docs/542-environment-variables

Conversation

@jarik2014

Copy link
Copy Markdown

Closes #542

Adds docs/environment-variables.md, a reference for every environment variable the three services read: apps/backend, apps/web and apps/ai_agent.

What the document contains:

  • A table of the variables apps/backend/src/config.ts validates at boot. A missing or malformed value there prints the offending names and exits 1, so these fail loudly, and I noted that PORT is required by the schema even though index.ts carries an unreachable ?? 3001 fallback.
  • Separate tables for the variables read lazily at the point of use (transport and origins, limits/GC/timing, the RATE_LIMIT_<BUCKET> overrides, messaging), each with the file that reads it, whether it is required, its in-code default, and the failure mode — including the ones that fail silently, like a malformed RATE_LIMIT_* override being ignored with a warning, or FIRST_CONTACT_HOUR_LIMIT=abc parsing to NaN and removing the limit.
  • A secrets table (JWT_SECRET, DATABASE_URL, REDIS_URL, the object-store keys, VAPID_PRIVATE_KEY, OPENAI_API_KEY) with an explicit statement that they must never be committed, and a note that only placeholders and the local MinIO throwaway credentials may appear in .env.example.
  • The NEXT_PUBLIC_* section states plainly that those values are substituted at build time, inlined into the bundle and therefore public and not rotatable without a rebuild. NEXT_PUBLIC_AUTH_TOKEN is called out separately: it is a bearer token in a public bundle.
  • Three .env.example names that no code reads (RPC_URL, PROPOSALS_CONTRACT_ID, XMTP_ENV), plus the names the backend reads but .env.example omits (STELLAR_RPC_URL, GROUP_TREASURY_CONTRACT_ID, the object-store and GC/limit overrides, and every NEXT_PUBLIC_*).
  • Edge notes: the schema also declares unused S3_* aliases and an IDEMPOTENCY_TTL_SECONDS that nothing consumes; infra/docker-compose.yml sets container-level POSTGRES_*/MINIO_* only; scripts/loadtest is argument-driven.

Verification. A throwaway script (kept outside the repo) extracts names from the code, from .env.example and from the tables in the new document, then compares all three directions. It reports 88 names read by code, 31 names in .env.example, 91 distinct names documented. Lists (b) and (c) are empty; the 60 names in (a) are the ones the document adds beyond .env.example, and the three names in (d) are the ones the document flags as read by nothing.

Commands used to find the reads:

grep -rn "process\.env\." --include=*.ts --include=*.tsx --include=*.js --include=*.mjs --include=*.cjs --include=*.py apps scripts infra src
grep -rn "process\.env\["  --include=*.ts --include=*.tsx --include=*.js apps scripts src   # bracket form
grep -rn "source\[" apps/backend/src                                            # helper reads (envValue/source[name])
grep -rn "os\.environ\|os\.getenv" apps/ai_agent                                # python service

Full output of the throwaway script, unedited:

=== commands used to find the reads ===
grep -rn "process\.env\." --include=*.ts --include=*.tsx --include=*.js --include=*.mjs --include=*.cjs --include=*.py apps scripts infra src
grep -rn "process\.env\["  --include=*.ts --include=*.tsx --include=*.js apps scripts src   # bracket form
grep -rn "source\[" apps/backend/src                                            # helper reads (envValue/source[name])
grep -rn "os\.environ\|os\.getenv" apps/ai_agent                                # python service

names read by code (test fixtures excluded): 88
names declared in .env.example:              31
backticked names in docs/environment-variables.md: 91
table rows in docs/environment-variables.md: 99

(a) in code but missing from .env.example:
    APP_ENV   <- apps/backend/src/lib/transportSecurity.ts:44
    DEVICE_GC_INTERVAL_MS   <- apps/backend/src/services/deviceGc.ts:46
    DEVICE_STALE_AFTER_DAYS   <- apps/backend/src/services/deviceGc.ts:42
    ENVELOPE_DELIVERED_RETENTION_DAYS   <- apps/backend/src/services/envelopeGc.ts:23
    ENVELOPE_GC_INTERVAL_MS   <- apps/backend/src/services/envelopeGc.ts:37
    ENVELOPE_MAX_AGE_DAYS   <- apps/backend/src/services/envelopeGc.ts:30
    ENVELOPE_TTL_SECONDS   <- apps/backend/src/routes/sync.ts:12
    FILE_GC_INTERVAL_MS   <- apps/backend/src/services/fileCleanup.ts:22
    FILE_HARD_DELETE_GRACE_MS   <- apps/backend/src/services/fileCleanup.ts:29
    FIRST_CONTACT_HOUR_LIMIT   <- apps/backend/src/services/rateLimit.ts:96
    GROUP_INVITE_HOUR_LIMIT   <- apps/backend/src/services/rateLimit.ts:97
    LOCAL_STORAGE_DIR   <- apps/backend/src/lib/localObjectStore.ts:25
    LOG_LEVEL   <- apps/backend/src/lib/logger.ts:12
    MAX_ENVELOPE_SIZE   <- apps/backend/src/services/rateLimit.ts:23
    MAX_PAYLOAD_SIZE   <- apps/backend/src/services/rateLimit.ts:14
    NEXT_PUBLIC_API_URL   <- apps/web/src/components/chat/NewConversationModal.tsx:6
    NEXT_PUBLIC_AUTH_TOKEN   <- apps/web/src/lib/auth.tsx:24
    NEXT_PUBLIC_BACKEND_URL   <- apps/web/src/hooks/useSocket.ts:16
    NEXT_PUBLIC_NETWORK   <- apps/web/src/components/chat/TransferCard.tsx:12
    NEXT_PUBLIC_NETWORK_PASSPHRASE   <- apps/web/src/lib/soroban.ts:19
    NEXT_PUBLIC_SOCKET_URL   <- apps/web/src/hooks/useSocket.ts:15
    NEXT_PUBLIC_SOROBAN_RPC_URL   <- apps/web/src/lib/soroban.ts:18
    NEXT_PUBLIC_TOKEN_TRANSFER_CONTRACT   <- apps/web/src/lib/soroban.ts:21
    NEXT_PUBLIC_VAPID_PUBLIC_KEY   <- apps/web/next.config.ts:5
    NODE_ENV   <- apps/backend/src/app.ts:50
    PENDING_UPLOAD_TTL_MS   <- apps/backend/src/services/fileCleanup.ts:36
    PORT   <- apps/backend/src/config.ts:16 (boot-validated schema)
    PREKEY_CONSUMED_RETENTION_DAYS   <- apps/backend/src/services/deviceGc.ts:32
    PREKEY_UNCONSUMED_MAX_AGE_DAYS   <- apps/backend/src/services/deviceGc.ts:37
    RATE_LIMIT_AUTH_CHALLENGE   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${auth_challenge} template)
    RATE_LIMIT_AUTH_VERIFY   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${auth_verify} template)
    RATE_LIMIT_DEVICE_LINK_CHALLENGE   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${device_link_challenge} template)
    RATE_LIMIT_DEVICE_LINK_VERIFY   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${device_link_verify} template)
    RATE_LIMIT_DISABLED   <- apps/backend/src/config/rateLimits.ts:180
    RATE_LIMIT_FILE_DOWNLOAD   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${file_download} template)
    RATE_LIMIT_GLOBAL_IP   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${global_ip} template)
    RATE_LIMIT_KEY_BUNDLE   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${key_bundle} template)
    RATE_LIMIT_KEY_BUNDLE_DAILY   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${key_bundle_daily} template)
    RATE_LIMIT_PUSH_SUBSCRIBE   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${push_subscribe} template)
    RATE_LIMIT_SOCKET_ASK_ASSISTANT   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${socket_ask_assistant} template)
    RATE_LIMIT_SOCKET_DEFAULT   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${socket_default} template)
    RATE_LIMIT_SOCKET_SEND_MESSAGE   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${socket_send_message} template)
    RATE_LIMIT_SOCKET_TYPING   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${socket_typing} template)
    RATE_LIMIT_UPLOAD_BYTES_DAILY   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${upload_bytes_daily} template)
    RATE_LIMIT_UPLOAD_SLOT   <- apps/backend/src/config/rateLimits.ts (RATE_LIMIT_${upload_slot} template)
    REPLAY_PROTECTION_TTL_SECONDS   <- apps/backend/src/services/replay-protection.service.ts:16
    S3_ACCESS_KEY_ID   <- apps/backend/src/config.ts:23 (boot-validated schema)
    S3_BUCKET   <- apps/backend/src/config.ts:25 (boot-validated schema)
    S3_ENDPOINT   <- apps/backend/src/config.ts:21 (boot-validated schema)
    S3_FORCE_PATH_STYLE   <- apps/backend/src/config.ts:26 (boot-validated schema)
    S3_REGION   <- apps/backend/src/config.ts:22 (boot-validated schema)
    S3_SECRET_ACCESS_KEY   <- apps/backend/src/config.ts:24 (boot-validated schema)
    SOCKET_BUFFER_THRESHOLD   <- apps/backend/src/services/backpressure.ts:5
    SOCKET_EVENT_MAX_AGE_MS   <- apps/backend/src/socket/dispatcher.ts:14
    SOCKET_EVENT_MAX_FUTURE_SKEW_MS   <- apps/backend/src/socket/dispatcher.ts:16
    SOCKET_RATE_LIMIT_PER_SEC   <- apps/backend/src/config/rateLimits.ts:155
    SOCKET_SHED_THRESHOLD   <- apps/backend/src/services/backpressure.ts:14
    STELLAR_RPC_URL   <- apps/backend/src/index.ts:454
    STORAGE_ENDPOINT   <- apps/backend/src/lib/localObjectStore.ts:29
    SYNC_PAGE_SIZE   <- apps/backend/src/routes/sync.ts:14

(b) in .env.example but NOT documented in the table:

(c) documented but absent from both code and .env.example:

(d) in .env.example but not read by code (dead/planned):
    PROPOSALS_CONTRACT_ID
    RPC_URL
    XMTP_ENV

names read only by test fixtures (not documented on purpose):
    CONTRACT123

RESULT: PASS - every .env.example name is documented; every documented name exists in code/.env.example

Docs only — no code, config or lockfile changes.


Retargeted to dev — the previous PR (#604) was auto-closed because contributor PRs must merge into dev, not main.

@codebestia codebestia closed this Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants