Commit graph

14 commits

Author SHA1 Message Date
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
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
6e627a3341 Replace upload file paths with single-use pick tokens 2026-08-21 13:48:34 -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
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