4.0.0
GUPT 4.0.0 — New Identity Model, Dedicated Streams, and a Simpler UI
This release accumulates 142 commits since
3.0.1. It is a breaking major bump — read the Breaking changes section before upgrading.
Breaking changes
1. Identity derivation replaced password + PIN with "memory anchors"
What changed. The old account recovery flow (derivePrivkeyFromPasswordPin, Argon2id over password + "\0" + pin with a gupt-kdf-v1 salt) is gone. v4 derives your key from a set of "brain factors" / memory anchors — passphrase, PIN, a special date, a secret person, favorite country, first pet, first car — that you answer from memory alone.
How it works now.
- Each anchor is normalized (IVs differ per field type), SHA-256 hashed, de-duplicated, then sorted by digest so slot order can never change the identity (
derivePrivkeyFromBrainFactors). - The canonical fold is fed to Argon2id (64 MiB, 3 passes) with a new
gupt-brain-kdf-v4salt. - You need at least 2 distinct anchors to reach the 80-bit entropy threshold; the UI shows live entropy and an estimated brute-force time.
Why. A single password + short numeric PIN was too guessable. Memory anchors spread entropy across independent facts, and the input-order-independent hash means you only have to remember the facts — not the order you typed them — to get back in.
What this means for you.
- Keys derived with the old password+PIN flow can no longer be re-derived in v4. You must restore from your original 64-char hex private key, a Gupt backup JSON, or any secret string — v4 classifies pasted input (
classifyPastedIdentitySecret): hex keys and backups import as-is, everything else is hardened through one Argon2id pass (gupt-secret-kdf-v1). - If you only ever knew your identity by password+PIN and didn't keep the hex key, back it up now before you sign out.
2. The Vault is gone — replaced by dedicated encrypted streams
What changed. vault.js, VaultView, VaultAddView and the vault create panel were deleted. The single grab-bag vault is now three separate, optimized, relay-synced streams, each with its own kind marker, 3-year expiry, tombstone deletes (no Kind 5), Dexie cache-first reads, and hybrid auto-renewal:
| Stream | Route | Marker | Encrypted payload |
|---|---|---|---|
| Passwords | #/passwords |
gupt_password |
title, username, email, password, uris[], totp, notes, tags |
| Notes | #/notes |
gupt_note |
title, body (Markdown), tags |
| Bookmarks | #/bookmarks |
gupt_bookmark |
title, url, tags |
Why. One generic list forced every item to fit the same shape — a notes app, a password manager, and a bookmarks view have different fields, and passwords genuinely need TOTP. Splitting them lets each stream keep its own schema, delete/renewal rules, and detail UI, while sharing one stream-renewal engine (streamRenewal.js).
What this means for you.
- Vault items stored on relays under the old scheme will no longer appear in the app. Re-add them as passwords/notes/bookmarks using the new list + detail views (
/passwords/:id,/notes/:id,/bookmarks/:id). - Passwords now support TOTP / 2FA: store a secret, get a live 6-digit code, copy username / password / code from the detail sheet.
- Notes are Markdown — headings, lists, links, code — rendered safely in-app, tag + searchable.
- Bookmarks gained encrypted tags, favicons, njump.me event inspection, manual "new" creation, and a reworked gupt-mark bookmarklet that prompts for tags and drags to your toolbar.
3. Temporary invites no longer leak your private key
What changed. Invite links previously embedded the private key. v4 generates a random 12-char token (generateInviteToken), resolves it to your key only on the receiver's side, and revokes temporary invites on first use (gupt_invite_revoked), with TTL options of 1h / 24h / 7d.
Why. An invite link is a bearer credential; embedding the full private key meant anyone who intercepted it got your permanent identity. Tokenized, single-use invites shrink the blast radius to a single short-lived handoff.
4. Servers folded into Settings
What changed. ServersView.vue and the /servers route are gone; /servers and /settings/servers now redirect to /settings. Relay and Originless config moved into a new Servers panel with stacked tabs, matching the active-list UX used elsewhere.
Why. Servers is an advanced, rarely-opened screen; a dedicated top-level tab wasted navigation space. Grouping it under Settings keeps one place for all network/storage knobs.
What else changed
Calls & WebRTC
- SAS call verification — end-to-end calls now show a short authentication string: 4 emojis + 4-digit code derived from both peers' SDP fingerprints, so you can confirm no man-in-the-middle (
webrtc/sas.js,extractSdpFingerprint). - Fix: stop the saved camera track when a call ends during screen share.
- Fix: renegotiate when screen sharing adds a track to an otherwise audio-only call.
- Fix: route call-decline signals to the correct peer; surface errors when answering from CallView.
- Fix: clear stale call-request state on end/timeout.
Reliability & relay layer
- Self-healing live subscription module for relay reads; reads resolve on EOSE and per-relay query health is recorded (
renewStreamItems/relay/). - Stream publishes now route through the send queue and are written to the local cache before acknowledgement — degraded networks can't drop items you just created (
mergeRawEventsByOriginupserts then returns the full cache). - Opportunistic stream renewal is throttled; stream items are kept when a relay refresh returns empty. Cache analytics now break down by origin and gupt tags.
- Expanded the default relay list with popular Nostr relays.
UI / UX
- Passwords, Notes, Bookmarks and Chat converted from split panes to list + detail subroutes (
BookmarkDetailView,NoteDetailView,PasswordDetailView), redesigned chat sidebar/cards/search, table-style bookmarks, flatter chrome,max-w-6xlcontainer constraining. - Switch account flow rebuilt: chooser → memory-anchor ("Memory identity") or "Paste secret" keypath, with live preview, debounce, and reset logic.
- New hardening pipeline / entropy ring on the identity screen with brute-force time estimate.
- Voice recording shows a waveform; tactile feedback via haptics; shimmer loaders on stream screens.
- Attach image/file buttons merged into one toggle menu; last-seen queried once on chat open (no caching/polling).
- Donate page shows the goal in USD via live BTC price; removed "Where Your Sats Go" section.
- Notification banner polished with bell badge + pill CTA; settings simplified into one-line toggles.
- Full public key shown with copy button on the account header; redundant QR share cards removed from Profile.
Housekeeping
- Added
AGENTS.md, new tests (brainDerivation,invites,pasteIdentity, expandedwebrtc), refreshed Flatpak manifests + screenshots, and clarified docs (GUPT is not a "Nostr app").
Full changelog: 3.0.1...4.0.0
Migration checklist
- Back up your current hex private key (Settings → Me → copy).
- Re-create any vault items as Passwords / Notes / Bookmarks before upgrading installs.
- Re-generate temporary invite links (old ones are disabled).