Add a control operation
The control plane is one protobuf request and one response per operation, dispatched by rohi-control and served over
BLE. The wire contract is documented in Control plane; this is the recipe for extending it.
- Schema (
crates/rohi-control-proto/proto/rohi/control/v1/control.proto): add the request/response messages and aoneofentry with a new field number. Field numbers and enum values are stable and only ever added. Add bounds for every repeated/bytes field inbuild.rsso the generated types stay heapless, and update the worst-case size tests if the message can grow beyondMAX_REQUEST_LEN/MAX_RESPONSE_LEN. Do not changePROTOCOL_VERSIONfor additive changes. - Capability and privilege (
rohi-control): add aCapabilitiesflag if clients must be able to discover the feature, extendrequirements()incontroller.rswith(capability, Privilege::Read | Mutate)and handle the call inexecute. Mutating operations needPrivilege::Mutate(checked by theAuthorizationPolicy). - Service seam: add a method to
ControlServicesfor what the firmware must provide (asyncor sync), with documented cancellation semantics. The dispatcher never sees stores, flash or radio drivers. Update every implementation: the firmware adapter (UrbanControlServices), the fakes inrohi-control,rohi-control-bleandtools/rohitests. - Mutation rule: if the operation commits durable state that a runtime must react to, the commit and the
publication happen in the owner task (Durable mutation),
exposed as one service call (see
set_wifi_config). - Errors: map service failures to the typed protocol errors (
INVALID_ARGUMENT,NOT_FOUND,NOT_SUPPORTED,BUSY,UNAVAILABLE,PERMISSION_DENIED,INTERNAL); secrets are never returned or logged. - Mapping: convert between
rohi-*types and protobuf inrohi-control/src/mapping.rs; the protobuf types do not leak into other crates. - Client: add the typed method to
rohi::Device(it checks capabilities first) and a CLI subcommand if useful. - Tests: protocol golden bytes/bounds, dispatcher (capability, authorization, validation, “nothing stored on invalid input”), loopback client end to end, and a cancellation test if the operation is long-running.
- Docs: the request table and limits in Control plane, resource limits if any, and the glossary for new terms.