Files
amethyst/desktopApp/plans/2026-08-11-new-account-key-onboarding-plan.md
nrobi144andClaude Opus 4.8 b6210e9fd0 feat(desktop): guided first-run key backup + reachable settings backup
Reworks the Desktop new-account key backup after testing surfaced that the
original card never rendered and the settings entry sat on dead code.

- Guided 3-step "Save your keys" onboarding (NewKeyOnboardingScreen), full
  window + scrollable so it never clips. Used by BOTH the cold-start login and
  the in-app "+ Add Account" generate paths. Retires NewKeyWarningCard.
- Split key generation from activation (AccountManager.buildNewAccount +
  activateAccount + begin/finish/cancelNewAccountOnboarding). generateNewAccount
  previously flipped account state immediately, tearing down the screen before
  any backup UI could show — the root cause of "no save-your-keys prompt".
- Move BackupKeysCard into the reachable Settings screen (RelaySettingsScreen);
  the old ProfileScreen host had no call sites.
- Fix the password show/hide eye (was a non-clickable Icon) in both the
  onboarding and settings encrypted-copy sections.
- Run NIP-49 encryption off the UI thread so the "Copy encrypted" button stays
  responsive and reliably flips to "Copied!"; match the plain copy button style.
- Add EncryptedKeyBackupTest: nsec -> hex -> Nip49 encrypt -> decrypt round-trip
  (and wrong-password fails).
- Plans + manual testing sheet under desktopApp/plans/.

Known follow-up: Desktop loginWithKey does not yet import ncryptsec1, so
encrypted backups can't be restored on Desktop yet (Android already handles it).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-13 06:54:55 +03:00

104 lines
5.6 KiB
Markdown

# First-Run "Save Your Keys" Onboarding — Plan (Desktop)
Date: 2026-08-11
Branch: `feat/key-backup-nsec-exposure`
Supersedes: the single `NewKeyWarningCard` for freshly-generated accounts.
## Why
New-account key backup is the highest-stakes moment in a Nostr client: the
`nsec` is shown once and can never be reset. Current impl crams warning + npub +
nsec + encrypted-copy + checkbox + continue into one `NewKeyWarningCard`. Inside
the 480px add-account dialog it has no scroll, so it clips — labels above and the
Continue button below are cut off → reads as "no label / no way forward". Even
un-clipped, one dense card is confusing.
Decision (user): **guided multi-step full-screen flow**, **soft checkbox gate**.
## What already exists (reuse — don't rebuild)
- **Split generation** (just built): `AccountManager.buildNewAccount()` creates the
keypair WITHOUT activating it; `activateAccount(state)` flips account state.
This is what lets a backup step render before the account switch tears the
screen down. Keep.
- **Entry points** that generate a key:
- Cold start: `LoginScreen` (`onGenerateNew` → `buildNewAccount()`).
- Logged-in: `AddAccountDialog` (`onGenerateNew` → `buildNewAccount()`), confirmed
via `onNewAccountConfirmed` on the App scope.
- **Pieces to lift out of `NewKeyWarningCard`**: `CopyKeyButton`, `EncryptedCopyRow`
(NIP-49 password → `ncryptsec1`), `SelectableKeyText`, the warning strings
(`new_key_*`). The `nsec→hex` decode (`decodePrivateKeyAsHexOrNull`) + `Nip49`.
- **QR**: `QrCodeCanvas(data)` — npub only, never nsec.
- **Settings** backup card (`BackupKeysCard`) already covers "view my keys later".
## Design — `NewKeyOnboardingScreen` (stepper, 3 steps)
A full-window composable (NOT a dialog). Rendered while `buildNewAccount()` result
is held and before `activateAccount`. Fixed max content width (~560dp), centered,
each step vertically scrollable so nothing clips.
**Step 1 — Why this matters (education)**
- Headline "Save your keys" + plain-language explainer: npub = your public
identity (shareable); nsec = a password that can never be reset or recovered —
lose it and the account is gone. No inputs. [Next].
**Step 2 — Your keys (the actual backup)**
- **Public key (npub)**: monospace, Copy, optional Show QR.
- **Secret key (nsec)**: monospace (shown — this is the one moment we intentionally
reveal it), **Copy** (primary, prominent) + best-effort clipboard auto-clear.
- **Copy encrypted (recommended)**: collapsible/secondary — password field →
`ncryptsec1`. Keep out of the way so the primary Copy is obvious.
- Strong "never share the nsec" inline warning. No nsec QR. [Back] [Next].
**Step 3 — Confirm & continue (soft gate)**
- Recap one line ("Stored somewhere safe? A password manager is ideal.").
- **Soft checkbox** "I have saved my keys somewhere safe" → enables **Continue**.
(Honor-system, matches the Android nudge decision. No copy/verify enforcement.)
- Continue → `activateAccount(state)` + persist + proceed into the app.
Progress indicator (e.g. "Step 2 of 3" or dots). [Back] on 2/3.
## Integration
- **New file**: `desktopApp/.../ui/auth/NewKeyOnboardingScreen.kt` (stepper +
step composables; reuse the extracted Copy/Encrypt pieces).
- **Cold start**: in `LoginScreen`, when `generatedAccount != null` render the
onboarding screen full-bleed instead of the inline card. `onFinish` =
`activateAccount` + `onLoginSuccess`.
- **Add-account**: when a key is generated, DON'T keep it inside the small dialog.
Either (a) dismiss the dialog and show the onboarding screen at the App level
(preferred — full space, survives the later account switch), or (b) let the
onboarding screen be the dialog's content at a larger, scrollable size. Pick (a)
for consistency with the cold-start path: hoist a top-level
`pendingNewAccount: AccountState.LoggedIn?` in the App composable; both entry
points set it; one `NewKeyOnboardingScreen` renders when non-null; `onFinish`
activates + persists on the App scope. This unifies both flows through one
screen and removes the dialog-clipping problem entirely.
- **Retire** `NewKeyWarningCard` (and its Preview) once both paths use the stepper.
## Testing (add to the manual sheet)
- Cold start: log out → Generate → 3-step screen, no clipping, Copy works,
encrypted copy → `ncryptsec1`, checkbox gates Continue, Continue lands in app.
- Add account (already logged in): Add → Generate → same screen at App level (not a
cramped dialog), Continue switches to the new account + persists (survives
restart).
- Back/Next preserve state; window resize keeps everything reachable (scroll).
- NIP-49 round trip (encrypted copy → login elsewhere → same npub).
## Non-goals / follow-ups
- Android first-run guided screen (Android already has `AccountBackupScreen` +
post-signup nudge; a matching stepper is a separate follow-up).
- Hard copy/verify enforcement (explicitly declined — soft gate).
- Mnemonic (NIP-06) backup.
## Unanswered questions
- Add-account path: hoist to App-level full-screen (recommended) vs enlarge the
dialog to host the stepper? (Plan assumes hoist.)
- Does generating from the logged-in state and cancelling mid-onboarding need an
explicit "discard this new key" confirm, or is silent discard fine?
- Show the nsec revealed by default on Step 2 (it's first-run, user must save it) —
or masked-with-reveal like the Settings card? (Plan assumes shown, since the
whole point is to save it now.)
- Progress UI: numbered "Step X of 3" vs dots vs a top wizard bar?
- Keep the `NewKeyWarningCard` as a fallback anywhere, or fully delete?