# archive-control-proto Source-of-truth protobuf contract for Archive Control clients and the Titan control daemon. Implementations exchange canonical protobuf JSON as one text message per WebSocket frame. Upstream: `cabbage/archive-control-proto` ## Contract overview - `common.proto`: protocol versioning, roles, health, and stable error codes - `resource.proto`: v1/v2 torrent identity, selected-file sets, trees, and placements - `route.proto`: discovered and automatically provisioned pairwise Syncthing routes - `transfer.proto`: the protobuf-JSON on-disk transfer manifest and ready marker - `job.proto`: immutable job requests, runtime states, steps, progress, archive coverage, and eviction - `inventory.proto`: scoped, chunked, on-demand inventory/tree responses - `client.proto`: capabilities, registration, active-job cursors, and heartbeat - `control.proto`: durable commands, acknowledgements, job events, snapshots, and route updates - `envelope.proto`: the only top-level WebSocket application message ## Wire rules 1. A new connection's first application message is `RegisterRequest`. 2. The pre-shared token appears only in that request. It must not be logged. 3. A server command is delivered at least once. Clients durably deduplicate `command_id` and return `DUPLICATE` for a replayed accepted command. 4. `CommandAck` means durable acceptance, not operation completion. 5. Job events have monotonically increasing global per-job sequences. A command carries the accepted sequence base and grants one client the event-writer lease; a gap requires `JobSnapshot` reconciliation before further destructive transitions. 6. UUIDs use lowercase canonical text. Info hashes use validated lowercase hex. 7. `SelectionSet.ranges` are inclusive, sorted, non-overlapping, and coalesced. 8. Receivers ignore unknown JSON fields for compatible minor versions. They reject an unknown required command/job operation. 9. Published field numbers and enum values are never reused. Removed values are reserved in the change that removes them. 10. Implementations cap an envelope at the negotiated maximum and keep streamed inventory chunks below that value. ## Dockerized tooling The host remains a thin editor. Buf runs in Docker and writes as the calling UID/GID: ```bash ./scripts/buf.sh format ./scripts/buf.sh lint ./scripts/buf.sh build ./scripts/validate-examples.sh ./scripts/buf.sh generate ``` An equivalent `Makefile` is provided for environments where `make` is already available; it is not required on the thin development host. Generated Python bindings are copied into and committed by consumer repositories with the exact proto release/commit recorded in their generated header. Both generator plugins are version/revision pinned. `gen/` is intentionally ignored here. Before releasing a compatible update: ```bash ./scripts/buf.sh breaking '.git#tag=v0.1.0' ``` ## JSON examples `examples/v1/` contains representative canonical protobuf JSON for registration, inventory, route setup, assignment, progress, commit, cancellation, eviction, and reconnect reconciliation. They are protocol fixtures, not hand-maintained alternative schemas.