Appearance
Operations: Pair a device
For the user-facing pairing flows, see Devices / Pairing. This page covers the admin/operator perspective: when an admin needs to pair a Device on a user's behalf, troubleshoot a stuck pair, or pair a service Device.
Admin pair-on-behalf
Status: target state. There is no UI today for an admin to start a pair flow on behalf of another principal. The CLI is the workaround.
If an admin must pair a Device for a user (e.g., support scenario):
- The user's principal must already exist (they have signed in once).
- The user's Space must exist (created on first login).
- The Device runs
hivecast login --device --cloud https://hivecast.ai. The user code must be approved by the user (or by the admin on the user's behalf, which requires a session for the user — anti-pattern, avoid).
A clean admin pair-on-behalf op (auth.device.adminApprove or similar) is target state. Today, the user must be involved in approval.
Self-pair (platform Host paired to itself)
The platform Host can be paired to itself for self-test purposes — useful when verifying the pair flow end-to-end without a separate Device.
- On the platform Host:
hivecast login --device --cloud http://127.0.0.1:3100. - CLI prints user code, navigates browser to local
/auth/link?userCode=<code>. - Approve via the local-client identity (loopback bypasses auth).
- CLI exchanges; persists
hivecast-link.jsonto the same<host-home>.
The platform Host is now paired to itself. Useful for development; not a production operation.
Service Device pairing
Status: target state. A service Device (a non-human-owned compute participant — bot, integration) requires
ownerType: 'service'on its Space, which is schema-only.
The workaround: pair a regular Device under a dedicated principal that exists for service use only. That principal's Space carries ownerType: 'principal' (not 'service'); the distinction is operator-discipline rather than enforced.
Diagnosing a stuck pair
If a pair flow is stuck (auth.device.poll returns authorization_pending indefinitely):
bash
# Inspect the pending device-flow record
matrix invoke system.auth auth.device.status \
'{"userCode":"<code>"}'
# Status fields: pending | approved | namespace_required | exchanged | cancelled
# If status is namespace_required:
# The principal does not own a Space with a matching public namespace claim.
# Either claim one or change the routeKey on the device-start.
matrix invoke system.auth auth.namespace.list '{"principalId":"p_xxx"}'
matrix invoke system.auth auth.namespace.claim '{...}'
# If status is pending:
# The user simply hasn't approved yet. Check whether they navigated to the
# correct activation URL.
# If the user code is invalid or expired:
# Cancel and start fresh.
matrix invoke system.auth auth.device.cancel '{"userCode":"<code>"}'Diagnosing a stuck approval
If the user clicked Approve but the CLI's auth.device.poll still says authorization_pending:
- The approval may have failed. Check the platform's
system-authruntime log. - The principal that approved may not own a Space with the requested
routeKey. Look fornamespace_requiredstatus.
Inspecting Host Links after pair
bash
matrix invoke system.auth auth.hostLink.list '{"principalId":"p_xxx"}'
# Confirm the new Host Link appears, status: 'active'.
matrix invoke system.devices devices.list '{"principalId":"p_xxx"}'
# Confirm the Device shows up. May lag by ~30s after pair.Authorization
A normal pair op (device-flow or pair-flow) requires:
- Approval call: a signed-in principal whose own Spaces match the requested
routeKey. The principal cannot approve into another principal's Space. - Exchange call: anyone holding the correct
deviceCode(CLI) orpairRequestId+approvalCode(browser). These codes are short-lived and single-use.
There is no "admin override" for these checks today. Target state.
See also
- Devices / Pairing — full user-facing flows.
- Operations: Disconnect a device — the inverse.
- Reference: Admin actor ops — the op surface.
Source:
projects/matrix-3/packages/system-auth/src/index.ts:882-1196for the pair/device ops.