Files
archive-control-proto/README.md
T

80 lines
3.3 KiB
Markdown

# 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. The current incompatible protocol major is `2`.
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 and name
the durable command that owns them. Control verifies the reporting client,
command cursor, and permitted state transition. A gap or conflict requires
authoritative `ReconcileJobCommand` processing 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 reject a different protocol major. Within major `2`, they ignore
unknown JSON fields only for compatible minor versions and 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.