The hub README predates channels (2026-07-09) and was built on the call-protocol-directly-over-QUIC model: 'One QUIC connection per peer carrying the call protocol,' CallClient::connect as the dial path, QUIC as the only transport. The channels crate replaced that substrate (ADR-071/079/080), and the hub's primary use case (worker provisioning on docker/vast.ai/runpod) requires TCP+TLS for registration and QUIC or TCP+TLS for the ongoing session — coexisting on one hub, not as alternatives. Rewrite: - Multi-transport stated as decided: 'A hub MUST support TCP+TLS and QUIC endpoints simultaneously.' TCP+TLS accept loop (ADR-010 Am. 1) lives in the hub, shares the HandlerRegistry with the quinn endpoint. - Channels substrate: the hub uses ChannelsAdapter/ChannelClient (from_connection primary, connect_quic convenience — ADR-080), not CallClient/CallAdapter directly. One channels connection per peer; CallAdapter runs on channel 0 (ADR-072). - Transport-agnostic dial/accept: dial_worker_connection takes a Connection (one-way door); connect_quic_worker is a two-way-door convenience. supervise_worker takes a dial closure, not a SocketAddr. - Identity over transports: fingerprint path (QUIC+raw-key, X.509 client cert) via resolve_from_fingerprint; bearer-token path (TCP+TLS no client cert, WebTransport, WebSocket) via resolve_from_token on the call first frame. Both resolve to the same PeerEntry (ADR-030/034). - Worker registration flow (6 steps): provision → token → download → key gen → HTTP POST over TCP+TLS → channels connect. Step 4 is HTTP on HttpAdapter; step 6 is channels over QUIC or TCP+TLS. The hub creates a mixed-fingerprint PeerEntry (ADR-034 §3) at registration. - OQ-58: worker registration flow — enrollment-token model, endpoint shape, register_worker API. Open (decision-ready, not blocked), one-way door, high priority. - ADR-081: fix stale references to channels-hub/channels-worker sub-crates (the ADR's Decision says they don't exist; the References section said they did). Review (architecture-reviewer): 3 critical (ADR-081 stale refs; bearer-token extraction flow; assembly example QUIC-only + unspecced into_connection), 7 warnings (registration 'or'→'both', channel/control translation, OQ-52 interim, HubError variant naming, RegistrationError definition, X.509-client-cert prose, adapter ownership phrasing), 5 suggestions. All criticals and warnings #4/#7/#8 addressed; #5/#6/#9/#10 addressed; #11-15 noted as optional.
3.7 KiB
3.7 KiB
OQ-58: Worker Registration Flow
- Origin:
docs/architecture/crates/hub/README.md§"Worker registration" — the provisioning → enrollment → connection sequence that makes TCP+TLS a hard requirement for the hub. - Status: open
- Door type: one-way (the registration endpoint shape and the enrollment-token model are an API surface; changing them after workers are provisioned against them is a breaking change for every deployment)
- Priority: high
- Blocked on: nothing structural — the identity machinery
(
resolve_from_token,PeerEntry.auth_token_hash, ADR-030/034) and the HTTP substrate (HttpAdapteronh2/http/1.1over TCP+TLS, ADR-010 Am. 1 / ADR-065) both exist. What remains is deciding the token model and the endpoint shape, not building new primitives. - Resolution: Not yet decided. The flow is decision-ready in
shape (see "Decision-ready shape" below). The open sub-questions are:
- Enrollment-token model. Is the registration token one-time single-use (burned on first POST), one-time-per-worker (a worker can retry the POST until it succeeds, then the token is invalidated), or refresh-capable (the token can enroll multiple workers, e.g. a pool token)? One-time-per-worker is the likely default (matches the provisioning flow: one token per instance); pool tokens are a feature extension.
- Session credential returned. After registration, does the
hub return a bearer token for the ongoing channels connection
(the worker authenticates over TCP+TLS via
auth_token), or does it record the worker's fingerprint and expect fingerprint auth on the channels connection (the worker authenticates over QUIC via its raw key)? Both are valid; the choice depends on whether the worker's transport is known at registration time. A hub that accepts both should probably support both return shapes (return a token and record the fingerprint). - Endpoint path.
POST /register?POST /v1/workers/register? A versioned path is safer for a one-way door. - Token source. Does the hub generate the enrollment token, or does the assembly layer (the provisioning system) generate it and the hub just validates it? The latter keeps the hub out of the token-generation business but requires a shared secret or signature scheme.
- Decision-ready shape: the registration endpoint is an HTTP POST
on the hub's
HttpAdapter(served onh2/http/1.1over TCP+TLS). The request carries the worker's public key and the enrollment token. The hub validates the token, creates aPeerEntryfor the worker (fingerprint from the key,auth_token_hashfrom a session token the hub issues), and returns the session credential. The worker then connects via channels (QUIC or TCP+TLS) and authenticates with the fingerprint or the bearer token. ThePeerEntrycreated at registration is whatresolve_from_token/resolve_from_fingerprintmatches at connection time. - What does NOT block on this: the hub's multi-transport accept
loop, the channels-over-TCP path, the identity-over-TCP path
(bearer token via
resolve_from_token), and the supervision loop. All of these are decided and use existing machinery. OQ-58 is about the registration endpoint specifically — the one new surface the hub introduces. - Cross-references: ADR-030 (PeerEntry, auth_token_hash), ADR-034 (bearer-token identity over non-fingerprint transports), ADR-010 Am. 1 (TCP+TLS dispatch via from_stream), ADR-065 (Connection::from_bidi), ADR-080 (ChannelClient::from_connection), OQ-52 (CallConnection::wait_for_close — the supervision loop the registration flow feeds into).