Skip to content

Device pairing

Pairing is the act of turning a local Host install into a Device on a HiveCast account. There is exactly one pairing protocol; different surfaces (CLI, local UI, HiveCast UI) start it differently but they all run the same five-step ceremony.

The user-facing terms are Device (the linked compute participant) and Space path (the user's public Space route handle). Internal data-model fields (hostId, installId, routeKey) appear on this reference page because we are explaining the data model, not because they belong in CLI prose or product UI copy.

The five-step ceremony

text
1. start enrollment      ─ produce a pending pairing record (deviceCode / pairRequestId)
2. authenticate + approve ─ a signed-in principal approves the pairing
3. redeem on the device  ─ the Host exchanges the approved record for a Host Link
4. issue credentials     ─ system-auth mints device-scoped NATS creds + heartbeat token
5. register + heartbeat  ─ host.control posts presence, runtimes show up in inventory

This shape is taken directly from HIVECAST-DEVICE-ENROLLMENT-SPEC.md § "Uniform Solution" and § "Backend Protocol". It is the same flow whether the user runs hivecast login --device headless or clicks "Connect to HiveCast" from the local Edge UI.

Two pending-record families

system.auth keeps two stores for in-flight pairings, used by different initiation surfaces:

StoreConstructorInitiated fromTTL
HostDeviceLinkStorehost-auth.ts:990headless / device-code: auth.device.start30 min (DEVICE_LINK_DURATION_MS)
HostPairingStorehost-auth.ts (later)interactive browser-pair: auth.pair.start10 min (PAIRING_DURATION_MS)

The headless device-code flow gives the user a userCode like ABCD-EFGH that they enter on a separate browser session. The browser-pair flow returns a pairRequestId plus an approvalCode that the Host carries through the local OAuth redirect.

Both flows terminate in the same place: a row in hostLinks[] with status: 'active', principalId, spaceId, authorityRoot, and a freshly allocated deviceSlug.

Anatomy of a successful pairing

After step 3 (redeem), the Host has on disk:

FileContents
<host-home>/credentials/hivecast-link.jsonLink record. See reference.
<host-home>/credentials/hivecast-nats.jsonDevice-scoped NATS user JWT + seed.
<host-home>/credentials/hivecast-host-link-tokenBearer token (single line, no JSON) used as Authorization: Bearer <token> for cloud heartbeats.
<host-home>/credentials.json (mirror)Symmetric copy of the NATS creds for the Host's own NATS client.

The cloud has on the system.auth side:

StateSource
hostLinks[] row with status: 'active'HostLinkStore.create() in host-auth.ts:799-859
heartbeatTokenHash recorded against the rowHostLinkStore.rotateHeartbeatToken()
External identity → principal mappingHostPrincipalStore.findOrCreate()
Optional publicNamespace claimHostNamespaceStore.claim() if the link includes a Space-path

The five steps mapped to ops

StepHeadless device-code opInteractive browser-pair op
1. startauth.device.startauth.pair.start
2. authenticate (browser)auth.google.loginauth.google.callbacksame
2. approveauth.device.approveauth.pair.approve
3. redeemauth.device.pollauth.device.exchangeauth.pair.exchange
4. issue credentialsside-effect of exchange: auth.hostLink.credentials.refresh mints a device-scoped NATS user JWT (see system-auth/src/index.ts)same
5. registerhost.control reads hivecast-link.json and posts devices.register + devices.runtimes.register heartbeatssame

The Host CLI command that drives steps 1+3+local-write side of this flow is hivecast login --device --cloud <url> (headless) or hivecast login --setup-code <code> --cloud <url> (interactive). See the Pairing section for the per-flow detail.

What pairing does NOT mint

Pairing does not give the Device:

  • a copy of the principal's account-level NATS account seed
  • a HiveCast session cookie or principal session JWT
  • an OAuth refresh token from Google/GitHub/Anthropic/Codex

The Device only ever holds device-scoped credentials. See Why hosts do not receive raw OAuth tokens for the security argument; this is a real architectural rule, not a polish detail.

See also

Source: WORKSTREAMS/product-launch/HIVECAST-DEVICE-ENROLLMENT-SPEC.md § "Uniform Solution" and § "Backend Protocol"; projects/matrix-3/packages/system-auth/src/host-auth.ts (HostLinkStore, HostDeviceLinkStore, HostPairingStore); projects/matrix-3/packages/system-auth/src/index.ts (op surface).