Files
clawdbot/docs/gateway/pairing.md
2026-01-22 23:10:09 +00:00

93 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
summary: "Gateway-owned node pairing (Option B) for iOS and other remote nodes"
read_when:
- Implementing node pairing approvals without macOS UI
- Adding CLI flows for approving remote nodes
- Extending gateway protocol with node management
---
# Gateway-owned pairing (Option B)
In Gateway-owned pairing, the **Gateway** is the source of truth for which nodes
are allowed to join. UIs (macOS app, future clients) are just frontends that
approve or reject pending requests.
**Important:** WS nodes use **device pairing** (role `node`) during `connect`.
`node.pair.*` is a separate pairing store and does **not** gate the WS handshake.
Only clients that explicitly call `node.pair.*` use this flow.
## Concepts
- **Pending request**: a node asked to join; requires approval.
- **Paired node**: approved node with an issued auth token.
- **Transport**: the Gateway WS endpoint forwards requests but does not decide
membership. (Legacy TCP bridge support is deprecated/removed.)
## How pairing works
1. A node connects to the Gateway WS and requests pairing.
2. The Gateway stores a **pending request** and emits `node.pair.requested`.
3. You approve or reject the request (CLI or UI).
4. On approval, the Gateway issues a **new token** (tokens are rotated on repair).
5. The node reconnects using the token and is now “paired”.
Pending requests expire automatically after **5 minutes**.
## CLI workflow (headless friendly)
```bash
clawdbot nodes pending
clawdbot nodes approve <requestId>
clawdbot nodes reject <requestId>
clawdbot nodes status
clawdbot nodes rename --node <id|name|ip> --name "Living Room iPad"
```
`nodes status` shows paired/connected nodes and their capabilities.
## API surface (gateway protocol)
Events:
- `node.pair.requested` — emitted when a new pending request is created.
- `node.pair.resolved` — emitted when a request is approved/rejected/expired.
Methods:
- `node.pair.request` — create or reuse a pending request.
- `node.pair.list` — list pending + paired nodes.
- `node.pair.approve` — approve a pending request (issues token).
- `node.pair.reject` — reject a pending request.
- `node.pair.verify` — verify `{ nodeId, token }`.
Notes:
- `node.pair.request` is idempotent per node: repeated calls return the same
pending request.
- Approval **always** generates a fresh token; no token is ever returned from
`node.pair.request`.
- Requests may include `silent: true` as a hint for auto-approval flows.
## Auto-approval (macOS app)
The macOS app can optionally attempt a **silent approval** when:
- the request is marked `silent`, and
- the app can verify an SSH connection to the gateway host using the same user.
If silent approval fails, it falls back to the normal “Approve/Reject” prompt.
## Storage (local, private)
Pairing state is stored under the Gateway state directory (default `~/.clawdbot`):
- `~/.clawdbot/nodes/paired.json`
- `~/.clawdbot/nodes/pending.json`
If you override `CLAWDBOT_STATE_DIR`, the `nodes/` folder moves with it.
Security notes:
- Tokens are secrets; treat `paired.json` as sensitive.
- Rotating a token requires re-approval (or deleting the node entry).
## Transport behavior
- The transport is **stateless**; it does not store membership.
- If the Gateway is offline or pairing is disabled, nodes cannot pair.
- If the Gateway is in remote mode, pairing still happens against the remote Gateways store.