checkpoint: sync to edd4e56 — accept NIP-46 connect *response* shape (root-cause fix) (2026-09-19)

This commit is contained in:
Avi 2026-09-19 20:50:12 -05:00
commit 5f9c64fb82

View file

@ -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":"<secret>"}` — 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) # Checkpoint — durable pairing trace log + forensics-file hygiene (2026-09-18)
## Where things are ## Where things are