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
@@ -61,12 +61,25 @@ enforceable and grantable through the exact same `requirePermission` middleware
|
||||
claimable by a module. `pnpm doctor` and `pnpm modules:validate` both validate permission
|
||||
composition. Installing, removing, or editing a module currently requires an API restart; removing
|
||||
one makes its permission unavailable to new checks and new grants without deleting or revoking any
|
||||
historical grant or audit row. Module HTTP route registration and relationship-derived grant
|
||||
creation remain later work. See
|
||||
historical grant or audit row. See
|
||||
[Authorization](docs/development/authorization.md#module-permission-composition),
|
||||
[Module development](docs/module-development/README.md), and
|
||||
[ADR 0014](docs/architecture/decisions/0014-module-permission-declarations-and-platform-registry.md).
|
||||
|
||||
Phase 5B mounts a module's own HTTP routes in production. A module registers framework-neutral
|
||||
Fetch (`Request`/`Response`) route handlers during its existing `register` hook; Core collects them
|
||||
into an immutable snapshot alongside its capabilities, and `apps/api` discovers modules exactly
|
||||
once, starts the module runtime from that same discovered inventory, and mounts its published
|
||||
routes under `/api/v1/modules/<module-id>` — after every module has registered and started
|
||||
successfully, so no request can reach a module before startup completes. Every route is enforced
|
||||
through the identical `requirePermission` middleware and composed permission registry Core's own
|
||||
routes use (a module can never supply its own baseline), state-changing methods require a trusted
|
||||
`Origin`, and a handler failure or non-`Response` return becomes a fixed, sanitized `500` — never a
|
||||
raw error, stack, path, or permission id. Relationship-derived grant creation remains later work.
|
||||
See [API](docs/development/api.md#module-http-routes),
|
||||
[Module development](docs/module-development/README.md#http-routes), and
|
||||
[ADR 0014](docs/architecture/decisions/0014-module-permission-declarations-and-platform-registry.md#deferred).
|
||||
|
||||
## Quick start
|
||||
|
||||
Prerequisites: Node.js 24 LTS, pnpm 11.12, and Docker with Compose.
|
||||
|
||||
Reference in New Issue
Block a user