torc 0.22.2

Workflow management system
# 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 in
  `src/server/live_router.rs`, and `src/models.rs`.
- The checked-in OpenAPI artifacts are `api/openapi.yaml` and `api/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.rs` and `src/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.rs`
- `src/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.rs`
- `src/client/apis/jobs_api.rs`
- `src/client/apis/access_control_api.rs`
- `src/client/apis/workflow_actions_api.rs`
- `src/client/apis/remote_workers_api.rs`
- `src/client/apis/ro_crate_entities_api.rs`
- `src/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
bash api/sync_openapi.sh emit
```

Verify the checked-in artifacts match the Rust emitter:

```bash
bash api/sync_openapi.sh check
```

Promote the Rust-emitted spec into `api/openapi.yaml`:

```bash
bash api/sync_openapi.sh promote
```

Regenerate Rust, Python, and Julia clients:

```bash
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
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
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.