checkpoint: document packaging icon fix (post-Step 2)
HEAD moved to 114b343 (icon restored); the previously-deleted
frontend/build/icon.png is now a committed asset, no longer a leftover.
Records the verified npm run dist + AppImage/deb icon proof, the
pre-existing format:check failure (5 files, Step-7), and notes the
homepage rename is on the record for Step 7 (not fixed). Step 3 signer
API is proposed and awaiting sign-off, not implemented.
This commit is contained in:
parent
114b34319e
commit
ee88171e45
1 changed files with 88 additions and 59 deletions
|
|
@ -1,20 +1,22 @@
|
|||
# Checkpoint — Signer Modes + Fail-Closed Key Export (2026-09-03)
|
||||
# Checkpoint — Signer Modes + Fail-Closed Key Export + Packaging Icon (2026-09-03)
|
||||
|
||||
## Where things are
|
||||
- Project: `/home/avi/Projects/Keynctr`
|
||||
- Branch: `master` @ **`6eff510`** ("feat: fail-closed ExportSecretKey with fresh auth and audit").
|
||||
- Working tree: **not clean** — see "Still uncommitted" below. The three feature
|
||||
commits of this session are committed; only the packaging icon, the old
|
||||
checkpoint, and pre-existing hygiene leftovers remain uncommitted.
|
||||
- Branch: `master` @ **`114b343`** ("fix(packaging): restore Linux app icon so dist builds ship an icon").
|
||||
- Working tree: **effectively clean for tracked files.** No tracked file is modified or
|
||||
staged. The only untracked entries are the pre-existing hygiene leftovers and the
|
||||
source JPEG (all intentionally untracked — see "Still untracked"). Build artifacts
|
||||
(`release/`, `dist/`) are gitignored.
|
||||
|
||||
## What was completed (this session)
|
||||
The previously-uncommitted working tree (27 modified + 10 untracked files, ~1852/692)
|
||||
was triaged into **three logical, independently-verifiable commits**. Order is
|
||||
`a → c → b`: `ExportSecretKey` (b) reads the per-profile `signer_mode` field and the
|
||||
`external_signer_not_connected` error that the signer-mode commit (c) introduces, so
|
||||
(c) had to land first. The only uncommitted *tests* were the export tests and the
|
||||
signer-mode/permission tests, so "(d) tests" is not a separate commit — each feature's
|
||||
tests travel with it.
|
||||
was triaged into **three logical, independently-verifiable commits** in a prior session,
|
||||
and this session **landed the Step-2 packaging fix** on top. Order is
|
||||
`a → c → b → (packaging)`: `ExportSecretKey` (b) reads the per-profile `signer_mode`
|
||||
field and the `external_signer_not_connected` error that the signer-mode commit (c)
|
||||
introduces, so (c) had to land first. The only uncommitted *tests* were the export
|
||||
tests and the signer-mode/permission tests, so "(d) tests" is not a separate commit —
|
||||
each feature's tests travel with it.
|
||||
|
||||
1. **Per-profile signer modes + persisted NIP-46 connections (c)** — three coexisting
|
||||
signing modes (Embedded / Nip46Client / Nip46Bunker), a `signer_mode` field on every
|
||||
|
|
@ -28,6 +30,17 @@ tests travel with it.
|
|||
replaces the old reveal modal.
|
||||
3. **Hash-chained audit log (a)** — SHA-256 hash-chained append-only log with atomic
|
||||
append and end-to-end `verify_chain()`; the `sha2` dependency.
|
||||
4. **Packaging icon restored (this session, `114b343`)** — `frontend/build/icon.png`
|
||||
was deleted from the working tree, so electron-builder had no Linux icon and every
|
||||
AppImage/deb it emitted carried the generic Electron placeholder. The icon was
|
||||
**regenerated from `KeynectrAppIconPossibility02.jpeg`** (not resized): the white
|
||||
(254) JPEG background was cut to transparent (alpha derived from luma), the art was
|
||||
flattened to a square canvas with symmetric padding, ink kept pure black (RGB 0,0,0),
|
||||
and exported as **512x512 RGBA**. The single declared config path
|
||||
(`linux.icon: build/icon.png`) was kept single — no `build/linux/` fan-out — because
|
||||
the 512 master satisfies both targets: AppImage downscales to 256 internally (≥256
|
||||
required) and the deb installs `usr/share/icons/hicolor/512x512/apps/keynectr.png`,
|
||||
matching the generated `.desktop` `Icon=keynectr`.
|
||||
|
||||
### Security properties confirmed
|
||||
- No secret material is logged or returned except the single, authenticated, audited
|
||||
|
|
@ -45,67 +58,81 @@ tests travel with it.
|
|||
## Commits added this session (newest first)
|
||||
| Hash | Message |
|
||||
|------|---------|
|
||||
| `6eff510` | feat: fail-closed ExportSecretKey with fresh auth and audit |
|
||||
| `2c61830` | feat: add per-profile signer modes with persisted NIP-46 connections |
|
||||
| `caed722` | feat: add hash-chained, append-only audit log |
|
||||
| `114b343` | fix(packaging): restore Linux app icon so dist builds ship an icon |
|
||||
|
||||
Parent of this session: `4038e2d` ("checkpoint: document embedded signer and NIP-46
|
||||
client signer modes").
|
||||
(The prior session's three feature commits and their checkpoint `d92371f` remain the
|
||||
parent chain: `6eff510` → `2c61830` → `caed722` → … → `d92371f` → `114b343`.)
|
||||
|
||||
### Files touched by the three commits (30 files, +3921 / -611)
|
||||
```
|
||||
Cargo.lock Cargo.toml frontend/electron/main.ts frontend/package.json
|
||||
frontend/package-lock.json frontend/src/components/ExportSecretKeyModal.tsx (new)
|
||||
frontend/src/components/ShowSecretKeyModal.tsx (deleted)
|
||||
frontend/src/lib/api.ts frontend/src/lib/signer/SignerManager.ts (new)
|
||||
frontend/src/lib/types.ts frontend/src/screens/ProfilesScreen.tsx
|
||||
frontend/src/screens/SignerModeScreen.tsx frontend/src/state/AppProvider.tsx
|
||||
frontend/src/styles.css frontend/src/test/apiMock.ts
|
||||
frontend/src/test/ExportSecretKey.test.tsx (new) frontend/src/test/fakeBackend.ts
|
||||
frontend/src/test/ShowSecretKey.test.tsx (deleted)
|
||||
src/app.rs src/audit.rs (new) src/errors.rs src/ipc.rs src/lib.rs src/main.rs
|
||||
src/profiles.rs src/signer/mod.rs src/signer/nip46_client.rs
|
||||
src/signer/permissions.rs (new) src/signer/types.rs src/vault.rs
|
||||
```
|
||||
|
||||
## Verification (run this session, per commit)
|
||||
Each commit was verified **in isolation** (checked out on top of its parent), not just
|
||||
as the final tree:
|
||||
- `caed722` (audit): `cargo test --release` → **124 passed** (119 prior + 5 audit).
|
||||
- `2c61830` (signer modes): `cargo test --release` → **186 passed**; `cargo clippy
|
||||
--all-targets` clean; `cargo fmt --check` clean; frontend `tsc --noEmit` clean;
|
||||
`npx vitest run` → **110 passed**.
|
||||
- `6eff510` (export): `cargo test --release` → **186 passed**; frontend `tsc --noEmit`
|
||||
clean; `npx vitest run` → **116 passed** (110 + 6 export tests).
|
||||
## Verification (run this session)
|
||||
Full suite per AGENTS.md, run on top of `114b343` (icon is a binary asset, no code
|
||||
change, so the suite is expected to hold):
|
||||
- **Rust**: `cargo test --release` → **186 passed**, 0 failed; `cargo clippy
|
||||
--all-targets` → clean (exit 0); `cargo fmt --check` → clean (exit 0); `cargo build
|
||||
--release` → Finished, exit 0.
|
||||
- **Frontend**: `npm test` → **116 passed** (16 files); `npm run typecheck` → clean
|
||||
(exit 0); `npm run lint` → clean (exit 0).
|
||||
- `npm run format:check` → **exit 1** on 5 files (`src/components/ExportSecretKeyModal.tsx`,
|
||||
`src/screens/SignerModeScreen.tsx`, `src/state/AppProvider.tsx`,
|
||||
`src/test/ExportSecretKey.test.tsx`, `src/test/fakeBackend.ts`). **Pre-existing** —
|
||||
those files are committed as-is at `6eff510` (prior session) and are clean in the
|
||||
working tree; this icon-only change touched none of them. Left for the Step-7
|
||||
hygiene/format pass; not silently auto-fixed here.
|
||||
- **Packaging (the point of this fix)**: `npm run dist` ran end-to-end. Note the script
|
||||
is `electron-builder --linux dir`, which builds only the unpacked dir; the declared
|
||||
`linux.target` (AppImage + deb) was also built directly to prove the icon lands:
|
||||
- `release/Keynctr-0.1.0.AppImage` — 135,749,547 bytes.
|
||||
- `release/keynectr_0.1.0_amd64.deb` — 105,810,972 bytes.
|
||||
- **Icon proven inside both artifacts**: the embedded icon is **byte-identical
|
||||
(md5 `b3e372f7`)** to the generated `build/icon.png` in all four locations checked —
|
||||
the deb's `usr/share/icons/hicolor/512x512/apps/keynectr.png`, the AppImage's hicolor
|
||||
png, the AppImage's `.DirIcon`, and `build/icon.png` itself — all 512x512 RGBA with
|
||||
real transparency (32,626 opaque px, 226,582 transparent, corners alpha 0), ink
|
||||
pure black. The deb `.desktop` reads `Icon=keynectr`, matching the hicolor name.
|
||||
|
||||
## How to reproduce / exercise
|
||||
- Backend: `cargo run --release -- serve` (JSON-lines IPC on stdio) or the CLI in
|
||||
`src/main.rs`.
|
||||
- GUI: from `frontend/`, `npm run electron:build && electron .` (prod) or `npm run
|
||||
start:dev` with `NOSTR_GUI_DEV_URL`.
|
||||
- Packaging: from `frontend/`, `npm run dist` (unpacked dir) or `npx electron-builder
|
||||
--linux AppImage deb` (declared targets) → artifacts in `release/`.
|
||||
- Exercise export: Profiles → a profile → Export secret key → enter the vault password
|
||||
and a reason. An external (NIP-46 client) profile shows it cannot export.
|
||||
- Exercise modes: Signer Mode screen → pick Embedded / NIP-46 client; connect a
|
||||
`nostrconnect://` URI with a `perms=` parameter to grant scoped permissions.
|
||||
|
||||
## Still uncommitted (do NOT lose; do NOT commit the hygiene junk)
|
||||
- **`frontend/build/icon.png` is deleted** (working tree) — the electron-builder Linux
|
||||
icon. This is the Step-2 packaging fix: regenerate it from
|
||||
`KeynectrAppIconPossibility02.jpeg` (or point electron-builder at the new asset),
|
||||
verify `npm run dist`, then commit. **Not done in this session.**
|
||||
- **`CHECKPOINT-encryption.md`** — this file, committed to reference the post-triage
|
||||
HEAD (`6eff510`). It must be re-updated to reference the new HEAD once Step 2
|
||||
(packaging) lands its own commit.
|
||||
- Pre-existing untracked hygiene leftovers (out of scope, address in the hygiene pass):
|
||||
`COSMIC_THEME.md`, `KeynectrAppIconPossibility02.jpeg`, `.opencode/`, `.impeccable/`,
|
||||
`.directory`. **`profiles_vault.json*` and `target/` remain correctly untracked and
|
||||
uncommitted** (vault is gitignored).
|
||||
## Still untracked (do NOT lose; do NOT commit the hygiene junk)
|
||||
- **Source JPEG** `KeynectrAppIconPossibility02.jpeg` — intentionally **untracked**
|
||||
(the icon is now derived from it; the JPEG itself is not a build input and stays out
|
||||
of git, per instruction).
|
||||
- Pre-existing untracked hygiene leftovers (out of scope, address in the Step-7 hygiene
|
||||
pass): `COSMIC_THEME.md`, `.opencode/`, `.impeccable/`, `.directory`.
|
||||
- **`frontend/build/icon.png` is no longer a leftover** — it was regenerated and
|
||||
committed in `114b343` this session. The prior "deleted icon" item is closed.
|
||||
- Build artifacts `release/` and `dist/` are gitignored and not committed.
|
||||
- `profiles_vault.json*` and `target/` remain correctly untracked and uncommitted
|
||||
(vault is gitignored).
|
||||
|
||||
## On the record (not fixed, per instruction)
|
||||
- **`package.json` → `homepage` still reads `https://github.com/avi/Keynctr`.** This is
|
||||
the Step-7 rename/hygiene item and was **left untouched** in this session; noted here
|
||||
so it is on the record rather than silently fixed.
|
||||
|
||||
## Deferred / next steps (unchanged, plus new)
|
||||
- **Step 2 (packaging)**: restore `frontend/build/icon.png`, verify `npm run dist`.
|
||||
- Signer abstraction (Step 3): promote `src/signer` to the single `Signer` source of
|
||||
truth; introduce `SigningBackend { Internal{..}, Remote{..} }` per profile and route
|
||||
every IPC handler through the trait (no inline mode branching).
|
||||
- **Step 2 (packaging): DONE.** Icon restored, `npm run dist` + declared targets green,
|
||||
icon proven inside both artifacts, committed as `114b343`.
|
||||
- **Step 3 (signer abstraction)** — proposed for sign-off, NOT yet implemented. Current
|
||||
state that motivates the API: `src/signer/mod.rs` already defines a `Signer` trait and
|
||||
a `Signing` enum (`Local(Keys)` / `External{signer, profile_pubkey}`); `SignerMode`
|
||||
(`Embedded`/`Nip46Bunker`/`Nip46Client`) lives on `StoredProfile` (per-profile) *and*
|
||||
is duplicated on `App` (app-level), and `App` holds three separate signer handles
|
||||
(`embedded_signer`, `nip46_signer`, `nip46_bunker_signer`). The IPC dispatcher
|
||||
(`src/ipc.rs`) branches on `signer_mode`/handle presence in ~12 sites (see the
|
||||
grep list pasted to the user this session). The proposal promotes `src/signer` to the
|
||||
single `Signer` source of truth, introduces a `SigningBackend { Internal{..},
|
||||
Remote{..} }` per profile, and routes every IPC handler through the trait so no inline
|
||||
mode branching remains. **Awaiting the user's sign-off on the API before any
|
||||
implementation.**
|
||||
- External-signer permissions (Step 4): wire `src/signer/permissions.rs` into the
|
||||
approval modal so grants (kinds, relays, expiry, rate) are persisted AND enforced in
|
||||
the UI, not just parsed.
|
||||
|
|
@ -113,8 +140,10 @@ as the final tree:
|
|||
+ backward-compatible migration; `--allow-env-secret` flag; remove or gate deprecated
|
||||
`RevealSecretKey` IPC behind the same fail-closed path.
|
||||
- Undo history (Step 6): resolve the `ProfileSummary`-loses-the-secret question.
|
||||
- Hygiene (Step 7): Keynctr rename pass, delete legacy Python, migrate root
|
||||
`profiles_vault.json*` into `~/.local/share/keynectr`.
|
||||
- Hygiene (Step 7): Keynctr rename pass (includes the `homepage` → correct repo fix noted
|
||||
above), delete legacy Python, migrate root `profiles_vault.json*` into
|
||||
`~/.local/share/keynectr`, and a Prettier format pass to clear the 5 pre-existing
|
||||
`format:check` failures.
|
||||
- Open question carried forward: `migrate_vault_signer_modes` currently reports a change
|
||||
on every load (always `changed = true`), so `App::load` re-saves the vault each start.
|
||||
Harmless (idempotent) but wasteful; tighten to only report real changes.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue