Introduce explicit test/dev/prod environment modes
Nobody has claimed this yet.
- Dominant language
- Jupyter Notebook
- Stars
- 5
- Forks
- 10
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 17
Description
Summary
Apollo doesn't know which environment it's running in. Config is read straight off process.env wherever it's needed, so a test run, a developer's laptop, and production all behave the same way. This issue proposes one explicit APOLLO_ENV mode (test/dev/prod), resolved once at startup, that becomes the single place deciding where the database comes from, whether an encryption key is required, and how strict boot is.
This is the foundation issue. Test hardening is the dependent follow-on and should land second.
The problem
Config gets read ad-hoc all over the place:
clientsDbUrl()resolvesAPOLLO_CLIENTS_DB_URL ?? POSTGRES_URL(platform/src/db/index.ts:18-20)InstanceAuth.init()readsAPOLLO_ENC_KEYand probes the DB (platform/src/auth/instance-auth.ts:114-144)server.tsdecides whether to migrate based purely on whether a clients DB URL is set (platform/src/server.ts:41-50)
Nothing tells the three environments apart, and that gap sits underneath two sharper problems.
1. Tests lean on a human getting it right. The live-DB tests check that a raw env var is set and quietly skip when it isn't (platform/test/db.test.ts:8,13; platform/test/auth/client/store.test.ts:16,20). A fresh clone with POSTGRES_URL pointing at a real database will happily run migrations and write client rows into whatever it points at. There's no notion of "this is a test run, so use a throwaway database and a throwaway encryption key, and never touch a real one."
2. Startup is lax everywhere. A missing clients DB, or a missing or invalid APOLLO_ENC_KEY, only warns and carries on degraded (instance-auth.ts:116-128). That's the right call in dev, but dangerous in prod. There's no global ANTHROPIC_API_KEY fallback by design, so per-client keys are mandatory, which means a prod boot without a reachable clients DB and a valid encryption key should fail hard rather than shrug and carry on.
Proposed concept
Introduce one explicit environment mode, resolved once at startup (from an APOLLO_ENV var with a sensible default) and threaded through config rather than re-derived from scattered process.env reads. The mode is the single place that answers three questions:
| Mode | Database | Encryption key | Startup |
|---|---|---|---|
| test | Dedicated apollo_test (the one CI uses); a real DB is never touched even if POSTGRES_URL/APOLLO_CLIENTS_DB_URL is set |
Generated automatically | n/a |
| dev | Single POSTGRES_URL; warn and carry on if missing |
Optional for boot and for plaintext/NULL clients; required once encrypted clients are involved |
Relaxed: warn and carry on |
| prod | Reachable clients DB required | Valid APOLLO_ENC_KEY required |
Strict: boot fails if either is missing |
A few details that don't fit in the table:
- test mode is TypeScript-only. The Python services read
POSTGRES_URLdirectly and know nothing aboutAPOLLO_ENV, so "test mode never touches a real database" holds for TypeScript only. The Python integration test keeps its own hazard until it's tidied separately (see the Python DB test hygiene follow-up). Don't claim the guarantee covers both stacks. - dev's encryption key isn't silently optional. Provisioning or reading an
enc:v1:client without a stable key should warn at startup and give a clear error at insert or read, rather than writing ciphertext that won't survive a restart. Those details live in the APOLLO_ENC_KEY safety follow-up. - prod has no global key fallback. That's what actually keeps per-client keys mandatory.
This issue is about the idea and where it lives: how the app learns its mode, what each mode means, and the single place in config that everything reads it from. It deliberately leaves out the test database mechanics.
Sequencing
This issue is the foundation and lands first. APOLLO_ENV is read once at startup and becomes the single answer to "where's the database, do we need a key, how strict is boot?"
Test hardening is the second piece and builds on it. Once test mode owns the choice of database, the live-DB suites point at apollo_test and isolate with transactional rollback. Keep this issue minimal and let the test mechanics live there.
This is deliberately the opposite of the earlier framing where test hardening came first. The idea comes first, the mechanics second, which is how mature frameworks derive the test database from the environment mode rather than the other way round.
Acceptance criteria
- A single resolved environment mode (
test/dev/prod) exists, read once at startup from one place rather than worked out again from scatteredprocess.envreads. - The database source, whether an encryption key is required, and startup strictness are all driven by the mode through one place in config, not by ad-hoc checks in
db/index.ts,instance-auth.ts, andserver.ts. - prod boot fails hard when no clients database is reachable or
APOLLO_ENC_KEYis missing or invalid (no silent degradation; documents that there is no global key fallback). - dev keeps today's relaxed behaviour with a single
POSTGRES_URL: warn when something's missing and carry on. - test mode resolves the database to a dedicated
apollo_testand a generated encryption key, and refuses to touch a real database. The test mechanics (rollback isolation, skip check) are left to the Test hardening follow-up. - The mode and what each mode means are documented (env vars, defaults) in the auth and database README and
CLAUDE.md. - References the Test hardening issue as the dependent follow-on (this issue lands first).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading platform/src/db/index.ts, platform/src/auth/instance-auth.ts, and platform/src/server.ts to map the current environment and startup checks. Then review the auth and database README and CLAUDE.md requirements. Done means one startup-resolved test/dev/prod mode drives database selection, key requirements, and boot strictness, with the documented Test hardening follow-up kept separate.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, typescript
- Domain
- authentication, backend, database, documentation
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100