From 5f9c64fb823b51ebd9d0932b892b5876536179dd Mon Sep 17 00:00:00 2001 From: Avi Date: Sat, 19 Sep 2026 20:50:12 -0500 Subject: [PATCH] =?UTF-8?q?checkpoint:=20sync=20to=20edd4e56=20=E2=80=94?= =?UTF-8?q?=20accept=20NIP-46=20connect=20*response*=20shape=20(root-cause?= =?UTF-8?q?=20fix)=20(2026-09-19)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHECKPOINT-encryption.md | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/CHECKPOINT-encryption.md b/CHECKPOINT-encryption.md index 68a0a49..5c08463 100644 --- a/CHECKPOINT-encryption.md +++ b/CHECKPOINT-encryption.md @@ -1,3 +1,73 @@ +# Checkpoint — Amber pairing: accept the NIP-46 connect *response* shape (2026-09-19) + +## Where things are +- Project: `/home/avi/Projects/Keynctr` +- Branch: `master` @ **`edd4e56`** ("fix(pairing): accept the NIP-46 connect + *response* shape Amber actually sends"). Previous feature HEADs: + `21c522b`, `188b2eb`, `aedde8f`, `759b5dd`, `5aa122d`, `f59c2b1`. +- Working tree: clean for tracked files. Untracked intentionally NOT + committed: `COSMIC_THEME.md`, `KeynectrAppIconPossibility02.jpeg`, + `deferred/` (stays deferred). +- Release binary rebuilt at `edd4e56` (2026-09-19 ~20:50) — Electron spawns + this one. **No live Amber scan has run against this build yet.** +- Verification (all green at `edd4e56`): `cargo fmt --check` clean, + `cargo test` **208 unit + 3 e2e passed / 0 failed**, `cargo clippy + --all-targets` 0 warnings, `cargo build --release` green. Frontend: + `npm test` **116 passed**, `npm run typecheck` / `lint` / + `format:check` / `build` / `electron:build` all clean. + +## What was completed since the last checkpoint +- **The likely root cause of the whole Amber pairing failure (`edd4e56`)**: + for a client-initiated `nostrconnect://` scan, NIP-46 specifies the signer + sends a connect **response** — `{"id":…,"result":""}` — not a + connect *request* (spec: "the _remote-signer_ … then sends `connect` + *response* event to the `client-pubkey`"; result is `"ack"` OR the secret; + "Client discovers remote-signer-pubkey from connect response author"). + `run_pairing_task` only recognized an inbound `{"method":"connect"}` + request. A bare `{"result":…}` parsed into `RawRequest` with an *empty* + method (the lenient deserializer never fails, so the old "not a NIP-46 + request" log couldn't fire) and was silently swallowed as "pre-handshake + '' ignored" — Amber showed "connected", Keynctr sat in the pairing loop + until timeout, no profile row, nothing persisted. That exactly matches the + original symptom and the observed 89-byte plaintext + (`{"id":"…","result":"<16-byte-hex-secret>"}` fits 65–96 B). + The pairing loop now verifies the echoed secret (or `"ack"`) directly and + proceeds to identity adoption; a signer-sent `error` fails fast with the + signer's message; a wrong secret is still ignored as spoofing; the legacy + request shape keeps working. Trace lines added for each outcome. +- **e2e regression lock**: `run_fake_scanner` takes a `connect_shape` + param; new `nip46_qr_pairing_connect_response_shape` test simulates + Amber's spec shape end-to-end. Confirmed RED on the pre-fix parser + (pairing times out) and GREEN with the fix. + +## Commits added (newest first) +- `edd4e56` fix(pairing): accept the NIP-46 connect *response* shape Amber + actually sends + +## How to reproduce / exercise +- Dev loop (unchanged): `npx vite --port 5173` in `frontend/` FIRST, then + `NOSTR_GUI_DEV_URL=http://localhost:5173 KEYNCTR_ENABLE_GPU=1 npx electron .`. +- GUI: Signer mode -> "Show QR" -> scan in Amber -> approve. Expected now: + trace log shows `connect response accepted (secret echo verified)` then + `identity adopted: npub=… — CONNECTED`, and a new profile row appears. +- Watch during a live scan: `bash ~/Tools/keynctr-debug/watch-pairing.sh 240` + (new helper — tails trace/capture, prints any new lines). +- E2E: `cargo test --test nip46_e2e` (no network; 3 tests incl. both + connect shapes). + +## Outstanding / next steps +1. **Live Amber re-scan required** to confirm end-to-end (cannot be done + from an unattended run). If it still stalls, `pairing-trace.log` names + the exact stop point. +2. If trace shows `pre-handshake 'get_public_key' ignored`, relax the + connect-only gate (the log line names it outright). +3. `publish_profile_metadata` (kind 0) still signs locally — reroute + through `Signing` for external profiles (P2). +4. Step 5 (KDF upgrade), Step 6 (undo preserves ProfileSummary), Step 7 + (rename pass incl. `homepage` URL). + +--- + # Checkpoint — durable pairing trace log + forensics-file hygiene (2026-09-18) ## Where things are