rollout-proto — wire-format crate

rollout-proto owns the workspace's .proto files and runs tonic-build exactly once. Downstream crates (rollout-transport, rollout-plugin-host, rollout-coordinator) depend on rollout-proto, not on .proto regeneration.

Why a dedicated crate

Per CONTEXT D-PROTO-01, the workspace has a single tonic-build invocation site. Centralising wire-format ownership means:

  • The HTTP/2 ↔ QUIC swap (CONTEXT D-TRANS-01 fallback) shares the same source-of-truth proto schema.
  • The sidecar IPC protocol (UDS) and the network transport carry the same message types — no drift between in-process and out-of-process plugin calls.
  • Build-time codegen happens once per workspace build; downstream crates compile faster.

Wire-format ownership

FilePackageOwns
proto/transport.protorollout.transport.v1Worker ↔ Coordinator transport
proto/plugin.protorollout.plugin.v1Host ↔ sidecar Plugin protocol

Both are committed to the repo. The build script (build.rs) compiles them via tonic-prost-build on every workspace build; rerun-if-changed keeps incremental builds fast.

Three transport channels

transport.proto defines the three logical channels from spec 05 §3:

ChannelRPC kindCadencePurpose
Heartbeatunary Beatevery 500 msWorker liveness; carries due_at for deadline-based health
Controlserver-stream Subscribeas-neededCoordinator pushes drain / snapshot / cancel
Workbidi StreamburstyPull/submit work items (full semantics land in Phase 6)

All three multiplex over one connection — HTTP/2 today, QUIC behind a feature flag in a later phase.

Plugin sidecar protocol

plugin.proto defines the five sidecar RPCs from spec 03 §3.3 + §4:

  • Init(InitRequest) -> InitResponse — one-time setup per worker.
  • Preflight(PreflightRequest) -> PreflightResponse — optional, after Init.
  • Call(CallRequest) -> CallResponse — generic typed entry point; payload is opaque bytes (JSON or postcard, plugin-defined).
  • Reload(ReloadRequest) -> ReloadResponse — hot reload signal; the sidecar may refuse.
  • Shutdown(ShutdownRequest) -> ShutdownResponse — clean exit with grace period.

The Python sidecar host implementation lands in rollout-plugin-host (plan 02-05).

Python stubs

The in-tree Python sample sidecar (python/examples/sample_sidecar/) uses stdlib length-prefixed JSON framing over UDS — per AGENTS.md §7, every plugin must be testable locally without pip install grpcio or other external services. See 02-RESEARCH.md §"Python sidecar IPC: avoid pip" for the rationale.

If you are authoring a Python plugin that does want real gRPC, opt in via make protos (which shells to cargo xtask gen-protos). Output goes to python/rollout/_proto/. The xtask gracefully degrades when grpcio-tools is missing — it prints a helpful message and exits 0; CI does not require it.

pip install grpcio-tools     # opt-in
make protos                  # writes python/rollout/_proto/*_pb2.py

Versioning

Both protos use a v1 package suffix (rollout.transport.v1, rollout.plugin.v1). Bumping to v2 is a future spec edit; the v1 modules will continue to compile alongside any future versions so in-flight Phase 2 deployments do not break.

Cross-references