- loadConfig: pure over env object, accumulates all problems, names var names only - DATABASE_URL now required at startup; PORT/HOST/LOG_LEVEL/NODE_ENV/REDIS_URL defaulted - flags module behind FeatureFlagProvider; unknown flags OFF; runtime setEnabled (no redeploy) - buildApp decorates app.flags; server.ts fail-fast before app boot - tests caught and fixed flag-store case-normalization bug before gates - zero new dependencies; all gates approved; verify.sh green
2.3 KiB
2.3 KiB
Implementer — F-004 Typed config and feature flags
done -> work/artifacts/F-004/implementer.md
Files created
- src/infrastructure/config/config.ts (loadConfig pure over env object; ConfigError accumulates all problems; names var names only)
- src/infrastructure/config/tests/config.test.ts (8 tests)
- src/modules/flags/domain/feature-flag-store.ts (FeatureFlagProvider + InMemoryFeatureFlagStore + createFlagStore)
- src/modules/flags/index.ts (module public API)
- src/modules/flags/tests/feature-flag-store.test.ts (5 tests)
- src/app/tests/config-flags.test.ts (2 composition tests: default OFF, runtime flip without redeploy)
Files modified
- src/app/build-app.ts: optional flags dep;
app.flagsdecorated on the instance (typed via module augmentation) - src/infrastructure/http/server.ts: loadConfig fail-fast before anything starts; typed port/host/logLevel; flags seeded from FLAG_* env
- .env.example: REDIS_URL + FLAG_EXAMPLE_FEATURE example
- README.md: Configuration section
API changes
- Server now REQUIRES DATABASE_URL at startup (fail-fast; intentional per spec).
Bug found by tests during build (fixed before gates)
- Flag store constructor did not lowercase keys while isEnabled lowercased lookups -> case-insensitive seed test failed. Fixed by normalizing keys in the constructor. Regression test retained.
Tests passed (evidence)
npm run lint -> OK
npm run lint:boundaries -> Boundary check OK: 22 file(s) checked (flags module imports nothing outside its subtree)
npm run typecheck -> exit 0
npm run build -> exit 0
npm test -> 9 files passed, 2 skipped (integration without DB); 38 passed | 6 skipped
npm run test:integration-> 2 files, 6 passed (no regression)
live smoke:
env -u DATABASE_URL node dist/.../server.js -> "Invalid configuration:\n- DATABASE_URL is required", exit 1 (AC1)
with DATABASE_URL + FLAG_EXAMPLE_FEATURE=true -> health=200, "HTTP server listening"
./scripts/verify.sh -> exit 0
Known limitations
- No admin endpoint to flip flags yet (scope out); store API is runtime-mutable so the first consumer only adds transport.
- Flags live in memory: restart reseeds from env (documented as expected; persistence is a later ticket if needed).
Follow-up work
- F-005 identity consumes config.databaseUrl through the pool and can guard risky paths via app.flags.