docs: record module HTTP architecture
Phase 5B, pass 3: adds ADR 0015 recording the durable module HTTP
routing and production runtime lifecycle architecture pass 1 and pass
2 implemented, extending ADR 0006 and ADR 0014 without superseding
either. Adds narrow cross-reference notes to both, and to the ADR
index, pointing at ADR 0015 for the work they deferred, while
preserving their historical text and accepted status.
Corrects stale forward-looking "pass 2"/future-tense language left
over from pass 1 in core/src/modules/runtime.ts and
packages/contracts/src/module-http.ts (comment-only; production
behavior unchanged), and a shutdown-lifecycle description in
docs/development/testing.md that predated the module-runtime-stop
step pass 2 added between draining the HTTP server and closing the
pool.
Full audit against origin/main...HEAD found the architecture,
contract, startup ordering, routing, authorization/origin
enforcement, and PostgreSQL integration coverage from passes 1-2
sound; the one concrete defect found (Vary-header merge producing an
invalid "*, Origin, Cookie" combination and case-sensitive duplicate
tokens) was already fixed with focused regression tests in a separate
commit (bf76f4e), not amending either checkpoint commit.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
bf76f4e006
commit
1285c90618
@@ -26,7 +26,8 @@ const parameterSegmentPattern = /^:[a-z][a-zA-Z0-9]*$/u;
|
||||
|
||||
/**
|
||||
* A module-local route path — never the production-mounted `/api/v1/modules/<module-id>` path a
|
||||
* caller actually sends (pass 2). Not branded (unlike `PermissionId`): like `PackageRelativePath`,
|
||||
* caller actually sends (`apps/api/src/module-http-routes.ts` owns that mapping). Not branded
|
||||
* (unlike `PermissionId`): like `PackageRelativePath`,
|
||||
* this is a validated location, not an opaque cross-system identifier. `"/"` is the module root;
|
||||
* any other canonical path begins with `/`, never ends with `/`, and is composed only of lowercase
|
||||
* kebab-case static segments or single `:parameterName` segments — no empty or repeated slashes, no
|
||||
@@ -126,7 +127,8 @@ export function moduleRouteShapeKey(method: ModuleHttpMethod, path: ModuleRouteP
|
||||
* What a module's route handler receives about the caller and the match — never a database
|
||||
* connection, authorization-store, grant-management, storage, jobs, configuration, secrets, the
|
||||
* Hono `Context`, or a raw Better Auth session. `principal` is already authorized by the time a
|
||||
* handler runs (pass 2 mounts and enforces); this pass never invokes a handler at all.
|
||||
* handler runs: `apps/api/src/module-http-routes.ts` mounts and enforces every route before ever
|
||||
* invoking its handler; this contracts-layer module never invokes a handler itself.
|
||||
*/
|
||||
export interface ModuleRouteHandlerContext {
|
||||
readonly moduleId: ModuleId;
|
||||
@@ -174,8 +176,8 @@ export interface ModuleHttpRouteRegistrar {
|
||||
|
||||
/** One published route in `StartedModuleRuntime`'s immutable route snapshot — the same validated
|
||||
* fields as `ModuleRouteDefinition` plus the owning module's ID, which the production mount prefix
|
||||
* (pass 2) uses to keep two modules' routes from ever colliding regardless of their own local
|
||||
* paths. */
|
||||
* (`/api/v1/modules/<module-id>`, `apps/api/src/module-http-routes.ts`) uses to keep two modules'
|
||||
* routes from ever colliding regardless of their own local paths. */
|
||||
export interface RegisteredModuleHttpRoute {
|
||||
readonly moduleId: ModuleId;
|
||||
readonly method: ModuleHttpMethod;
|
||||
|
||||
Reference in New Issue
Block a user