Strata architecture and SDDMenu
On this page

Analog request-scoped HTTP interceptors

Scope and API

Starting main: 8417d60e040190a6a68c91a96f8380db934908bf.

@strata-sc/analog adds StrataAnalogInterceptor, StrataAnalogInterceptorContext and StrataAnalogNext, configured through the optional RegisterControllersOptions.interceptors array. The array is checked before route registration, copied and frozen. Each registration owns its own snapshot. The context exposes the existing request, route information and request-local onCleanup callback; it does not expose Nitro/H3 internals.

Execution contract

Guards run sequentially before any interceptor. A denial remains the existing safe 401/403 response, runs cleanup, and skips interceptors, factory and handler. When allowed, interceptors run onion-style: A before B, then factory and handler, then B after A. They share the guard/factory request cleanup scope. Cleanup runs once, LIFO and awaited after interceptor unwinding.

An interceptor that returns normally must invoke next() once and wait for downstream settlement. Missing, repeated or concurrent calls are configuration errors; calling next after settlement is rejected. Interceptors may throw before calling next, observe/rethrow downstream errors, or transform returned data. They cannot short-circuit with a cached result. A caught application error that is replaced is consumer-owned policy.

Values flow directly to Nitro. The adapter does not add serialization or wrap values in Response. A pass-through native Response is left intact; a consumer-created replacement follows Web API body and header ownership rules. Do not consume response bodies for logging. Expected validation errors remain safe 400/413/415 responses when rethrown. Unexpected errors are not converted to client errors, and private errors are not placed in public responses.

Evidence and limitations

The focused Analog package suite passes (109 tests), including onion ordering, guard precedence, transformed data, native Response pass-through, exact guard/interceptor/factory LIFO cleanup ordering, malformed/missing/repeated/ concurrent next() handling, and draining detached downstream work before cleanup. Package typecheck passes.

pnpm test:analog passes 86/86 checks on Analog dev and Nitro Node production. The greeting fixture proves the response transformation, and guarded plus Standard Schema validation routes use a pass-through interceptor; existing 24-request validation and authorization checks pass. The separate Cloudflare Pages/workerd qualification passes with an intercepted and transformed greeting and a guarded route. The packed consumer verifies interceptor declarations and runtime with TypeScript 5.9.2; the full-stack packed consumer passes strict TypeScript 6.0.3/5.9.2 checks and Node/local-workerd runtime checks with public and guarded routes wrapped by an interceptor.

The repository build, lint, typecheck, unit/release/performance-tools gates pass. Server Component navigation/defer/server-only/security/request-context/ failure/SSR-response/authorization/dev fixtures pass; both Cloudflare qualification and the full-stack source-packed workerd rehearsal pass. Packed Server Component and full-stack consumers, www/Relay Server Component dogfood, and the Cloudflare site build pass. Entwine 0.5.1 check and build pass. The standalone pnpm --filter @strata-sc/www test:e2e currently fails both tests: the page never sets html[data-app-ready="true"]; no apps/www files are changed by this branch, and the test:www:server-components Playwright suite passes. The earlier Cloudflare run also caught and fixed a stale expected greeting value after the transformation was added; the rerun passes. GitHub Actions results are pending until the branch is pushed. No deployed Cloudflare project or package publication was used. Do not treat fixture evidence as production qualification.

Interceptors do not provide authentication, production tracing, arbitrary short-circuiting, cancellation semantics or a full response-stream lifecycle. M3, real application adoption and Strata 1.0 remain unqualified.

Source: docs/research/analog-http-interceptors.md

Generated by Entwine · Markdown remains the source of truth.