Refresh session checkpoint for compose media feature

This commit is contained in:
Avi 2026-08-04 13:30:54 -05:00
commit 8b701db929

View file

@ -1,4 +1,4 @@
# Checkpoint — Secret-key reveal after unlock (2026-08-04) # Checkpoint — Compose preview with image attachments (2026-08-04)
A stopping point you can return to if this session is closed. Everything below was A stopping point you can return to if this session is closed. Everything below was
verified green at the moment this file was written. verified green at the moment this file was written.
@ -6,87 +6,72 @@ verified green at the moment this file was written.
## Where things are ## Where things are
- Project: `/home/avi/Projects/skills/nost-feed-manager` - Project: `/home/avi/Projects/skills/nost-feed-manager`
- Git repo: `master` - Git repo: `master` @ `3e3467b` ("Add compose preview with image attachments (NIP-92 imeta)"),
- The reveal feature is **uncommitted** — all changes are in the working tree. on top of `17e8ace` ("Clarify the Profiles subtitle about private keys") and `8eb6685`
("Add reveal-secret-key after unlock (CLI + GUI)").
- The working tree is **clean** — everything from this session is committed.
- `/home/avi/Projects/nostr_backend/nostr_backendmanager.md` (old-CLI docs) has been updated - `/home/avi/Projects/nostr_backend/nostr_backendmanager.md` (old-CLI docs) has been updated
to match reality; it lives outside this repo so it is not part of the commit. to match reality; it lives outside this repo so it is not part of any commit.
- `/home/avi/Projects/nostr_backend/vlog-website/` (separate, untouched). - `/home/avi/Projects/nostr_backend/vlog-website/` (separate, untouched).
## What was completed in this session: reveal a secret key after unlock ## What was completed: compose preview + image attachments
Building on the existing password-encrypted vault (AES-256-GCM + Argon2id), owners can now view a The Compose screen now has a **Write / Preview** tab split. The preview renders the note as it
profile's secret key after entering the vault password: will appear (profile avatar + npub, the text, and any images), without publishing anything.
- Backend: `profiles::reveal_secret_key` returns the key in both hex and `nsec1...` forms, gated on - **Photos from hyperlinks**: pasting an image URL (`.jpg/.jpeg/.png/.gif/.webp/.avif`) anywhere in
an unlocked vault (`VaultLocked` when encrypted + locked). New CLI command `show-secret <npub>`, the note shows the picture in the preview. On publish, the backend detects the same URLs and tags
which prompts for the password when locked (via `NFM_PASSWORD` env or hidden prompt). the event with NIP-92 `imeta` (`url`, `m`) plus the legacy `image` tag, so both new and older
- IPC: new `reveal_secret_key { npub }` method. Error replies now carry a machine-readable `code` Nostr clients render the images. Detection is by extension only — nothing is downloaded to decide.
field (ErrorKind serialised as snake_case, e.g. `vault_locked`), so the GUI can branch without - **Attach images**: an "Attach image" button opens the native file dialog (multi-select),
string-matching on user-facing messages. uploads each file to nostr.build (anonymous `POST /api/v2/upload/files`, field `fileToUpload`),
- GUI: a "Secret key" button on every profile card opens `ShowSecretKeyModal`, which shows hex + and shows a removable thumbnail chip. The hosted URLs are appended to the note on publish.
nsec with copy buttons and a warning. When the vault is locked the modal asks for the password - **Where upload lives**: `pick_image` / `upload_image` are handled by the Electron main process
inline, unlocks, then reveals. (native dialog + `fetch`), not the Rust backend — they need a file dialog and a one-off HTTP
- Key is only ever fetched after unlock; never stored in state before reveal. upload. The renderer still calls them through the same `window.backend.request` envelope.
- The reveal-secret-key feature from the previous commit (`8eb6685`) is unchanged and still works.
## Files changed (16 modified, 2 new) ## Commits this session (newest first)
Modified: - `3e3467b` "Add compose preview with image attachments (NIP-92 imeta)" — 11 files, 1 new.
- `README.md` — documented the reveal feature + `show-secret` Backend: `src/publish.rs` (`extract_image_urls`, `image_mime_from_url`, `image_tags` + tests).
- `src/errors.rs``ErrorKind` now serialises as snake_case for the IPC error code Electron: `frontend/electron/main.ts` (`pickImage`, `uploadImage`, routed from `backend:request`).
- `src/profiles.rs``RevealedKey`, `reveal_secret_key`, `profile_label` + tests Renderer: `frontend/src/lib/media.ts` (new), `api.ts`, `types.ts`, `AppProvider.tsx`,
- `src/ipc.rs``RevealSecretKey` request, `code` on error replies `ComposeScreen.tsx`, `styles.css`. Tests: `ComposeScreen.test.tsx`, `apiMock.ts`, `fakeBackend.ts`
- `src/main.rs``show-secret` CLI command (adds request recording + `pick_image`/`upload_image`).
- `frontend/src/components/Icon.tsx` — new `key` icon - `17e8ace` "Clarify the Profiles subtitle about private keys" — `ProfilesScreen.tsx` copy.
- `frontend/src/lib/api.ts``revealSecretKey`, `BackendError.code` - `8eb6685` "Add reveal-secret-key after unlock (CLI + GUI)" — previous feature, see history.
- `frontend/src/lib/types.ts``RevealedKey`, error `code` in `BackendResponse`
- `frontend/src/screens/ProfilesScreen.tsx` — "Secret key" button per profile
- `frontend/src/state/AppProvider.tsx``revealSecretKey` in context
- `frontend/src/test/{App,ProfilesScreen,apiMock,fakeBackend}` — updated for new UI + error codes
New:
- `frontend/src/components/ShowSecretKeyModal.tsx`
- `frontend/src/test/ShowSecretKey.test.tsx`
Also updated (outside repo): `/home/avi/Projects/nostr_backend/nostr_backendmanager.md`.
## New backend API (IPC + CLI)
IPC: `reveal_secret_key { npub }``{ hex, nsec }`. Error replies now include
`"code": "vault_locked"` (etc.) alongside `message`/`details`.
CLI: `show-secret <npub>` prints hex + nsec after unlocking. `create`, `publish`, and
`show-secret` all auto-prompt for the vault password when it is encrypted.
## How it was verified (all green) ## How it was verified (all green)
``` ```
cargo test # 55 passed cargo test # 60 passed
cargo clippy --all-targets # clean cargo clippy --all-targets # clean
cargo fmt --check # clean cargo fmt --check # clean
cargo build --release # builds cargo build --release # builds (rebuilt so the GUI runs the new backend)
npm run typecheck # clean (frontend/) npm run typecheck # clean (frontend/)
npm run lint # clean (pre-existing module warning only) npm run lint # clean (pre-existing module warning only)
npm run format:check # clean npm run format:check # clean
npm test # 56 passed (11 files) npm test # 60 passed (11 files)
npm run build # rebuilds the React bundle (dist/)
npm run electron:build # compiles the Electron main process
``` ```
Plus a manual IPC end-to-end smoke test: reveal on plaintext → OK; set-password → lock →
reveal returns `code: "vault_locked"`; unlock → reveal returns the same hex. Temp data cleaned up.
## How to resume ## How to resume
1. Open the repo: `cd /home/avi/Projects/skills/nost-feed-manager` 1. Open the repo: `cd /home/avi/Projects/skills/nost-feed-manager`
2. Inspect the diff: `git diff` (work is still uncommitted) 2. State is committed: `git status` should be clean; `git log --oneline -5` shows the three commits.
3. To try it: 3. To try it:
- CLI: `cargo build --release`, then - GUI: `cd frontend && npm start` — Compose → "Attach image" or paste an image URL → Preview tab.
`XDG_DATA_HOME=/tmp/nfm-smoke ./target/release/nostr-manager-backend create "Alice"` and (Note: `npm start` alone does NOT rebuild the React bundle — run `npm run build` first, or use
`./target/release/nostr-manager-backend show-secret <npub>` `npm run dev` + `NOSTR_GUI_DEV_URL=http://localhost:5173 npm start` for live reload.)
- GUI: `cd frontend && npm start`, Profiles → "Secret key" on a card - CLI: `cargo build --release`, then `./target/release/nostr-manager-backend list` and
`./target/release/nostr-manager-backend show-secret <npub>` (no angle brackets).
4. Re-run verification with the commands above. 4. Re-run verification with the commands above.
## Outstanding / next steps (if you continue) ## Outstanding / next steps (if you continue)
- Decide whether to **commit** the reveal work (nothing is committed yet). - Nothing uncommitted. Possible follow-ups: a real feed view (currently Home only shows the last
- Consider a small UI hint that profiles with an unencrypted vault can be revealed with no prompt. publication); optional NIP-98 auth for nostr.build uploads; relay defaults in code still point at
- Relay defaults are currently `relay.damus.io` (503 upstream) and `relay.nostr.band` (timeout); `relay.damus.io` (503 upstream) and `relay.nostr.band` (timeout) — user's local settings already
user's local settings already point at `nos.lol` + `relay.primal.net` instead. use `nos.lol` + `relay.primal.net` instead.