- request_id generated or sanitized-propagated on every request (x-request-id)
- structured JSON logging (pino), one correlated line per request, injectable logger
- error envelope v2 { error: { statusCode, code, message, details? }, requestId }
- 5xx messages always generic; stack traces stay in server logs only
- explicit parseJson (zod) input validation hook at the API layer
- README HTTP contract section; deps justified in spec/tech.md
- all gates approved; verify.sh green
23 lines
1.7 KiB
Markdown
23 lines
1.7 KiB
Markdown
# Architect — F-003 HTTP foundation and request context
|
|
|
|
done -> work/artifacts/F-003/architect.md
|
|
|
|
## Deliverables
|
|
- specs/F-003-http-foundation/SPEC.md
|
|
- specs/F-003-http-foundation/DESIGN.md
|
|
- specs/F-003-http-foundation/TASKS.md
|
|
- specs/F-003-http-foundation/TESTS.md
|
|
|
|
## Key decisions
|
|
1. **pino** for JSON structured logging: Fastify ecosystem standard, fast, boring. Fastify's own logger stays OFF (`logger: false`); logging happens through explicit onRequest/onResponse hooks so there is exactly one log line per request and zero hidden log paths.
|
|
2. **zod** for the input validation hook: explicit `parseJson(schema, body)` calls inside handlers. No decorators, no magic binding. F-003 ships the hook; first real consumer is F-005 identity.
|
|
3. **request_id policy**: propagate incoming `x-request-id` only when it matches `^[A-Za-z0-9._-]{1,128}$` (header-injection defense); otherwise `crypto.randomUUID()`. Response header `x-request-id` on every response; error envelopes also embed requestId.
|
|
4. **Error envelope v2** (additive): `{ error: { statusCode, code, message }, requestId }`. Codes: NOT_FOUND, VALIDATION_ERROR, INTERNAL_ERROR, or upstream Fastify error codes for known 4xx. >=500 always answers the generic `Internal Server Error`; stack goes to logs tagged with requestId, never to the client.
|
|
5. **Logger injection**: `buildApp({ logger? })` — tests capture logs through an in-memory destination. No transports, no env sniffing in tests.
|
|
|
|
## Boundaries
|
|
- Cross-cutting code lives in `shared` and `infrastructure/logging`; composition wiring only in `src/app`. Modules (health) untouched.
|
|
|
|
## Open risks
|
|
- Envelope change touches F-001 test expectations (additive; tests will be updated in build).
|