diff --git a/CHECKPOINT-encryption.md b/CHECKPOINT-encryption.md index fc3881d..6bba0a7 100644 --- a/CHECKPOINT-encryption.md +++ b/CHECKPOINT-encryption.md @@ -1,3 +1,68 @@ +# Checkpoint — NIP-46 session restore on startup (2026-09-24) + +## Where things are +- Project: `/home/avi/Projects/Keynctr` +- Branch: `master` @ **`0982dad`** ("feat(nip46): restore saved signer + sessions on startup/unlock — no fresh scan"). Previous: `73bf17c` + (checkpoint), `f53bc56` (sign timeout leash). +- Working tree: clean for tracked files. Untracked intentionally NOT + committed: `COSMIC_THEME.md`, `KeynectrAppIconPossibility02.jpeg`, + `deferred/` (stays deferred). +- Release binary: **rebuilt at `0982dad`**. Frontend untouched — no + renderer rebuild needed. Restart Electron before retesting. + +## What was completed this session +1. **Session restore without a fresh scan (`0982dad`)**: the WIP from + the Sep-23 session (item 2 of the previous next-steps) is finished + and committed. Amber remembers our *client pubkey* as the identity + of an approved connection for its whole life, so the client keypair + minted at pairing is now persisted in the vault + (`Vault::connection_client_keys` — encrypted under the vault key + exactly like connection secrets, keyed by the same `VaultRef`, and + re-keyed to the identity ref when the handshake resolves it). +2. **Re-dial path**: `reactivate_saved_sessions()` picks the active + profile's live connection (or any other live one), rebuilds the + exact wire identity, re-derives the NIP-44 conversation key, and + re-sends `connect` — no QR/bunker scan. It is called at `serve()` + for unencrypted vaults and after `UnlockVault` for encrypted ones; + a restore failure can never block the GUI. +3. **Cross-account guard**: restored sessions pin `expected_identity` + before dialing; `adopt_identity` refuses (never adopts) a signer + that answers as a different account — different Amber account, + mistyped bunker, or relay spoof all fail closed. +4. Legacy connection rows without a stored client key are skipped + (they need one fresh scan, after which they become restorable too). +- Verification (all green at `0982dad`): `cargo test` **216 unit + 5 + e2e passed / 0 failed** — incl. the new + `nip46_session_restore_redials_and_refuses_wrong_identity` e2e + (fresh pairing → simulated restart → re-dial connects → a fake + Amber answering as a different key is refused) and 3 new vault unit + tests (plaintext roundtrip, encrypted fail-closed, legacy-vault + parsing). `cargo clippy --all-targets` 0 warnings, `cargo fmt + --check` clean, `cargo build --release` green. Frontend untouched. + +## Commits added (newest first) +- `0982dad` feat(nip46): restore saved signer sessions on startup/unlock — no fresh scan + +## How to resume / reproduce +- Restart Electron (new release binary). With the vault already + unlocked/unencrypted, the backend logs `[NIP46] restoring session: + peer=... as npub1...` then `identity check on restored session: + PASS` and the profile goes Connected without showing Amber a new + scan. CLI trace: `~/Tools/keynctr-debug/` logs. +- Then do the still-pending live proof: Publish name / publish a note + and approve in Amber within 2 minutes (120s leash from `f53bc56`). + +## Outstanding / next steps +1. **Live sign/publish through real Amber** (covers both the 120s + leash and the restored session in one shot). +2. Prune the 11 stale profileless `nip46_connections` rows (cosmetic; + restore already skips them). +3. Remote picture/nip05 edits, KDF upgrade (Step 5), rename pass + (Step 7) — unchanged. + +--- + # Checkpoint — sign_event given the human-approval timeout leash (2026-09-23 evening) ## Where things are