Current guidance for packages/kirincode/src/server/routes/instance/httpapi.
Use HttpApiBuilder.group(...) for normal JSON and streaming HTTP API
endpoints. Yield stable services once while building the handler layer,
then close over those services in endpoint implementations.
export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session", (handlers) =>
Effect.gen(function* () {
const session = yield* Session.Service
return handlers.handle("list", () => session.list())
}),
)
Use raw HttpRouter only for routes that do not fit the request/response
HttpApi model, such as WebSocket upgrades or catch-all fallback routes.
Do not rebuild stable layers inside request handlers. Provide stable services at the route/layer boundary and use request-level provisioning only for request-derived context.
Expected service errors should be mapped at the handler boundary to endpoint-declared public HTTP errors. Keep one-off mappings inline. Extract small helpers when the same mapping repeats.
Generic middleware should not become a domain-error mapper. It should handle cross-cutting concerns and final unknown-defect fallback.
Public JSON errors should be explicit schema contracts declared on each
endpoint or group. Built-in HttpApiError.* is fine only when its generated
body is intentionally the public wire shape.
Preserve existing { name, data } error bodies until a deliberate breaking
API change.
public.ts still owns SDK/OpenAPI compatibility transforms. Shrink those
transforms by tightening source schemas one workaround at a time.
When an OpenAPI-visible source schema changes: