Orion vault — clean initial history
Knowledge vault (Orion/PARA) migrated from the pre-Orion 484vault on 2026-10-01. Deliberately orphaned: prior history contained a plaintext password and stays local-only on branch archive/pre-boilerplate-history. Secrets and live Hermes state are gitignored.
This commit is contained in:
commit
a66996ac10
233 changed files with 103810 additions and 0 deletions
34
1. Projects/Products/Keynctr/PROD-1_hub.md
Normal file
34
1. Projects/Products/Keynctr/PROD-1_hub.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
type: project
|
||||
id: PROD-1
|
||||
area: Products
|
||||
done_when: "Keynctr is polished, packaged, and released for others to use as a shared Nostr account manager, not just Avi's own setup."
|
||||
status: open
|
||||
updated: 2026-10-01
|
||||
tags:
|
||||
- hub
|
||||
- products
|
||||
---
|
||||
|
||||
# PROD-1 Keynctr
|
||||
|
||||
## What this is
|
||||
|
||||
Nostr account manager (desktop, Rust/Electron): profiles with generated keys, feed management, NIP-46 remote signing (Amber).
|
||||
|
||||
## Tasks
|
||||
|
||||
_See `sources/` — pre-Orion notes preserved verbatim; promote live tasks here as they're worked._
|
||||
|
||||
## Open items
|
||||
|
||||
_None registered yet (migration)._
|
||||
|
||||
## Key files
|
||||
|
||||
- Code: `~/Projects/Keynctr/`
|
||||
- Sources (pre-Orion notes, preserved): `sources/`
|
||||
|
||||
## People
|
||||
|
||||
_None yet._
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
|
||||
|
||||
#nostr #accountmanger #feedmanager
|
||||
|
||||
pass [REDACTED 2026-10-01 — secrets do not belong in vault notes]
|
||||
# <font color="#f79646">Terminal Command To launch Dev Mode</font>
|
||||
|
||||
Use the dev-server mode — renderer changes (React/CSS/TS in frontend/src) then appear instantly via hot reload:
|
||||
# Terminal 1
|
||||
```
|
||||
cd /home/avi/Projects/Keynctr/frontend && npx vite --port 5173
|
||||
```
|
||||
# Terminal 2
|
||||
```
|
||||
cd /home/avi/Projects/Keynctr/frontend && NOSTR_GUI_DEV_URL=http://localhost:5173 KEYNCTR_ENABLE_GPU=1 npx electron . 2>&1 | tee ~/Tools/keynctr-debug/el.log
|
||||
```
|
||||
|
||||
### To Kill App
|
||||
```
|
||||
pkill -f "electron ." ; sleep 2; pgrep -af "electron .|keynectr serve" || echo "all clear"
|
||||
```
|
||||
|
||||
If anything still prints, force it:
|
||||
|
||||
```
|
||||
pkill -9 -f "electron ."; pkill -9 -f "keynectr serve"; pgrep -af "electron .|keynectr serve" || echo "all clear"
|
||||
```
|
||||
|
||||
You want the final all clear with no process lines. (npx vite can stay running — only Electron and keynectr serve must die.) Then relaunch Electron fresh per the previous message.
|
||||
|
||||
---
|
||||
|
||||
# Nostr is a decentralized social network.
|
||||
No central company runs this network. Instead, your account is a pair of mathematical keys:
|
||||
|
||||
- A **public key**, which you share like an address.
|
||||
- A **secret key**, which you guard like a master password.
|
||||
|
||||
|
||||
Posts are distributed through independent servers called **relays**. Anyone can run a relay, and no one can lock you out of the network.
|
||||
|
||||
This app gives you a clean, secure desktop window into that world.
|
||||
|
||||
### What It Does For You
|
||||
|
||||
- **Manages your identities**
|
||||
Create profiles with friendly names like “Personal” or “Work.” The app generates and stores the secret keys behind them. You can switch between identities anytime. Your secret keys stay inside the app’s protected core—screens are designed so they physically cannot display or leak them.
|
||||
|
||||
- **Lets you post**
|
||||
Write a note in the **Compose** tab. Optionally attach images (uploaded automatically to an image host) or paste links (the app fetches preview cards). When you publish, you’ll see exactly which relays accepted your post and which didn’t.
|
||||
|
||||
- **Lets you read**
|
||||
The **Feed** tab shows recent notes from your relays over the last 24 hours—either everyone’s notes or just the people your profile follows.
|
||||
|
||||
- **Connects you to the network**
|
||||
Use the **Relays** tab to add, remove, enable, disable, and test relay servers.
|
||||
|
||||
- **Protects other apps from having your keys**
|
||||
Instead of pasting your secret key into random Nostr clients, those clients can ask this app to sign things for them remotely. Every request shows up as **“Sign this? / Decrypt this?”** with an **Approve** or **Reject** button. Nothing happens without your click.
|
||||
|
||||
- **Locks up when you walk away**
|
||||
Set a vault password once. All secret keys on disk become unreadable without it—while profile names remain visible so you can still browse.
|
||||
|
||||
|
||||
### Typical First Session
|
||||
|
||||
1. **Open the app** → **Profiles** → **Create profile** → give it a name.
|
||||
2. **Relays** → confirm at least one is enabled.
|
||||
3. **Compose** → write something → **Publish**.
|
||||
4. **Feed** → see your note appear alongside everyone else’s.
|
||||
|
||||
That’s it—no account signup, no email, no phone number. Your identity is your key pair, and this app keeps it safe while making it usable.
|
||||
|
||||
## Installation
|
||||
|
||||
Arch
|
||||
|
||||
```
|
||||
sudo pacman -U ./shonar-desktop-0.1.0-1-x86_64.pkg.tar.zst
|
||||
# (waits while it downloads the Whisper model ~142 MB as part of install)
|
||||
shonar-desktop # or find "SHONAR Desktop" in the app menu
|
||||
```
|
||||
|
||||
Debian
|
||||
|
||||
```
|
||||
sudo apt install openjdk-17-jdk python3 python3-venv mpv
|
||||
mkdir -p ~/Projects && tar xzf shonar-desktop-6efec57.tar.gz -C ~/Projects
|
||||
cd ~/Projects/shonar-desktop && ./setup-standalone.sh # engine venv + Whisper model
|
||||
sudo apt install ~/shonar-desktop_0.1.0-2_amd64.deb
|
||||
shonar-desktop # or from the app menu
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
|
||||
#nostr #accountmanger #feedmanager
|
||||
|
||||
pass [REDACTED 2026-10-01 — secrets do not belong in vault notes]
|
||||
# <font color="#f79646">Terminal Command To launch Dev Mode</font>
|
||||
|
||||
Use the dev-server mode — renderer changes (React/CSS/TS in frontend/src) then appear instantly via hot reload:
|
||||
# Terminal 1
|
||||
```
|
||||
cd ~/Projects/Keynctr/frontend
|
||||
npm run dev
|
||||
```
|
||||
# Terminal 2
|
||||
```
|
||||
cd ~/Projects/Keynctr/frontend
|
||||
NOSTR_GUI_DEV_URL=http://localhost:5173 npm start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Nostr is a decentralized social network.
|
||||
No central company runs this network. Instead, your account is a pair of mathematical keys:
|
||||
|
||||
- A **public key**, which you share like an address.
|
||||
- A **secret key**, which you guard like a master password.
|
||||
|
||||
|
||||
Posts are distributed through independent servers called **relays**. Anyone can run a relay, and no one can lock you out of the network.
|
||||
|
||||
This app gives you a clean, secure desktop window into that world.
|
||||
|
||||
### What It Does For You
|
||||
|
||||
- **Manages your identities**
|
||||
Create profiles with friendly names like “Personal” or “Work.” The app generates and stores the secret keys behind them. You can switch between identities anytime. Your secret keys stay inside the app’s protected core—screens are designed so they physically cannot display or leak them.
|
||||
|
||||
- **Lets you post**
|
||||
Write a note in the **Compose** tab. Optionally attach images (uploaded automatically to an image host) or paste links (the app fetches preview cards). When you publish, you’ll see exactly which relays accepted your post and which didn’t.
|
||||
|
||||
- **Lets you read**
|
||||
The **Feed** tab shows recent notes from your relays over the last 24 hours—either everyone’s notes or just the people your profile follows.
|
||||
|
||||
- **Connects you to the network**
|
||||
Use the **Relays** tab to add, remove, enable, disable, and test relay servers.
|
||||
|
||||
- **Protects other apps from having your keys**
|
||||
Instead of pasting your secret key into random Nostr clients, those clients can ask this app to sign things for them remotely. Every request shows up as **“Sign this? / Decrypt this?”** with an **Approve** or **Reject** button. Nothing happens without your click.
|
||||
|
||||
- **Locks up when you walk away**
|
||||
Set a vault password once. All secret keys on disk become unreadable without it—while profile names remain visible so you can still browse.
|
||||
|
||||
|
||||
### Typical First Session
|
||||
|
||||
1. **Open the app** → **Profiles** → **Create profile** → give it a name.
|
||||
2. **Relays** → confirm at least one is enabled.
|
||||
3. **Compose** → write something → **Publish**.
|
||||
4. **Feed** → see your note appear alongside everyone else’s.
|
||||
|
||||
That’s it—no account signup, no email, no phone number. Your identity is your key pair, and this app keeps it safe while making it usable.
|
||||
17
1. Projects/Products/Keynctr/sources/keynctr 1.md
Normal file
17
1. Projects/Products/Keynctr/sources/keynctr 1.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
project: keynctr
|
||||
status: active
|
||||
last-updated: 2026-09-04T16:48:00-05:00
|
||||
hermes-owned: true
|
||||
local-path: /home/avi/Projects/Keynctr/
|
||||
---
|
||||
|
||||
# Keynctr (redirect)
|
||||
|
||||
> **Moved (2026-09-04):** the canonical project file is now
|
||||
> **`01-PROJECTS/keynctr.md`** — the path the startup protocol references.
|
||||
> This root-level copy was a duplicate and is kept only as a redirect so old
|
||||
> links don't dangle. Edit the file under `01-PROJECTS/`, not this one.
|
||||
|
||||
- Local code: `/home/avi/Projects/Keynctr/`
|
||||
- Checkpoint: `/home/avi/Projects/Keynctr/CHECKPOINT-encryption.md`
|
||||
244
1. Projects/Products/Keynctr/sources/keynctr.md
Normal file
244
1. Projects/Products/Keynctr/sources/keynctr.md
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
---
|
||||
project: keynctr
|
||||
status: active
|
||||
last-updated: 2026-09-25T23:00:00-05:00
|
||||
hermes-owned: true
|
||||
local-path: /home/avi/Projects/Keynctr/
|
||||
tech-stack: [Rust, Electron, React, TypeScript]
|
||||
---
|
||||
|
||||
# Keynctr
|
||||
|
||||
## Overview
|
||||
A desktop GUI for managing Nostr identities and publishing notes, with a focus on
|
||||
key security through vault encryption and a modular signer abstraction layer.
|
||||
Rust backend (JSON-lines IPC on stdio) + Electron/React frontend.
|
||||
|
||||
**Ultimate goal:** Keynctr itself never holds or transmits secret key
|
||||
material. In embedded mode keys live only in the encrypted local vault; in
|
||||
external-signer mode (the most secure of the three ways, and the current
|
||||
focus per Avi's directive) the keys live on the signer device — Amber on the
|
||||
phone — and Keynctr only ever sends signing *requests*, approving each use at
|
||||
the signer. The Rust core does all signing/relay work; the Electron UI never
|
||||
touches secret material. Usable as GUI *and* same-core CLI, and doubling as a
|
||||
NIP-46 bunker for other apps.
|
||||
|
||||
## Architecture
|
||||
- **Frontend:** Electron + React + TypeScript (`frontend/`); Prettier-formatted.
|
||||
- **Backend:** Rust crate `keynectr` (`src/`); `cargo build --release` binary.
|
||||
- **Storage:** a single encrypted vault file (`profiles_vault.json`) holding
|
||||
profiles, signer modes, NIP-46 connections, and encrypted connection secrets.
|
||||
- **Key files:**
|
||||
- `src/main.rs`: CLI entry point / JSON-lines IPC serve.
|
||||
- `src/ipc.rs`: dispatcher.
|
||||
- `src/signer/`: `Signer` trait (permission checks now async),
|
||||
`Signing` enum, `EmbeddedSigner`, `Nip46ClientSigner` (the active path),
|
||||
`permissions.rs`, `backend.rs` (`SigningBackend`, `VaultRef`, `SigningError`).
|
||||
- `src/bunker.rs`: legacy server-mode bunker (bunker:// host role).
|
||||
- `src/vault.rs`: vault load/save, migrations, encrypted `connection_secrets`.
|
||||
- `tests/nip46_e2e.rs`: in-process NIP-46 e2e test (mini relay + fake Amber).
|
||||
- `CHECKPOINT-encryption.md` (repo root): the standing, current checkpoint —
|
||||
always read this first for "where things are."
|
||||
|
||||
## Current Status
|
||||
**External signer (the most secure mode) works end-to-end, proven by test.**
|
||||
Headline commits since the vault was last updated:
|
||||
- `f917e5e` Amber-compatible handshake: `bunker://` URIs, deferred identity
|
||||
(URI key is a per-connection comms key, never identity; real identity learned
|
||||
via `get_public_key` after approval), 120s approval window, fail-closed while
|
||||
Connecting.
|
||||
- `c096705` vault-load rewrite fix (migration no longer re-saves every start).
|
||||
- `85756df` `bunker://` accepted frontend-side + async permission surface +
|
||||
`tests/nip46_e2e.rs` — full e2e: local relay, fake Amber with human-approval
|
||||
delay, identity assertions, `sign_event` verification, vault persistence
|
||||
(remote profiles store no secret material).
|
||||
- `38499d4`→`3d5302f` QR pairing (client-initiated `nostrconnect://` flow),
|
||||
IPC lazy-init fix, Electron allowlist fix, and real kind-0 display
|
||||
name/picture adoption for paired identities (3s-capped, falls back to label).
|
||||
|
||||
Verification at last check (2026-09-12): `cargo test` 200 + e2e green, clippy
|
||||
0 warnings, fmt clean, release build green; frontend 116 tests + typecheck +
|
||||
lint + build green.
|
||||
|
||||
### 2026-09-18 — pairing trace milestone
|
||||
- `21c522b` Durable pairing trace: every pairing decision point now appends
|
||||
a timestamped line to `~/Tools/keynctr-debug/pairing-trace.log` (started,
|
||||
inbound 24133, decrypt-fail with real NIP-44 error, exact unparsable
|
||||
payload, pre-handshake method, connect answered, identity adopted,
|
||||
session failed). Backend stderr only reached the Electron console and
|
||||
/tmp logs got cleaned, so failed live handshakes previously left no trace.
|
||||
- Found forensics contamination: pairing-capture.jsonl lines from Sep 18
|
||||
were the e2e harness's loopback fake-scanner events, not Amber — the
|
||||
capture path was hardcoded. Test events pruned (backup kept) and loopback
|
||||
pairings now skip the capture. Net: no real Amber scan has run against
|
||||
the `188b2eb` lenient parser yet; the next re-scan's trace.log tail will
|
||||
name exactly where the handshake stops, no terminal capture needed.
|
||||
- Verification at `21c522b`: cargo test 208 + 2 e2e green, clippy 0
|
||||
warnings, fmt clean, release rebuilt; frontend all green.
|
||||
|
||||
### 2026-09-16 — pairing debug milestone
|
||||
- `188b2eb` RawRequest deserializer rewritten as universal coercion: any
|
||||
valid JSON now parses (numeric/missing ids → text, object-shaped params,
|
||||
double-encoded request strings). The strict derive was still dropping
|
||||
Amber's connect request even after `aedde8f`. Decrypt failures now log
|
||||
the real NIP-44 error (HMAC vs padding vs wrong key) and the exact
|
||||
decrypted payload instead of a generic message.
|
||||
- Forensics: all 4 captured pairing frames (`~/Tools/keynctr-debug/
|
||||
pairing-capture.jsonl`, latest Sep 16 20:11) are 163-byte spec-valid
|
||||
NIP-44 v2 payloads (plaintext 65–96 bytes; the observed 89 fits) — so
|
||||
Amber's frames decrypt fine and the failure was JSON-shape parsing.
|
||||
- IMPORTANT: `/tmp/keynctr-el*.log` is gone (tmp-cleaner). To see pairing
|
||||
diagnostics launch from a terminal:
|
||||
`NOSTR_GUI_DEV_URL=http://localhost:5173 KEYNCTR_ENABLE_GPU=1 npx electron . 2>&1 | tee ~/Tools/keynctr-debug/el.log`
|
||||
then re-scan the QR in Amber.
|
||||
- Verification at `188b2eb`: cargo test 208 + 2 e2e green, clippy 0
|
||||
warnings, fmt clean, release rebuilt; frontend all green.
|
||||
|
||||
### 2026-09-27 — multi-account switching + permissions UI + updater fix
|
||||
- **Multi-account switching shipped (`c89b31a`, Option A):** pairing/connecting a second signer PARKS the live session (never revoked; row+secret+client key intact); `SelectProfile` re-dials the target profile's saved session (local-key profiles leave the session alone); new `nip46_cancel_pairing` IPC restores the parked session on QR cancel — both Add-profile and Signer Mode cancels use it. Verified: cargo test 216 + 6 e2e green (new two-fake-Amber switch test).
|
||||
- **Step 4 first slice (`adbc7c2`):** `Nip46Status` carries declared `perms=` list + expiry; Signer Mode shows a Permissions panel (grant rows, or a signer-side-enforcement note). Always-allow grants are now kind-scoped: a `sign_event` grant records the approved request's kind; legacy kind-less grants keep all-kinds meaning (`serde(default)`, never bricked existing vault rows); enforced in `bunker.rs` + `nip46_client.rs` via `has_signer_grant(peer, method, event_kind)`.
|
||||
- **Updater fix (`fa59b63`):** `updates.rs` `run()` augments the inherited PATH with `~/.cargo/bin`, `~/.local/bin`, mise/asdf shims, `/usr/local/bin` — Check-for-updates was dead under the desktop-launcher env; verified live under `env -i PATH=/usr/bin:/bin`.
|
||||
- Status at end of night: tree clean @ `118f5d3`, 7 ahead of origin (push needs per-use token); cargo test 219 + 6 e2e green, clippy 0, frontend 135 tests green, release rebuilt 22:43.
|
||||
- Open: live eyeball of Permissions panel (relaunch — running serve predates commits), approve kind-1 "Always allow" then send kind-3 and confirm it prompts; two-account live pass with real Amber; Step 5 KDF; Step 6 undo; Step 7 rename/hygiene.
|
||||
|
||||
### 2026-09-28 — Moi "workshop" themes + no-restart updater
|
||||
- **Workshop themes (`add956a`, `c18f59a`, `de804c8`):** user's "the theme I asked you to add" = the Moi project's Cybernetic Workshop look, NOT Cosmic Stardust. Pitfall: Moi's look isn't just palette tokens — `site.css` paints a 24px hairline graph-paper grid + mint/clay radial washes over the paper; matching requires the background stack, not just colors. `workshop-dark` accent moved to `#007AFF` per request; white logo on dark themes (invert filter).
|
||||
- **No-restart updater (`dcc701f`):** `app:selfupdate` IPC runs npm build + `cargo build --release` with augmented PATH, kills the backend child; the next request picks up the new binary — no app restart needed.
|
||||
- **Auto-naming fix:** pairing a new Amber connection showed generic "Amber"; persistent kind-0 identity backfill (`5b60ae3`) + stdin EAGAIN crash fix (`9770f46`). Suite at checkpoint `f905cbc`: 221 unit + 6 e2e, clippy 0, frontend 139 green.
|
||||
|
||||
## Active Tasks
|
||||
- [x] On-device Amber round-trip: pair from the real Amber app on the phone,
|
||||
sign a note, publish. The e2e test proves the protocol; this proves Amber.
|
||||
- [ ] Reroute kind-0 profile metadata publish through the external signer path.
|
||||
- [ ] Step 4: external-signer permissions UI (grants persisted AND enforced).
|
||||
|
||||
### 2026-09-26 — live publish CONFIRMED + forensics log cleaned
|
||||
- **End-to-end Amber signing verified on-chain:** kind:1 notes from `npub1qn0w4a…` (ids `5191172d01f9…`, `fe9a256f597f…`) confirmed accepted on primal/damus/snort/nos.lol at exactly the sign_event timestamps in el.log (Sep 25 ~19:50). Every named milestone of the pairing project is now live-verified except one optional scanless-restart eyeball.
|
||||
- **False alarms retired:** the scary recurring "restored signer answered as a different account" and stray "auto-name attempt" lines in pairing-trace.log were e2e TEST traffic (wrong-identity refusal test + loopback enrichment loop), not live Amber failures. Fixed by gating `fail()` + auto-name traces on `live_relays()` like every other trace site (`332ab64`); measured proof: an e2e run now leaves the trace file byte-identical.
|
||||
- **Live vault pruned again:** legacy keyless `fac852dc…` connection row removed (backup `profiles_vault.json.backup-cron-20260926`) so startup restore targets only the restorable `4148a9a1…` pairing. Serve smoke test on the real vault fires the restore with the persisted client key, no errors.
|
||||
- 216 unit + 5 e2e green; clippy 0; fmt clean; release rebuilt at `332ab64`. Checkpoint `1b4655c`.
|
||||
|
||||
### 2026-09-24/25 — session restore + live sign-in + auto-naming milestones
|
||||
- **Session restore shipped (`0982dad`, checkpoint `aa3c514`):** NIP-46 client key persisted in the vault; re-dial at startup/unlock — no re-scan after restart. `expected_identity` cross-account guard refuses a wrong-identity connection. e2e covers restart + wrong-identity refusal (216 unit + 5 e2e green, clippy 0). Pre-commit bug fixed: client-key re-keying was nested in the pairing-secret branch.
|
||||
- **11 profileless `nip46_connections` rows pruned** from the live vault (backup `profiles_vault.json.backup-prune-20260924`). Legacy connection rows predate client-key persistence — each needs one last fresh scan.
|
||||
- **LIVE Amber sign-in confirmed (Sep 25 PM)** through the new Add-profile flow; active remote profile `npub1qn0w4a…`. **Session restore live-verified against real Amber at `01ce5de`** (fix: restored sessions skip the connect secret re-echo — already-approved peers don't re-send it).
|
||||
- **Pairing label step removed** — one click → QR (seed label 'Amber'). Auto-name enrichment hardened to 4 retries × 20s; **confirmed end-to-end on the live account**: seed label shown at pairing, retry loop fetched kind-0 from nos.lol, vault row upgraded to 'web5osint' + picture. UI `fc2fe93`, backend `bc736ff`, checkpoint `704addc`.
|
||||
- **Repo renamed on Forgejo 2026-09-25:** `avi/Nostr_Keynctr` → `avi/Keynctr` (see [[Forgejo git.atitlan.io]]).
|
||||
- Open hardening item: account kind-0 still lives ONLY on nos.lol — publishing it to primal/damus (one Amber approval) remains open.
|
||||
|
||||
## Next Steps
|
||||
- [ ] Publish account kind-0 to primal/damus (currently only on nos.lol).
|
||||
- [ ] Remote picture/nip05 edits, KDF upgrade (Step 5), rename pass (Step 7).
|
||||
- [ ] Consider swapping `wss://relay.nostr.band` out of the user's
|
||||
enabled relays (settings.json) too — it hangs handshakes today and
|
||||
is pay-to-read.
|
||||
- [ ] Adopt [[Polaris Vault Workflow]] boilerplate conventions for the repo
|
||||
(directive 2026-09-25).
|
||||
|
||||
## Completed
|
||||
- [x] **LIVE PAIRING CONFIRMED + sign_event timeout fix
|
||||
(`f53bc56`, Sep 23):** two full live pairings against real Amber
|
||||
recorded in the trace log (15:17 + 15:37 CDT): `inbound 24133` ->
|
||||
secret echo -> `identity adopted: npub1f3tura… — CONNECTED`. The
|
||||
"Dev" profile row now exists in `profiles_vault.json`
|
||||
(`nip46_client` mode) — the original Sep problem (no profile row,
|
||||
no persisted connection) is CLOSED. Remaining failure diagnosed
|
||||
from el.log: valid Amber signatures arriving ~61s after
|
||||
publication were discarded ("stale/duplicate response: no
|
||||
waiter") because `sign_event` used the 30s ordinary-RPC leash;
|
||||
every sign needs a human tap in Amber. `sign_event` now has a
|
||||
120s `SIGN_TIMEOUT` (handshake leash). 213 unit + 4 e2e green,
|
||||
clippy 0, fmt clean, release rebuilt at `f53bc56`.
|
||||
- [x] **Feed author resolution + kind-0 via signer (`a76d8df`,
|
||||
`6f4dbb2`, Sep 23):** feed shows names/pictures from batched
|
||||
kind-0 lookups; "Publish name" routes through Amber.
|
||||
- [x] **First live pairing attempt diagnosed + relay-set fix
|
||||
(`c789cb4`, Sep 22):** trace log recorded the first real session
|
||||
(started 18:01:29 CDT, timed out 18:06:39, zero inbound 24133).
|
||||
Read-only relay sweep: the ephemeral key had NO 24133 anywhere.
|
||||
Anonymous write+readback canary (`canary-24133.py`, throwaway
|
||||
keys): purplepag.es blocks kind 24133, nostr.band hangs
|
||||
handshake; damus/primal/nos.lol accept+store, snort accepts for
|
||||
live push. New pairing set: damus.io, primal.net, nos.lol,
|
||||
snort.social, with a regression test pinning the blockers out.
|
||||
Also removed `inspect.py` from the debug dir (shadowed stdlib
|
||||
`inspect`, leaked stale output into terminals). 209 unit + 3 e2e
|
||||
green, clippy 0, fmt clean, release rebuilt.
|
||||
- [x] **Pairing forensics fully de-noised (`f6bf6a9`, Sep 21):** the
|
||||
`identity adopted — CONNECTED` trace line had no loopback gate, so
|
||||
every `cargo test` run appended fake CONNECTED entries to
|
||||
`pairing-trace.log` (Sep 18–21 evening entries were all test
|
||||
traffic, incl. this cron's own runs). Gated on `live_relays()`;
|
||||
verified by re-running the e2e suite and confirming the trace file
|
||||
stays untouched. Added a `paired: connection stored` handover trace
|
||||
line so a stall between the connect echo and `get_public_key`
|
||||
names itself. Full read-through audit of the QR pairing flow found
|
||||
no further defects; nothing left to fix without live Amber data.
|
||||
208+3 tests green, clippy 0, fmt clean, release rebuilt.
|
||||
- [x] **e2e vault-isolation bug found + fixed (`d52fa58`+`deeb4f9`, Sep 20):**
|
||||
the e2e tests seeded their isolation vault one directory too shallow
|
||||
(`$XDG_DATA_HOME/` instead of `$XDG_DATA_HOME/keynectr/`), so every
|
||||
e2e run silently migrated the legacy repo vault — the user's real
|
||||
profile with a plaintext secret key — into the test process.
|
||||
Forensic proof: two legacy-vault backups timestamped Sep 19 20:43:54
|
||||
+ 20:44:30, exactly the test runs around the root-cause commit. Also
|
||||
means the Sep 19 `identity adopted` trace lines were e2e traffic, NOT
|
||||
a live Amber scan — no live scan has happened against the fixed
|
||||
build yet (zero `pairing started` trace lines). Fix seeds the vault
|
||||
at the correct path and asserts emptiness after every e2e load so
|
||||
this can never pass silently again. Verified: repo legacy vault
|
||||
byte-identical, backup count unchanged, 208+3 tests green.
|
||||
- [x] **Amber pairing root cause found + fixed (`edd4e56`, Sep 19):** the
|
||||
pairing loop only accepted an inbound `{"method":"connect"}` *request*;
|
||||
NIP-46 says a nostrconnect:// signer sends a connect **response**
|
||||
(`{"id","result":"<secret>"}`, secret echo IS the handshake). Amber's
|
||||
approval was silently dropped as `pre-handshake '' ignored` — hence
|
||||
"Amber says connected, Keynctr shows nothing". Now the echo is
|
||||
verified directly, `ack` accepted, signer errors fail fast; locked by
|
||||
a new e2e test (`nip46_qr_pairing_connect_response_shape`, proven
|
||||
red-on-old/green-on-new). Awaiting live re-scan to confirm.
|
||||
- [x] Steps 1–3 (vault encryption, packaging, SigningBackend abstraction,
|
||||
vault-integrated connection secrets, IPC reroute, end-to-end external
|
||||
signing in publish + upload auth)
|
||||
- [x] Per-profile signer modes + persisted NIP-46 connections (`2c61830`)
|
||||
- [x] Fail-closed key export (`6eff510`), hash-chained audit log (`caed722`)
|
||||
- [x] Amber-compatible deferred-identity handshake (`f917e5e`)
|
||||
- [x] **Oct 1: Step 4 shipped — approval-time kind scope** (`d09c4ec`,
|
||||
checkpoint `38612a4`): "Always allow…" on a sign_event opens an inline
|
||||
kind editor prefilled with the request's kind; grants store the edited
|
||||
scope; legacy vault rows keep old meaning. Latent fix: legacy
|
||||
"Always allow" never recorded a grant (AppProvider dropped `always`).
|
||||
Suite: 227 unit + 6 e2e, clippy 0, frontend 148 green.
|
||||
- [x] **Oct 1 evening cron hygiene (`41d4a60`, checkpoint `2b91aea`, pushed):**
|
||||
lockfile refresh from the in-app update committed; pairing problem
|
||||
re-checked and still closed (3 nip46_connections, latest Sep 28 10:23);
|
||||
debug dirs cleaned up — no parse-failure evidence since closure.
|
||||
- [x] **Sep 28: pairing problem closed.** Vault now holds 3 persisted
|
||||
`nip46_connections` with matching `signer_mode: nip46_client` rows
|
||||
(latest Sep 28 10:23, active profile) — Amber connect events parse and
|
||||
persist; original failure no longer reproduces. Supporting fixes:
|
||||
stdin EAGAIN crash (`9770f46`), persistent kind-0 identity backfill
|
||||
for generic "Amber" labels (`5b60ae3`). Suite: 221 unit + 6 e2e,
|
||||
clippy 0, frontend 139 green (checkpoint `f905cbc`).
|
||||
- [x] Vault-load rewrite fix (`c096705`)
|
||||
- [x] NIP-46 e2e test harness + frontend bunker:// support (`85756df`)
|
||||
- [x] QR pairing + IPC/Electron wiring + real identity metadata (`38499d4`..`3d5302f`)
|
||||
- [x] Connect immediately after identity; kind-0 metadata fetched in
|
||||
background so the UI stops hanging on slow relays (`286bbca`)
|
||||
- [x] Always-allow grants: approvals gained an "Always allow" option;
|
||||
standing permission stored per (app pubkey, method) in the encrypted
|
||||
vault, listed with Revoke on the Signer screen (`93892fa`)
|
||||
|
||||
## Known Issues
|
||||
- `package.json` → `homepage` still reads `https://github.com/avi/Keynctr`
|
||||
(Step-7 hygiene item).
|
||||
- Legacy Python files + root `profiles_vault.json*` + dead stub
|
||||
`src/signer/nip46_external.rs` are hygiene leftovers (Step-7 pass).
|
||||
- Fixed since last update: `migrate_vault_signer_modes` no longer reports a
|
||||
change on every load (`c096705`).
|
||||
|
||||
## References
|
||||
- Local code: `/home/avi/Projects/Keynctr/`
|
||||
- Checkpoint: `/home/avi/Projects/Keynctr/CHECKPOINT-encryption.md`
|
||||
- [[00-HERMES/Current State]]
|
||||
- [[00-HERMES/Session Handoff]]
|
||||
Loading…
Add table
Add a link
Reference in a new issue