Frontend half of PLANS/NIP49_LOCAL_BACKUP_PLAN.md Rev 3 (D3):
- BackupStep: encrypted by default. The default path never invokes
get_nsec — the webview only ever sees the finished ncryptsec1 blob
returned by create_ncryptsec_backup. The raw key path survives behind
an explicit 'Show raw key instead' click with its previous
loading/error/skip semantics.
- EncryptedBackupCreator (shared by onboarding + settings): generated
6-word passphrase default with cannot-be-recovered copy, 'choose my
own' = min 12 chars + confirmation, create -> masked display + copy +
'Save a copy…' via the native dialog.
- encryptedBackup.ts: pure reducer/validation model, unit-tested without
a DOM; keyImportInput.ts: HRP classification + submit gating.
- NsecMaskedDisplay: kind='nsec'|'ncryptsec' drives labels/aria/testids;
existing nsec call sites unchanged.
- NostrKeyImportForm: ncryptsec1 paste switches to encrypted mode
(passphrase field, no npub preview possible), decrypt errors surface;
raw nsec flow untouched. import_identity plumbs the optional password
through OnboardingFlow/MachineOnboardingFlow/KeyringLockedScreen.
- ProfileSettingsCard: 'Encrypted backup' row alongside the raw reveal.
- ncryptsecSourceScan.test.mjs: TS-side source-allowlist tripwire
mirroring the Rust scan (defense-in-depth per plan D4).
- e2e: mock bridge learns the three backup commands + ncryptsec import;
onboarding-backup.spec.ts covers the encrypted happy path (asserting
get_nsec is never called), custom-passphrase validation, raw fallback,
and error/retry; onboarding.spec.ts adds encrypted-import happy path
including a wrong-passphrase rejection.
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>