# User Pairing & Access Control

Pairing is GoClaw's primary mechanism for granting users access to chat with your agents. It provides a secure way to authorize individuals on third-party platforms like Discord or Microsoft Teams.

## How Pairing Works

When the `pairing` DM policy is active (the default), GoClaw acts as a gatekeeper:

1.  **Challenge:** An unknown user messages the bot.
2.  **Code Issued:** The bot generates an 8-character challenge code (e.g., `ABCD1234`) and sends it to the user.
3.  **Approval:** You (the bot owner) review the request and approve the code.
4.  **Authorized:** The user is added to the approved list and can now interact with the agent.

Despite its name, `channels.dm_policy` applies to every message the bot receives on Discord, Teams, Telegram and Facebook Messenger, not only to direct messages. An unapproved member who @mentions the bot in a Discord server channel or a Telegram group gets the pairing reply in that channel or group. Comments on a Facebook Page's posts and Lead Ads submissions are not messages to the bot and do not go through pairing; see [Facebook: comments, leads and `dm_policy`](facebook.md#comments-leads-and-dm_policy).

| `channels.dm_policy` | Who gets an answer |
|---|---|
| `pairing` (default) | IDs in `channels.allow_from` and approved (paired) users. Anyone else gets a pairing code. |
| `allowlist` | IDs in `channels.allow_from` and users already approved. Anyone else is told "You are not authorized to use this bot." and no code is issued. |
| `open` | Everyone. |

---

## Approving a Request

Once a user has their pairing code, you can approve it using any of the following methods:

### 1. Web UI (Recommended)
Navigate to the **Pairing** tab in your GoClaw dashboard (typically `http://localhost:8080`). Pending requests are listed with their channel, the user's platform ID and their code. Pick a role for the user (`user`, `admin` or `system`) and click **Approve**. The tab can be filtered by channel.

### 2. CLI
Use the `goclaw` binary directly:
```bash
# List pending pairing requests (the channel defaults to discord)
./goclaw pairing pending telegram

# Approve a specific code (--role user | admin | system, default user)
./goclaw pairing approve <CODE>
./goclaw pairing approve <CODE> --role admin
```

`approve` prints the new user's GoClaw user ID (`u_…`), which `revoke` and `link` take.

A running gateway sees an approval, revocation or link made with the CLI at once: it reads the pairing files again whenever they change.

### 3. REST API
The dashboard uses this API under the hood. It needs the gateway token (`gateway.auth.token`):
```bash
curl -X POST http://localhost:8080/api/pairing \
  -H "X-Goclaw-Token: <gateway token>" \
  -H "Content-Type: application/json" \
  -d '{"action": "approve", "channel": "discord", "code": "ABCD1234", "role": "user"}'
```

`channel` may be left out of an approve; the answer names the account and channel approved. `GET /api/pairing?channel=<name>` (or `all`) lists pending requests and approved users. The other `POST` actions are `{"action": "revoke", "user_id": "u_…"}` and `{"action": "update_role", "user_id": "u_…", "role": "admin"}`. A role other than `user`, `admin` or `system` is refused (`400`).

---

## Pre-Approved Users (Bypassing Pairing)

If you already know the platform-specific IDs for yourself or your team, you can bypass the pairing flow by adding them to the `allow_from` list in `config.yaml`:

```yaml
channels:
  allow_from:
    - "100000000000000103"    # Discord user ID
    - "29:1abc-def-ghi"       # Teams user ID
```

`allow_from: ["*"]` lets everyone in, under either policy.

---

## Revoking Access

To remove a user from the approved list, use the Web UI (**Pairing** tab → approved users → **Revoke**) or the CLI. Revoking removes the user and every channel account linked to them.

```bash
# Revoke access via CLI: takes the GoClaw user ID (u_…), not the platform ID
./goclaw pairing revoke <USER_ID>

# Approved users on a channel (shows platform IDs; the channel defaults to discord)
./goclaw pairing list telegram
```

`pairing list` shows each user's platform ID, not the `u_…` ID. Find the `u_…` ID in the output of `approve`, on the Web UI (shown as "User ID"), or in `goclaw-users.json`. As with approvals, a CLI revoke is not seen by a running gateway until it restarts, so the user keeps access until then: revoke on the Web UI while the gateway runs.

Approved users are stored in `<state dir>/credentials/goclaw-users.json` and pending requests in `<state dir>/credentials/goclaw-pending.json` (the state directory is `~/.goclaw` unless `GOCLAW_STATE_DIR` says otherwise).

---

## Security Details

- **Challenge Codes:** Codes are 8 characters long, uppercase, and avoid ambiguous characters (like `0`, `O`, `1`, `I`).
- **Expiration:** Codes expire after **1 hour**.
- **Rate Limiting:** GoClaw keeps at most 5 pending requests in total, across all channels, to prevent spam. The oldest request is dropped when a new one arrives over the limit.
- **Cross-Platform Identity:** Approving a user on Discord does not automatically approve them on Teams. To let the same person in on another channel, link that channel's account to their existing GoClaw user: `./goclaw pairing link u_123456 telegram 123456789` (user ID, channel, platform account ID). The same restart rule applies as for a CLI approval.
