feat: mount module HTTP routes
Phase 5B, pass 2: production API mounting, authorization enforcement, and module-runtime lifecycle integration. apps/api now discovers the installed module inventory exactly once (prepareStartupModuleInventory), composes the platform permission registry from it, starts the module runtime from that same discovered list (startDiscoveredModuleRuntime, never rediscovering), and mounts StartedModuleRuntime's published routes under /api/v1/modules/<module-id> via a new apps/api-owned Hono adapter (module-http-routes.ts). Every module route is protected by the existing requirePermission middleware against the composed registry, state-changing methods additionally require a trusted Origin, OPTIONS remains entirely platform-owned, and a handler that throws, rejects, or returns a non-Response becomes a fixed, sanitized 500 MODULE_HANDLER_FAILED. Module-supplied CORS headers are stripped and every module response is forced to Cache-Control: no-store with Vary: Origin, Cookie. RunningApi shutdown now stops the module runtime between draining the HTTP server and closing the shared pool, and every startup failure path stops the runtime and/or closes the pool before propagating, without masking the original failure. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
e296e083ec
commit
dfaf324a65
@@ -240,11 +240,20 @@ connection, authorization store, grant/platform-owner state, storage, jobs, conf
|
||||
a framework-specific request context, or a raw Better Auth session. The full query string remains
|
||||
available through `Request.url`; there is no separate query or body abstraction.
|
||||
|
||||
This pass only defines, validates, and collects routes into `StartedModuleRuntime`'s immutable route
|
||||
snapshot — Core never invokes a handler here. Mounting routes into the production `apps/api` Hono
|
||||
application, enforcing each route's permission through `requirePermission`, applying
|
||||
`requireTrustedOrigin`, mapping handler errors to sanitized responses, and wiring this into
|
||||
`startApi`'s production lifecycle are later work.
|
||||
Core defines, validates, and collects routes into `StartedModuleRuntime`'s immutable route
|
||||
snapshot — it never invokes a handler itself. `apps/api` mounts that exact snapshot into production
|
||||
at startup, under the `/api/v1/modules/<module-id>` prefix described above: every route is enforced
|
||||
through the identical `requirePermission` middleware Core's own routes use, a state-changing method
|
||||
(`POST`/`PUT`/`PATCH`/`DELETE`) additionally requires a trusted `Origin` before authorization ever
|
||||
runs, and a handler that throws, rejects, or returns something other than a `Response` becomes a
|
||||
fixed, sanitized `500 {"code":"MODULE_HANDLER_FAILED"}` — never the caught value, a stack, the
|
||||
route's path, its permission id, or the module id. The platform remains the sole owner of CORS and
|
||||
caching for every module route: a handler-supplied CORS-control header is stripped, and every
|
||||
module response is forced to `Cache-Control: no-store` with `Vary: Origin, Cookie` (in addition to
|
||||
any of the handler's own legitimate `Vary` values) until a dedicated cache-policy contract exists —
|
||||
deliberately conservative, since even a public-baseline handler still receives an authorized
|
||||
principal and may personalize its response. See [API](../development/api.md#module-http-routes) for
|
||||
the full production mounting, enforcement, and error-response contract.
|
||||
|
||||
## Drizzle schema definition
|
||||
|
||||
|
||||
Reference in New Issue
Block a user