Commit graph

23 commits

Author SHA1 Message Date
Avi
24b34b6f93 Remove duplicate productName entries from package.json 2026-08-23 11:06:32 -05:00
Avi
6ead6f418c Fix hardcoded dev window title to Keynectr 2026-08-23 11:04:09 -05:00
Avi
31ef3057e0 Rebrand remaining UI strings to Keynectr
Sidebar brand, home welcome title, settings version line, stylesheet
header comment and the three tests asserting them.
2026-08-23 10:43:20 -05:00
Avi
7c6a085bf1 Rename the app to Keynectr
- Crate/binary: nostr-manager-backend -> keynectr
- Data directory: nost-feed-manager -> keynectr, migrated automatically
  on first data_dir() call (existing vaults, settings and backups move)
- Electron extraResources/spawn path, executableName, productName,
  window title and CLI usage strings updated to match
- Deliberately unchanged: crypto.rs KDF verifier string, so previously
  encrypted vault backups remain decryptable

Verified live: existing vault with two profiles migrated to
~/.local/share/keynectr and loads correctly.
2026-08-23 10:22:25 -05:00
Avi
ae5dddaa47 Allow new profile methods through the Electron IPC allowlist
set_profile_picture and publish_profile_metadata were rejected by the
renderer-method gate added in the 2026-08-21 hardening ('rejected renderer
method' in the log), so the GUI buttons could never reach the backend.
Also allow delete_profile / undo_delete from the deletion feature, which
were missing from the list as well.
2026-08-22 20:38:53 -05:00
Avi
a6329d5640 Publish profile metadata (name + picture) so external clients show it
Profiles created in the app never published a kind 0 metadata event, so
clients like Iris and Yakihonne showed generated petnames ("evil iguana")
or a truncated npub instead of the user's chosen name.

- Publish kind 0 metadata (name/display_name) automatically on creation
- Add "Publish name" action (GUI button + publish-name CLI) for existing
  profiles, with a per-relay success/failure report
- Add profile pictures: optional picture URL persisted in the vault,
  set via GUI modal (URL paste or nostr.build upload), set-picture CLI,
  and included in the published metadata; avatars render it in-app
- Run metadata publishing on its own thread so sync and async callers
  never nest tokio runtimes
- Expose undo_history in the state view and fix typecheck errors left by
  the unfinished delete/undo work (variants, icon, null-safety)
- Use offline relay settings in tests: Settings::default() points at real
  relays, which tests were silently publishing to (suite: 126s -> ~3s)

Verification: cargo test 96 passed; clippy/fmt/build clean. Frontend:
78 tests, typecheck, lint, format, vite and electron builds all pass.
2026-08-22 18:42:20 -05:00
Avi
db81f8dfda Implement profile deletion with undo functionality
- Add delete_profile() to profiles.rs - moves profile to undo stack
- Add undo_history field and undo_delete() method to App struct
- Add cli_delete_profile() and cli_undo_delete() CLI commands
- Add delete-profile <npub> and undo-delete to USAGE
- Update CHECKPOINT-encryption.md checkpoint

Verification: cargo test (91 passed), clippy clean, fmt clean, release build successful
2026-08-22 15:29:26 -05:00
Avi
f7db29e793 Add SSRF guard, signer queue cap, secret echo, request timeout 2026-08-21 16:06:18 -05:00
Avi
4d4dfde1de Enforce header-based CSP and block window open/navigation 2026-08-21 13:53:45 -05:00
Avi
6e627a3341 Replace upload file paths with single-use pick tokens 2026-08-21 13:48:34 -05:00
Avi
4bde3957b9 Restrict renderer IPC to an explicit method allowlist 2026-08-21 13:30:58 -05:00
Avi
5b0b87b784 Repair project paths after move 2026-08-20 18:50:19 -05:00
Avi
a1445d17a8 Add contact-aware feed scope
- src/feed.rs: contact_feed + contact_pubkeys fetch the active profile's
  kind 3 contact list and aggregate notes only from those authors;
  aggregate_for + FeedBuilder accept an optional author whitelist
- IPC: FeedGet accepts contacts_only, resolves the active profile npub
- CLI: feed --contacts [limit] filters to the active profile's contacts
- Frontend: Feed screen Everyone/My contacts toggle, scope-aware empty
  states, feedGet(limit, contactsOnly) threading
- Tests for author filtering and the contacts scope in feed.rs and
  FeedScreen.test.tsx
2026-08-06 11:01:27 -05:00
Avi
37a9d945c9 Add feed aggregation from enabled relays
- src/feed.rs: aggregate recent kind 1 notes from enabled relays into a
  newest-first, de-duplicated feed using a throwaway identity
- IPC: FeedGet; CLI: feed [limit]; frontend: Feed screen + nav + tests
- README: mark feed aggregation as shipped
2026-08-06 10:31:45 -05:00
Avi
ca3203cfc4 Require user approval for NIP-46 sign/encrypt requests 2026-08-06 10:03:50 -05:00
Avi
73cb08d856 Add NIP-46 remote signer (external signing)
Add a remote-signer (bunker) role so other Nostr apps can delegate
signing to this app's active profile keys via nostrconnect:// links.

Backend: new src/signer.rs implementing the NIP-46 protocol (kind 24133
events encrypted with NIP-44 v2 conversation keys). It parses
nostrconnect:// connect URIs, spawns an async task in the serve process
that reads relay requests, auto-approves once the handshake completes,
signs delegate events, and publishes responses. Exposes status, connect,
and disconnect via IPC and CLI (signer status / signer connect).

Other: ipc.rs serve/handle now share Arc<Mutex<App>>; main.rs adds the
signer CLI commands; Cargo.toml enables nostr nip46 feature.

Frontend: new Signer screen (nav item + sidebar entry with key icon)
to paste a nostrconnect:// link, connect/disconnect, and show the
connected peer and relays; wires signer_connect/_disconnect/_status
through api.ts and AppProvider; adds tests and test mocks.
2026-08-05 19:28:26 -05:00
Avi
d677125555 Show preview images and link cards in Compose 2026-08-04 13:53:12 -05:00
Avi
03f687717e Sign NIP-98 auth for nostr.build image uploads 2026-08-04 13:37:05 -05:00
Avi
3e3467b006 Add compose preview with image attachments (NIP-92 imeta) 2026-08-04 13:30:30 -05:00
Avi
17e8ace5ab Clarify the Profiles subtitle about private keys 2026-08-04 13:30:25 -05:00
Avi
8eb6685281 Add reveal-secret-key after unlock (CLI + GUI)
- profiles::reveal_secret_key returns a key in hex and nsec1... forms, gated on
  an unlocked vault (VaultLocked when encrypted + locked)
- IPC: reveal_secret_key method; error replies now carry a machine-readable
  code field (ErrorKind as snake_case, e.g. vault_locked)
- CLI: show-secret <npub> prompts for the vault password when locked
- GUI: 'Secret key' button per profile card opens a modal showing hex + nsec
  with copy buttons; locked vaults ask for the password inline before revealing
- Tests: Rust (reveal plaintext/encrypted/locked) and Vitest (reveal flow,
  lock-then-unlock), all green
2026-08-04 12:09:30 -05:00
Avi
7ca1d14dcb Add password-encrypted vault
- Encrypt stored secret keys with AES-256-GCM under an Argon2id-derived key;
  the vault stays plaintext until a password is set (Settings -> Storage or
  the CLI set-password command)
- Only secret keys are encrypted; labels and npubs stay readable so profiles
  can be browsed while the vault is locked
- Backend: crypto module, Vault.crypto metadata, unlock/lock/set/remove
  password on App, VaultLocked/WrongPassword errors, secret resolution on the
  publish path
- IPC: set_vault_password, unlock_vault, lock_vault, remove_vault_password
- CLI: set-password, remove-password, unlock; create/publish prompt when the
  vault is locked (NFM_PASSWORD env or hidden prompt, never argv)
- GUI: unlock banner + modal on locked vaults, protect/change/remove password
  in Settings, password field styling
- Tests: Rust (argon2/AES round-trips, vault lifecycle) and Vitest (unlock
  flow, set/change/remove password), all green
2026-08-03 19:00:41 -05:00
Avi
7e3bac345c Add Nostr Feed Manager: Rust backend with Electron + React GUI
- Rust library (nostr-manager-backend) with CLI and JSON-lines IPC serve mode:
  profiles, publishing with per-relay reports, relays, settings, vault storage
  and legacy-vault migration
- Electron + React + TypeScript desktop GUI using the same backend over stdio IPC
- Vitest suite with a fake backend speaking the real protocol
- electron-builder linux packaging; README with build and usage instructions
2026-08-03 16:05:59 -05:00