- 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
45 lines
2.3 KiB
Markdown
45 lines
2.3 KiB
Markdown
# 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.flags` decorated 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.
|