Developer Guide
OpenAPI Generation
http/openapi.ts builds a service's OpenAPI 3 spec from the same route
tables that serve traffic. The spec is never a hand-maintained document:
a route that exists but isn't documented — or vice versa — is impossible
by construction.
The three spec builders
| Function | Input | Produces |
|---|---|---|
rpcSpec(routes) | RpcRoute[] — reads each route's openapi field | paths entries for RPC-style routes |
entityCrudSpec(entity, opts) | entity code + declared ops | the canonical 8-op CRUD path set (meta, list, get, create, update, delete, restore, audit) |
buildOpenApiSpec({info, serverUrl, tags, paths}) | merged paths + metadata | the full { openapi: "3.0.x", ... } spec object |
Routes declare their docs inline — openapi is a field on RpcRoute:
Code
Serving the spec — makeOpenApiHandler
Code
Canonical composition per service
Code
Every service owns one src/openapi.ts (or openapi-route.ts) following
this exact shape — the same const then feeds two consumers:
makeOpenApiHandler→ served live at/api/v1/openapi.jsonbuildDocsPack({ openapi })→ serialized intodist/docs-pack/openapi.json, shipped to the AI KB — so the assistant answers API questions from the service's own runtime spec, not from a stale extracted file
When openapi metadata matters
- Routes without an
openapifield are absent from the spec — the flag is also how you deliberately keep an internal route unpublished. entityCrudSpec'sopslist must match the ops the entity router actually registers; keep them adjacent in the same file.
Last modified on