The central contract of http-policy:
Compile policies once; execute them cheaply on every request.
Developer API (immutable builders)
│ policy().cache(...).security(...).when(...)
▼
Normalize eager, at the call site:
│ · header names → RFC 9110 tokens, lowercased
│ · durations parsed once into seconds
│ · structural errors throw immediately (ADR-0003)
▼
Intermediate representation (IR)
│ per-category normalized config (internal)
▼
Validate + Diagnose whole-policy semantic checks at compile():
│ errors aggregate into PolicyCompileError,
│ warnings report once via onDiagnostic/console.warn
▼
Compile freeze everything:
│ · staticHeaders: ordered frozen [name, value] pairs
│ · preflightHeaders: separate 204-response view
│ · notModifiedHeaders: 304 view (entity headers removed)
│ · CORS resolution maps / resolvers
│ · conditional branches fully compiled as sub-policies
▼
Immutable CompiledPolicy ── shared across requests, frameworks, threads
▼
Resolve + apply resolveRequestPolicy(): identity for static policies,
predicate + branch pointer for conditional ones
▼
Framework adapter writes pairs through the framework's native setter
- Immutability. Compiled policies are deep-frozen. Sharing them between requests, routes or concurrent executions cannot corrupt state — verified by dedicated concurrency tests.
- Lazy request state. Overlays exist only after a handler mutates policy; otherwise requests run allocation-free.
- Category ownership. Generated headers own their names over custom headers; merge semantics are explicit per category (see precedence.md).
- No framework leakage. Core depends on nothing and knows nothing about
Express/Fastify/Hono/NestJS; adapters project native requests onto a
minimal
PolicyContext.
src/
├── builder/ PolicyBuilder + section builders (cache/security/cors/etag)
├── ir/ normalized intermediate representation + merge rules
├── compile/ IR → CompiledPolicy lowering + diagnostics
├── runtime/ applyHeaders, resolveRequestPolicy, overlays, CORS/ETag
├── cors/ CORS types and origin strategies
├── security/ CSP & Permissions-Policy serialization
├── etag/ ETag types; RFC 9110 If-None-Match matching
├── duration/ human-readable duration parsing
├── headers/ name/value validation
├── diagnostics/ stable diagnostic codes
└── context.ts framework-independent PolicyContext