Qirava DMS docs
OpenAPI 3.1 projection: /api/spec/openapi
GET /api/spec/openapi returns a hand-written, zero-dependency OpenAPI 3.1 document describing exactly the real HTTP routes the system worker serves — run QQL, batch QQL, log in, read the catalog, read this spec, and drain. It is not a generic description: a drift test asserts the documented paths equal the routes the worker actually registers, and the ErrorEnvelope.error.code enum is derived from code_status (the single source of truth) rather than a hand-maintained literal list, so the spec can never fall out of sync with the wire contract. This page documents the projection's structure, every operation, the shared component schemas, and the drift guarantees, transcribed from src/functions/api/openapi.rs.
What the projection is#
This is a real OpenAPI 3.1 document you can feed to Swagger UI, a code generator, or any OpenAPI tool. It models only the routes the system worker registers, references shared OkEnvelope / ErrorEnvelope component schemas, and uses the eight stable error codes as the enum for the error code field.
It is built by build_openapi() from 'static route metadata plus code_status, built once at system-worker construction (via register_api_openapi_handler), cached as bytes, and served verbatim — zero per-request cost. Like the catalog, it documents method/path/request-shape/response-shape only; it reads no row data and reflects no request body.
- openapi
- "3.1.0" — the
OPENAPI_VERSIONconstant. - info.title
- "Qirava DMS HTTP API".
- info.version
- "1" — mirrors the catalog's
API_VERSION. - info.description
- "The HTTP surface of the Qirava DMS system worker: run QQL, batch QQL, log in, and read the API catalog. Every response is the uniform {error,data,root} envelope."
Fetching the projection#
Request
GET /api/spec/openapi HTTP/1.1
Host: localhostResponse
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"error":null,"data":{"openapi":"3.1.0","info":{"title":"Qirava DMS HTTP API","version":"1","description":"..."},"paths":{...},"components":{"schemas":{...}}},"root":{"took_us":<int>,"request_id":"<hex>"}}Output
// Route api.openapi (GET /api/spec/openapi, handler system.api_openapi)
// is OutputKind::RawJson, so the OpenAPI document is embedded
// UNESCAPED as the envelope's `data` value.The documented routes#
The paths object groups operations by path (a path may carry several methods — /api/qql carries both POST and GET). These mirror the Routes the system worker registers in src/workers/mod.rs.
| Method | Path | operationId | Request body | 2xx schema |
|---|---|---|---|---|
| POST | /api/qql | runQql | text/plain raw QQL string | OkEnvelope |
| GET | /api/qql | runQqlGet | none (uses `q` query param) | OkEnvelope |
| POST | /api/qql/batch | runQqlBatch | application/json array of QQL strings | BatchResponse |
| POST | /api/login | login | application/json LoginRequest | OkEnvelope |
| GET | /api/spec | getCatalog | none | OkEnvelope |
| GET | /api/spec/openapi | getOpenApi | none | OkEnvelope |
| POST | /admin/drain | drain | none | OkEnvelope |
A real operation object#
Request
// GET /api/spec/openapi -> data.paths["/api/qql"]["post"]Response
{
"operationId": "runQql",
"summary": "Run one QQL statement",
"description": "Execute a single QQL statement. The request body IS the raw query text (no JSON wrapper). Returns the uniform envelope.",
"requestBody": {
"required": true,
"description": "The raw QQL statement text.",
"content": {
"text/plain": {
"schema": { "type": "string", "example": "SELECT * FROM users LIMIT 20" }
}
}
},
"responses": {
"200": {
"description": "Success.",
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/OkEnvelope" } } }
},
"default": {
"description": "Error — the HTTP status mirrors the stable error code.",
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEnvelope" } } }
}
}
}Note the QQL POST body is plain text (text/plain) — the raw query, not a JSON wrapper. The batch route takes an application/json array of QQL strings (minItems 1).
Shared component schemas#
components.schemas holds four shared schemas referenced throughout the document: OkEnvelope, ErrorEnvelope, BatchResponse, and LoginRequest. Modelling the envelope once and $ref-ing it everywhere means a generated client gets one envelope type.
- OkEnvelope
- Object requiring
error/data/root.erroris null;datais an untyped result ("The function result (rows, a record, or a value).");rootis an object with optional integertook_us, stringrequest_id, and integercount. - ErrorEnvelope
- Object requiring
error/data/root.erroris{ code, message }wherecodeis a string with the eight-value enum;datais null;rootis the same root object. - BatchResponse
- An array whose items are
oneOfOkEnvelope/ErrorEnvelope— one envelope per submitted statement, in submission order. - LoginRequest
- Object requiring
usernameandpassword(both strings).
Request
// GET /api/spec/openapi -> data.components.schemas.ErrorEnvelopeResponse
{
"type": "object",
"required": ["error", "data", "root"],
"properties": {
"error": {
"type": "object",
"required": ["code", "message"],
"properties": {
"code": {
"type": "string",
"enum": ["ok","workers_busy","not_found","forbidden","bad_request","rate_limited","function_failed","internal"]
},
"message": { "type": "string" }
}
},
"data": { "type": "null" },
"root": {
"type": "object",
"properties": {
"took_us": { "type": "integer" },
"request_id": { "type": "string" },
"count": { "type": "integer" }
}
}
}
}Output
// The `code` enum is the eight distinct stable codes from
// distinct_error_codes()/code_status — NOT a literal list.No-drift design#
Two properties keep the projection truthful against the running server, enforced by tests in src/functions/api/openapi.rs.
- Paths match real routes —
documented_paths_match_the_system_worker_routesasserts the documented path set equals the worker's registered routes: /api/qql, /api/qql/batch, /api/login, /api/spec, /api/spec/openapi, /admin/drain. Adding/removing a route without updating the spec fails the build. - Error enum is derived, not literal —
error_code_enum_is_derived_from_code_statusasserts every stable code fromcode_statusappears in theErrorEnvelope.error.codeenum. The enum is generated byerror_code_enum_json()iteratingdistinct_error_codes(), so a newResponseCodeautomatically flows into the spec. - Well-formed + real routes —
openapi_is_well_formed_and_models_real_routesasserts version 3.1.0, the /api/qql, /api/qql/batch, /api/login, /admin/drain paths, and the OkEnvelope/ErrorEnvelope schemas are present.
code_status (envelope.rs)
11 ResponseCode -> 8 stable codes
|
+------------+------------+
| | |
worker wire /api/spec /api/spec/openapi
(HTTP status error_codes ErrorEnvelope.error.code
+ envelope) table enum
All three are generated from code_status, so the
HTTP status, the catalog table, and the OpenAPI
enum can never disagree.