Authentication
Host-authorized device pairing and operator credential lifecycle.
📄️ List owner-controlled plugin grants
List explicit paired-device plugin privileges from the direct localhost or verified Tailscale dashboard. This route is unavailable through relay access and refuses any paired bearer, including on the direct listener. It does not expose credentials. Existing pairings have no plugin grants.
📄️ Replace one device's explicit plugin grants
Replace plugin read, management and approval grants after a direct owner dashboard check and expected-revision comparison. An empty scope list revokes every plugin grant immediately, including for existing access tokens. A presented paired bearer is refused even with matching direct-owner origin headers. Remote operators cannot call this route or grant themselves privileges.
📄️ List dashboard pairing invitations
Return safe invitation status without bearer nonces or pairing codes. A node that has never paired returns an empty list. This management route is available only to the gateway dashboard over localhost or Tailscale and never through the relay gateway.
📄️ Create a dashboard pairing invitation
Create one bounded, revocable pairing invitation from the configured gateway dashboard over localhost or Tailscale. The secret pairing code is returned once with no-store response headers and is never relay-accessible. A cluster allows at most five active paired devices: the invitation's pairing limit is reduced to the free device slots, and creation returns 409 when no slot is free.
📄️ Report paired-device capacity
Return how many paired devices can still connect, the cluster's maximum of five, and the free device slots. A device stops occupying a slot when it is revoked or its refresh credential expires. A node that has never paired a device reports every slot free. This management route is available only to the dashboard over localhost or Tailscale and never through the relay gateway.
📄️ Revoke a dashboard pairing invitation
Immediately prevent new and unfinished pairing attempts for one invitation without revoking devices that already paired. This management route is available only to the configured gateway dashboard over localhost or Tailscale and is never relay-accessible.
📄️ Bind a device key to a local pairing session
Accept a candidate Ed25519 public key only when the nonce names an unexpired host-created pairing session or invitation, then return one random challenge for proof of possession. Reusable invitations return an independent five-minute attempt identity. Returns 409 when the cluster already has its maximum of five active paired devices.
📄️ Exchange a device-key proof for operator credentials
Verify the candidate device's Ed25519 signature, consume its single-use session or independent invitation attempt, and return short-lived access plus rotating refresh credentials exactly once. The device limit is enforced atomically with the credential commit: when the cluster already has five active paired devices the exchange returns 409 and issues no credential.
📄️ Rotate an operator refresh credential
Accept the current opaque refresh credential for one paired device, invalidate its existing token pair, and return a fresh short-lived access token plus rotating refresh token exactly once.
📄️ List paired operator devices
Return safe active and revoked device projections for a bearer credential with device-management scope or a verified direct dashboard. Credential material is never included. The direct dashboard receives an empty list on a node that has never paired.
📄️ Revoke a paired operator device
Immediately invalidate the target device's access and refresh credentials. Repeating revocation for an already revoked device is idempotent. Requires device-management bearer scope or verified direct dashboard authority.
📄️ Read phone pairing status
Return whether phone pairing through the relay is set up on this node and whether the relay holds a live session from it: not_set_up, registering, connecting, connected, relay_unreachable, revoked (the relay permanently refused the route), or managed_elsewhere (another node holds the cluster's relay route). Also reports whether this node can register a route, the last registration failure, and the relay host. Available only to the dashboard over localhost or Tailscale, never through the relay.
📄️ Turn phone pairing on
Register this node's relay route when it has none, so paired phones can reach it through the content-blind relay; remote access starts without a restart. The node generates its connector key and carrier credentials and sends the relay only their fingerprints. Idempotent: with a route stored or a registration in flight it returns the current status. Refused while another node manages phone pairing or the cluster has its maximum of paired devices. Failures carry a stable code. Available only to the dashboard over localhost or Tailscale, never through the relay.
📄️ Turn phone pairing off
Forget this node's relay route; remote access stops without a restart. Phones paired through the route lose remote access and keep their device records until revoked. Active invitations for the route are revoked. The relay is not contacted. Idempotent. Available only to the dashboard over localhost or Tailscale, never through the relay.