Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
# `build-routes.ts` — OpenAPI route surface for the event-bus plugin
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Builds the three `PluginRouteEntry` objects the plugin mounts on the
host Hono app + `OpenAPIRegistry` via `definePluginRoutes`. The
surface (`POST /publish`, `GET /subscriptions`,
`DELETE /subscriptions/:id`) gives operators an HTTP-only path to
exercise the event bus — useful for cross-language producers, smoke
tests, and admin tooling. Per-tenant scoping flows through the same
`extractTenantId` helper used by the request middleware so the HTTP
and in-process surfaces stay consistent.
## Features
- 3 routes: publish, list, delete.
- All routes typed via `RouteBuilder` with Zod request/response
schemas — the OpenAPI doc the host serves at `/openapi.json`
advertises every shape with full inference.
- Auth gating is installed by the plugin's `onInit` at the
sub-path level (`app.use(routePrefix + "/*", requireAuth())`),
because `RouteBuilder` does not own a `.middleware(...)` slot.
- DELETE returns HTTP 404 for both unknown ids AND cross-tenant
attempts (the `TENANT_MISMATCH` swallow is deliberate — exposing
the distinction would leak id ownership across tenants).
## Usage: Basic
```ts
import { definePluginRoutes } from "@suaveplan/api-openapi";
import { buildRoutes } from "@suaveplan/api-plugin-event-bus/routes/build-routes";
const entries = buildRoutes({
service: eventBusService,
tenantIsolation: true,
});
definePluginRoutes(entries, {
app,
registry: openAPIRegistry,
pluginName: "event-bus",
});
```
## Usage: Advanced
```ts
import { buildRoutes } from "@suaveplan/api-plugin-event-bus/routes/build-routes";
// Mount under a custom prefix by remapping each entry's path before
// handing the array to definePluginRoutes.
const prefix = "/internal/bus";
const entries = buildRoutes({
service,
tenantIsolation: true,
}).map((e) => ({
...e,
route: { ...e.route, path: `${prefix}${e.route.path}` },
}));
```
## API Reference
### `buildRoutes(options: BuildRoutesOptions): PluginRouteEntry[]`
Returns 3 entries:
1. `POST /publish` — body: `PublishBodySchema`; response:
`successResponse(PublishResultSchema)`.
2. `GET /subscriptions` — response: `successResponse(SubscriptionListSchema)`.
3. `DELETE /subscriptions/{id}` — params: `UnsubscribeParamsSchema`;
response: `successResponse(UnsubscribeResultSchema)`. Returns 404
for both unknown ids AND foreign tenants.
### `interface BuildRoutesOptions`
`{ service: EventBusService; tenantIsolation: boolean }`.
## Implementation Notes
- The handlers parse the request body via `PublishBodySchema.parse`
directly rather than relying on Hono's `c.req.valid()` so the
validation flow is identical when the host is using a stripped-down
test harness without the full OpenAPI middleware chain.
- The publish handler clones `c.req.raw` before reading the body so
any downstream middleware that re-reads the request keeps working.
- The auth gate is installed by the plugin's `onInit`, NOT here. This
keeps `buildRoutes` pure — it has no opinion on auth, allowing test
harnesses to mount the routes without standing up `api-plugin-auth`.
- The 404 mapping for `TENANT_MISMATCH` is deliberate — exposing the
difference between "not found" and "found but not yours" would
leak subscription-id ownership across tenants.