R2D2-MERIDIAN/crates/meridian-pairing-cli
Joshua Belke de4cfec61e feat: rebrand Codebase Chat to Meridian
Renames the product to Meridian across 1826 files: 24 crates
(codebase-chat-* -> meridian-*), the Flutter package, env vars
(CODEBASE_CHAT_* -> MERIDIAN_*), the deep-link scheme (meridian://),
Postgres GUCs, Helm charts, skills, and the agent surface.

White-labels every external identity onto self-hosted infrastructure:
hosts move from *.codebase.design to *.meridian.r2d2.office.ilab.zone,
images to registry.r2d2.office.ilab.zone/meridian-*, the repo slug to
r2d2/meridian, and bundle IDs to zone.ilab.office.r2d2.meridian.*.
The Block staging relay and the four Block-internal build repos are not
reachable from a self-hosted deployment and are no longer referenced.

The mark becomes a pixel M. It is 5x6 rather than a square 5x5 because
the avatar-pile mask asserts the hole clears the glyph's right edge:
at 5x5 that edge moves from 68.4% to 73% of the tile, which overruns the
56px team-card hole outright and leaves the other three piles under a
pixel. At 5x6 the aspect is 0.833 against the retired C's 0.800, so all
four masks clear it unchanged. All 59 materializations are regenerated
from the generators; `just check-brand` passes.

Four things are deliberately NOT renamed, because they match what was
*stored* rather than what now ships. Rewriting any of them makes a
migration no-op on exactly the installs it exists to repair:

- Frozen migrations 0001-0030. Their SHA-256 digests are pinned in
  n-minus-one-pins.json and embedded in the attested N-1 image. The new
  vocabulary lands as forward migration 0031, which dual-reads all three
  generations' GUCs, lock names, app profiles and mesh d_tags. The
  push-gateway's own 0001 is likewise restored byte-identical, with
  0002 widening its app_profile CHECK.
- Legacy namespace chains. xyz.block.codebasechat.app is *prepended* to
  LEGACY_RELEASE_IDENTIFIERS and its dev/localStorage twins, per the rule
  in legacy_dirs.rs that a previous rename already broke once.
- Bead IDs (codebaseChat-*), which are cited from commits and docs.
- CHANGELOG history and upstream issue links.

The Codebase-era persona ids are added to RETIRED_PERSONAS with their
prompts verbatim, but deliberately NOT to RETIRED_PERSONA_REPLACEMENTS:
that map drives migration::retire_agents, which deletes deployed
instances, and its safety argument is that the successor is already
deployed alongside. That held for Buzz->Codebase; nothing provisions a
Meridian agent on an install that already onboarded, so mapping these
would delete a working agent and leave nothing in its place.

The brand-guard self-test changes axis: the M is symmetric about its
vertical axis, so a mirrored M *is* the canonical M and asserting a
rejection there would assert a bug. It now flips top-to-bottom (the mark
reads as a W) and pins the horizontal symmetry so the coupling is visible
if the mark ever becomes asymmetric again.

Verified: cargo check --workspace --all-targets clean, just fix-all
clean, flutter analyze clean, just check-skills pass, check-brand 59/59,
brand-core 9/9, avatarPileMask 4/4, starter-avatar contrast 2/2.

Signed-off-by: Joshua Belke <joshua@innovationhub-act.org>
2026-08-04 14:06:04 -04:00
..
src feat: rebrand Codebase Chat to Meridian 2026-08-04 14:06:04 -04:00
Cargo.toml feat: rebrand Codebase Chat to Meridian 2026-08-04 14:06:04 -04:00
README.md feat: rebrand Codebase Chat to Meridian 2026-08-04 14:06:04 -04:00

meridian-pair

CLI tool for testing the NIP-AB device pairing protocol end-to-end. Exercises the full protocol over a live Nostr relay — designed for interop testing and NIP submission, not production use.

Quick Start

cargo build --release -p meridian-pairing-cli

# Terminal 1 — source (holds the secret)
./target/release/meridian-pair source --relay wss://relay.damus.io

# Terminal 2 — target (receives the secret)
./target/release/meridian-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.

meridian-pair source --relay <RELAY_URL> [--nsec <BECH32_NSEC>]
  • --relay — WebSocket relay URL (default: wss://relay.damus.io)
  • --nsec — bech32 nsec to transfer. If omitted, generates a throwaway test key.

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.

meridian-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.

meridian-pair test-vectors

Testing Against a Local Meridian Relay

The CLI supports NIP-42 authentication, so it works with Meridian relays out of the box.

Prerequisites

  • Docker running (for Postgres, Redis, etc.)
  • Meridian relay built: cargo build --release -p meridian-relay

Start the relay

just setup                          # Docker services + schema
cargo build --release --workspace
screen -dmS relay bash -c "./target/release/meridian-relay 2>&1 | tee /tmp/meridian-relay.log"
sleep 3 && curl -s http://localhost:3000/health   # → "ok"

Run the E2E test

An automated test script using expect is provided:

.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

# Terminal 1
./target/release/meridian-pair source --relay ws://localhost:3000

# Terminal 2
./target/release/meridian-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.