Files
buzz/crates/buzz-pairing-cli/README.md
npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e 2caf293fab feat(pairing): support explicit interop payloads
Add paired payload type and content flags while preserving the existing nsec behavior. Document the Buzz workspace payload shape and cover argument validation and verbatim interop payload handling.

Co-authored-by: npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e <e18f3511303812c437d487ac4bf46ad897dc46946699b18ab2e60bf8ee0ea851@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e <e18f3511303812c437d487ac4bf46ad897dc46946699b18ab2e60bf8ee0ea851@sprout-oss.stage.blox.sqprod.co>
2026-07-13 17:39:57 -07:00

143 lines
5.8 KiB
Markdown

# buzz-pair
CLI tool for testing the [NIP-AB device pairing protocol](../buzz-core/src/pairing/NIP-AB.md) end-to-end. Exercises the full protocol over a live Nostr relay — designed for interop testing and NIP submission, not production use.
## Quick Start
```bash
cargo build --release -p buzz-pairing-cli
# Terminal 1 — source (holds the secret)
./target/release/buzz-pair source --relay wss://relay.damus.io
# Terminal 2 — target (receives the secret)
./target/release/buzz-pair target --show-secret
# paste the QR URI from terminal 1 when prompted
```
Both sides display a 6-digit SAS code. Confirm they match on each side, and the key transfers.
## Subcommands
### `source`
Acts as the device holding the secret. Generates an ephemeral keypair and session secret, displays a `nostrpair://` QR URI, waits for a target to connect, performs SAS verification, and sends the payload.
```
buzz-pair source --relay <RELAY_URL> [--nsec <BECH32_NSEC>]
buzz-pair source --relay <RELAY_URL> --payload-type <TYPE> --payload <CONTENT>
```
- `--relay` — WebSocket relay URL (default: `wss://relay.damus.io`)
- `--nsec` — bech32 nsec to transfer. If omitted, generates a throwaway test key.
- `--payload-type` — type for explicit payload content: `nsec`, `bunker`, `connect`, or `custom`.
- `--payload` — explicit payload content. Must be provided with `--payload-type`; it is sent verbatim so interop tests can exercise both valid and malformed payloads.
`--payload-type` and `--payload` let the generic interop tool exercise application-defined payloads without baking an application's schema into the CLI. For example, a Buzz workspace payload can be sent with:
```bash
buzz-pair source \
--relay wss://relay.example.com \
--payload-type custom \
--payload '{"relayUrl":"https://relay.example.com","pubkey":"<HEX_PUBKEY>","nsec":"<BECH32_NSEC>"}'
```
The workspace `relayUrl` is the HTTP API base URL, while `--relay` remains the WebSocket relay used for the pairing exchange.
### `target`
Acts as the receiving device. Reads a `nostrpair://` URI from stdin, connects to the relay encoded in the URI, sends an offer, verifies SAS, and receives the payload.
```
buzz-pair target [--relay <OVERRIDE_URL>] [--show-secret]
```
- `--relay` — Override the relay URL from the QR code
- `--show-secret` — Print the received secret to stdout (off by default for safety)
### `test-vectors`
Prints all derived cryptographic values from the NIP-AB spec's fixed test keys. Useful for verifying implementations against the spec.
```
buzz-pair test-vectors
```
## Testing Against a Local Buzz Relay
The CLI supports NIP-42 authentication, so it works with Buzz relays out of the box.
### Prerequisites
- Docker running (for Postgres, Redis, etc.)
- Buzz relay built: `cargo build --release -p buzz-relay`
### Start the relay
```bash
just setup # Docker services + schema
cargo build --release --workspace
screen -dmS relay bash -c "./target/release/buzz-relay 2>&1 | tee /tmp/buzz-relay.log"
sleep 3 && curl -s http://localhost:3000/health # → "ok"
```
### Run the E2E test
An automated test script using `expect` is provided:
```bash
.scratch/e2e-pair-local.sh
```
This spawns source and target as PTY-driven subprocesses, feeds the QR URI between them, waits for both SAS codes to appear, delays to ensure relay subscriptions are registered, then confirms SAS on both sides. Prints `PASS` or `FAIL` with the SAS codes.
**Requirements:** `expect` (macOS: built-in at `/usr/bin/expect`)
**Environment variables:**
| Variable | Default | Description |
|----------|---------|-------------|
| `RELAY_URL` | `ws://localhost:3000` | Relay to test against |
| `TEST_TIMEOUT` | `45` | Per-step timeout in seconds |
| `SOURCE_CONFIRM_DELAY_MS` | `3000` | Delay after SAS display before confirming (lets relay register subscriptions) |
### Manual two-terminal test
```bash
# Terminal 1
./target/release/buzz-pair source --relay ws://localhost:3000
# Terminal 2
./target/release/buzz-pair target --show-secret
# paste the nostrpair:// URI, confirm SAS on both sides
```
## Protocol Overview
```
Source Relay Target
────── ───── ──────
Generate ephemeral keys
Display QR (pubkey+secret+relay)
Subscribe kind:24134 Scan QR
Generate ephemeral keys
Subscribe kind:24134
Wait for EOSE
◄─────────────────────── Send offer
Verify session_id
Compute SAS ◄──────────────────────────────────────────► Compute SAS
Display: "047291" Display: "047291"
[User confirms codes match]
Send sas-confirm ──────────────►─────────────────────►
Verify transcript_hash
[User confirms]
Send payload ──────────────────►─────────────────────►
Decrypt + import
◄─────────────────────── Send complete
Done Done
```
All events are NIP-44 encrypted, signed with ephemeral keys, and addressed via `p` tags. The relay sees only opaque ciphertext between throwaway pubkeys.