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> |
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| README.md | ||
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.