diff --git a/CHECKPOINT-encryption.md b/CHECKPOINT-encryption.md new file mode 100644 index 0000000..e81e6fe --- /dev/null +++ b/CHECKPOINT-encryption.md @@ -0,0 +1,78 @@ +# Checkpoint — Password-encrypted vault (2026-08-03) + +A stopping point you can return to if this session is closed. Everything below was +verified green at the moment this file was written. + +## Where things are + +- Project: `/home/avi/Projects/skills/nost-feed-manager` +- Git repo: `master` @ `7e3bac3` ("Add Nostr Feed Manager: Rust backend with Electron + React GUI") +- The encryption work is **uncommitted** — all changes are in the working tree. +- Also relevant: `/home/avi/Projects/nostr_backend/nostr_backendmanager.md` (old-CLI docs, untouched), + and `/home/avi/Projects/nostr_backend/vlog-website/` (separate, untouched). + +## What was completed: password-encrypted vault + +- Secret keys are now encrypted at rest with **AES-256-GCM** under a key derived via **Argon2id** + from the user's password. Vaults stay plaintext until a password is set (opt-in). +- Encryption only covers the secret keys; labels/npubs stay readable so profiles can be browsed + while the vault is locked. The derived key lives only in memory for the session. + +## Files changed (19 modified, 4 new) + +Modified: +- `Cargo.toml`, `Cargo.lock` — added `argon2`, `aes-gcm`, `base64`, `getrandom`, `rpassword` +- `README.md` — documented the new feature + CLI commands +- `src/lib.rs`, `src/app.rs`, `src/vault.rs`, `src/profiles.rs`, `src/publish.rs`, + `src/ipc.rs`, `src/main.rs`, `src/errors.rs` +- `frontend/src/App.tsx`, `frontend/src/lib/api.ts`, `frontend/src/lib/types.ts`, + `frontend/src/state/AppProvider.tsx`, `frontend/src/screens/SettingsScreen.tsx`, + `frontend/src/styles.css`, `frontend/src/test/apiMock.ts`, `frontend/src/test/fakeBackend.ts` + +New: +- `src/crypto.rs` — Argon2id KDF + AES-256-GCM encrypt/decrypt + password verifier +- `frontend/src/components/UnlockModal.tsx` +- `frontend/src/components/VaultPasswordModal.tsx` +- `frontend/src/test/VaultPassword.test.tsx` + +## New backend API (IPC + CLI) + +IPC methods: `set_vault_password { current_password?, new_password }`, +`unlock_vault { password }`, `lock_vault`, `remove_vault_password { password }`. + +CLI: `set-password`, `remove-password`, `unlock`; `create`/`publish` auto-prompt when locked. +Passwords come from `NFM_PASSWORD` env var or a hidden terminal prompt — never argv. +Min password length: 8 chars. + +## How it was verified (all green) + +``` +cargo test # 50 passed +cargo clippy --all-targets # clean +cargo fmt --check # clean +cargo build --release # builds +npm run typecheck # clean (frontend/) +npm run lint # clean (pre-existing module warning only) +npm run format:check # clean +npm test # 52 passed (10 files) +``` + +Plus a manual end-to-end CLI smoke test: create → set-password → vault file shows only base64 +ciphertext → wrong password rejected → correct password creates encrypted profile. Temp data +was cleaned up (`/tmp/nfm-e2e` removed). + +## How to resume + +1. Open the repo: `cd /home/avi/Projects/skills/nost-feed-manager` +2. Inspect the diff: `git diff` (work is still uncommitted) +3. To try it: `cargo build --release` then + `XDG_DATA_HOME=/tmp/nfm-smoke ./target/release/nostr-manager-backend create "Alice"`, + `NFM_PASSWORD=... ./target/release/nostr-manager-backend set-password` +4. Re-run verification with the commands above. + +## Outstanding / next steps (if you continue) + +- Decide whether to **commit** the work (nothing is committed yet). +- `nostr_backendmanager.md` still lists "password-based vault encryption" as a future item and was + left untouched — it may deserve updating to match reality. +- No lock-screen gate: browsing works while locked; only create/publish require unlocking (intended).