Files
alknet/docs/architecture/questions/058-worker-registration-flow.md
T
glm-5.2 a26401aadd docs(arch): rewrite hub README for multi-transport + channels substrate; add OQ-58 (worker registration)
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.
2026-07-13 09:22:32 +00:00

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 (HttpAdapter on h2/http/1.1 over 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:
    1. 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.
    2. 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).
    3. Endpoint path. POST /register? POST /v1/workers/register? A versioned path is safer for a one-way door.
    4. 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 on h2/http/1.1 over TCP+TLS). The request carries the worker's public key and the enrollment token. The hub validates the token, creates a PeerEntry for the worker (fingerprint from the key, auth_token_hash from 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. The PeerEntry created at registration is what resolve_from_token / resolve_from_fingerprint matches 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).