Skip to content

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_VERSION constant.
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: localhost

Response

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.

MethodPathoperationIdRequest body2xx schema
POST/api/qqlrunQqltext/plain raw QQL stringOkEnvelope
GET/api/qqlrunQqlGetnone (uses `q` query param)OkEnvelope
POST/api/qql/batchrunQqlBatchapplication/json array of QQL stringsBatchResponse
POST/api/loginloginapplication/json LoginRequestOkEnvelope
GET/api/specgetCatalognoneOkEnvelope
GET/api/spec/openapigetOpenApinoneOkEnvelope
POST/admin/draindrainnoneOkEnvelope

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. error is null; data is an untyped result ("The function result (rows, a record, or a value)."); root is an object with optional integer took_us, string request_id, and integer count.
ErrorEnvelope
Object requiring error/data/root. error is { code, message } where code is a string with the eight-value enum; data is null; root is the same root object.
BatchResponse
An array whose items are oneOf OkEnvelope / ErrorEnvelope — one envelope per submitted statement, in submission order.
LoginRequest
Object requiring username and password (both strings).

Request

// GET /api/spec/openapi -> data.components.schemas.ErrorEnvelope

Response

{
  "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_routes asserts 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_status asserts every stable code from code_status appears in the ErrorEnvelope.error.code enum. The enum is generated by error_code_enum_json() iterating distinct_error_codes(), so a new ResponseCode automatically flows into the spec.
  • Well-formed + real routes — openapi_is_well_formed_and_models_real_routes asserts 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.
Single source of truth feeding three artifacts