establishment: the mechanics — reply capabilities, helloExchange, lineage routing

P0 of docs/establishment-planes-plan.md; no behavior changes yet, nothing
sets the new flag or sends a hello capability.

- service.run gains a reply-capability out-slot (replyWithCapability), the
  registry idiom init already uses, lifted into the harness; null stays the
  untouched common path. Subscribers gains claimArrival() so a provider
  handler can keep a turn capability through the same flag the reserved
  subscribe uses.
- Hello wire struct: the padding byte becomes wants_channel — old callers
  wire-compatibly say 0, and the manager nominates a reply capability ONLY
  when asked, because a capability sent to a caller that never reads one is
  a leaked slot in that caller's table.
- driver.helloExchange: one handshake can hand a serving endpoint up and
  receive the device's provider channel down (usb-storage will need both at
  once). No channel in the reply is retryable, never a verdict.
- The manager stores each instance's serving endpoint on its Driver entry,
  routes consumer hellos by lineage (child -> reporter -> endpoint), replaces
  on re-hello, and closes the stale handle on death - the 32-slot table is
  the bound that makes forgetting this boot-fatal.
This commit is contained in:
Daniel Samson
2026-08-09 11:39:29 +01:00
parent 0d5a7394ef
commit 77fe4d220e
4 changed files with 116 additions and 6 deletions
@@ -79,7 +79,13 @@ pub const Role = enum(u8) {
pub const Hello = extern struct {
/// A `Role` value.
role: u8,
_padding: u8 = 0,
/// 1 = the caller asks the reply to carry a capability to the channel of
/// the driver that provides the caller's device — the target's reporter;
/// establishment by lineage (communication.md "Establishment: two
/// planes"). 0 = a plain handshake, and the reply carries nothing — which
/// keeps every caller that never reads a reply capability from leaking
/// one. Was padding, so old callers wire-compatibly say 0.
wants_channel: u8 = 0,
/// The protocol version this driver was built against (`version`).
version: u16 = version,
};