API Generation Architecture
This document describes how Torc's HTTP API contract and generated clients are produced.
Overview
Torc uses a Rust-owned OpenAPI workflow:
- The HTTP contract is defined in Rust by
src/openapi_spec.rs, live handlers insrc/server/live_router.rs, andsrc/models.rs. - The checked-in OpenAPI artifacts are
api/openapi.yamlandapi/openapi.codegen.yaml. - The live server transport is implemented in Rust under
src/server/http_transport.rs. - The Rust client used by the CLI/TUI/dashboard is generated into
src/client/apis/using checked-in OpenAPI Generator template overrides so it matches Torc's canonical model layer and client conventions. - The Python and Julia clients are generated from the checked-in OpenAPI artifact.
Source Of Truth
The main ownership layers are:
src/models.rs- Canonical API models used by the Rust-owned contract.
src/openapi_spec.rs- OpenAPI document definition, emission, and parity checks.
src/server/live_router.rs- Live typed handlers that also own route metadata and operation IDs.
src/server/http_transport.rsandsrc/server/http_transport/*.rs- Live HTTP transport implementation for the server.
src/server/api_contract.rs- Rust server contract traits.
The HTTP API version is single-sourced in:
src/api_version.rs
That constant feeds:
- server version reporting
- client/server version checks
- emitted OpenAPI document version
- external client generation package metadata
OpenAPI Artifacts
The checked-in files in api/ are:
api/openapi.yaml- Promoted OpenAPI artifact used for external client generation.
api/openapi.codegen.yaml- Rust-emitted artifact kept alongside the promoted spec.
These should match the Rust emitter output. The parity check enforces that.
Server Creation
The live server is built from:
src/server/http_server.rs- top-level server wiring and shared state
src/server/http_transport.rs- HTTP route dispatch and request/response mapping
src/server/http_transport/*.rs- domain-specific transport handlers
src/server/api/*.rs- lower-level server business logic modules
Rust Client Creation
The Rust client under src/client/apis/ is generated from api/openapi.yaml, but it does not own
its own model layer.
Relevant files:
api/regenerate_rust_client.sh- Generates a sync Rust client into a temporary directory.
- Passes
api/openapi-generator-templates/rust/to OpenAPI Generator. - Copies only the generated grouped API modules, not the generated
models/tree.
api/openapi-generator-templates/rust/- Checked-in template overrides for the generated Rust client surface.
- Must remain version-controlled because regeneration uses them as a required input.
- Encodes Torc-specific generation behavior such as importing
crate::models, using the shared blocking client helpers, and applying auth consistently.
src/client/apis/configuration.rs- Hand-owned blocking client configuration used by the generated Rust API modules.
- Carries Torc-specific conventions like TLS settings, cookie handling, and auth application.
The surrounding Rust client logic is hand-written in:
src/client/
That includes things like:
src/client/version_check.rssrc/client/commands/src/client/workflow_spec.rs
The generated Rust client is one layer inside a larger hand-owned Rust client stack. The canonical
Rust API models remain in src/models.rs.
The generated Rust client does not own a second Rust model layer. Generated models.rs output
is discarded. The repo keeps exactly one canonical Rust API model surface in src/models.rs.
The generated Rust client is tag-grouped. Current generated modules include domains such as:
src/client/apis/workflows_api.rssrc/client/apis/jobs_api.rssrc/client/apis/access_control_api.rssrc/client/apis/workflow_actions_api.rssrc/client/apis/remote_workers_api.rssrc/client/apis/ro_crate_entities_api.rssrc/client/apis/system_api.rs
The rest of the Rust codebase now calls those grouped generated modules directly.
Python And Julia Client Creation
The Python and Julia clients are generated from api/openapi.yaml.
Relevant files:
api/regenerate_clients.sh- Regenerates the Rust, Python, and Julia clients from the selected spec.
api/sync_openapi.sh- Main developer entrypoint for emitting, checking, promoting, and regenerating clients.
Generated output locations:
- Python:
python_client/src/torc/openapi_client/
- Julia:
julia_client/Torc/src/api/julia_client/julia_client/docs/
There is also a hand-written Python compatibility/helper layer in:
python_client/src/torc/api.py
That layer exists to provide a stable high-level interface over the tag-grouped generated Python APIs.
Developer Workflow
Emit the Rust-owned OpenAPI spec:
bash api/sync_openapi.sh emit
Verify the checked-in artifacts match the Rust emitter:
bash api/sync_openapi.sh check
Promote the Rust-emitted spec into api/openapi.yaml:
bash api/sync_openapi.sh promote
Regenerate Rust, Python, and Julia clients:
bash api/sync_openapi.sh clients
This regenerates the Rust client from the selected spec using the checked-in template overrides, then regenerates the Python and Julia clients from the same spec.
To iterate on clients against the Rust-emitted contract before promotion:
bash api/sync_openapi.sh emit
bash api/sync_openapi.sh check
bash api/sync_openapi.sh clients --use-rust-spec
Run the full sync flow:
bash api/sync_openapi.sh all --promote
Why This Layout Exists
This arrangement gives Torc one authoritative contract pipeline:
- The server contract is owned in normal Rust code.
- The OpenAPI artifact is emitted deterministically from that Rust code.
- External clients are generated from the emitted artifact.
- Rust generator customization is expressed in checked-in templates, not a post-generation patch overlay.
- Generated files are downstream artifacts, not the source of truth.