Skip to content

Align .env.example with the Zod config schema and remove direct process.env reads #573

Description

@devJaja

Summary

The configuration surface has drifted in both directions. 18 keys exist in the Zod schema but not in .env.example. 10 keys exist in .env.example but bypass Zod validation entirely via hand-rolled parseInt. Several more are read directly off process.env in feature code.

Direction 1 — undocumented keys (18)

AUTH_JWT_SECRET                        DB_POOL_MIN
AUTH_ACCESS_TOKEN_TTL_SECONDS          DB_POOL_MAX
AUTH_REFRESH_TOKEN_TTL_SECONDS         DB_POOL_ACQUIRE_TIMEOUT_MS
AUTH_SESSION_MAX_TTL_SECONDS           DB_POOL_HEALTH_CHECK
DB_BACKUP_DIR                          DB_MAINTENANCE_INTERVAL_MS
DB_MAINTENANCE_VACUUM_THRESHOLD        DB_BACKUP_RETENTION_COUNT
ERROR_REGISTRY_MAINTENANCE_INTERVAL_MS REGISTER_RATE_LIMIT_MAX_REQUESTS
ERROR_REGISTRY_CAP_PER_AGENT           HEALTH_PROBE_TIMEOUT_MS

AUTH_JWT_SECRET is the critical one and is tracked as a security issue. The rest include the entire connection-pool configuration, which suggests the pool abstraction was added without its configuration being documented.

Direction 2 — unvalidated keys (10)

These are in .env.example but not in the config schema. The 6 rate-limit keys are parsed by a hand-rolled parseInt with a > 0 fallback (rateLimit.ts:237-244); the 4 Venice cache keys are read straight off process.env (venice/client.ts:75-98).

A typo silently falls back to the default. RATE_LIMIT_PUBLIC_MAX_REQUEST=999999 (missing the S) does not error — it quietly yields 120.

services/featureFlags.ts:44 repeats the pattern for FEATURE_<FLAG> with its own parseInt.

Direction 3 — direct reads in feature code (10+)

SKIP_STELLAR_ACCOUNT_VERIFY  (agents.ts:268)
NODE_ENV                     (agents.ts:278)
ADMIN_AUDIT_DB_PATH          (adminControl.ts)
ADMIN_BACKUP_DIR             (adminControl.ts)
AI_NET_READ_ONLY             (middleware/readOnly.ts)
AI_NET_READ_ONLY_REASON      (middleware/readOnly.ts)
QUALITY_*                    (qualityScorer.ts, 6 keys)
IDEMPOTENCY_TTL_MS           (services/idempotency.ts)
IDEMPOTENCY_CLEANUP_MS       (services/idempotency.ts)

Direction 4 — stale PostgreSQL references

db/pool.ts (424 lines) and .env.example:16 describe the connection as SQLite/PostgreSQL, and db/events.sql:9 explicitly notes the DDL "is not compatible with PostgreSQL". Meanwhile the pool abstraction and four DB_POOL_* keys (min, max, acquire timeout, health check) imply a connection pool — which a single-writer synchronous engine like SQLite does not need. This is unresolved architectural drift, not a docs problem.

Acceptance criteria

  • .env.example and the Zod schema agree in both directions, enforced by a CI test.
  • All 10 hand-parsed environment variables move into the Zod schema.
  • A parseInt fallback that silently defaults is replaced with a validation error, or documented as an intentional default.
  • Direct process.env reads in feature code are moved into the config module, leaving process.env access confined to config, logger, and CLI entry points.
  • A lint rule or test asserts the config surface has no direct process.env readers outside the config module.
  • The PostgreSQL-vs-SQLite question is resolved: either the pool abstraction is justified and the docs corrected, or it is removed as unnecessary for SQLite.
  • DB_POOL_* keys are documented and their effect on the SQLite path is stated explicitly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions