Files
buzz/desktop/src/shared/lib/ncryptsecSourceScan.test.mjs
T
Taylor Ho 6dca931df6 feat(onboarding): replace post-download blob view with Test your backup flow
- Add BackupTestFlow.tsx: after downloading the Keycase, the step becomes an
  explicit "Test your backup" view — a large dropzone for the downloaded
  file, then a password prompt that succeeds the instant the password is
  typed completely, ending in a spring-in check badge with an emoji burst
  celebration (skipped under reduced motion)
- Verification is instant and KDF-free: the dropped file's bytes are
  compared to the committed ncryptsec blob and the typed password to the
  in-memory passphrase, so no key material beyond what the creator already
  held enters the component
- Wrong files get inline errors (Keycase-but-different vs not-a-Keycase);
  full-length wrong passwords get a mismatch hint; a "Re-download backup"
  button re-opens the native save dialog and "Use a different file" returns
  to the dropzone
- EncryptedBackupCreator.tsx: swap the masked-ncryptsec result view
  (NsecMaskedDisplay + "Save a copy…") for BackupTestFlow
- DownloadKeyStep.tsx: header/subtitle now conditional — "Backup your key
  with a password" while creating, "Test your backup" once created; remove
  the bracketed shell-box visual, the keep-this-file-private hints, and the
  "back up anytime in Settings" footer note
- BackupStep.tsx / MachineOnboardingFlow.tsx: chooser footer "Next" now
  always leads into the download step (skip lives there as "Skip for now")
- Update onboarding-backup.spec.ts happy path to drive the new flow
  (wrong file, right file, wrong password, success, Next) with screenshots;
  align docked-CTA spec and passThroughBackupStep helper with the new
  navigation; allowlist BackupTestFlow.tsx in the ncryptsec source scan

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-07-28 23:59:48 -07:00

69 lines
2.4 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import test from "node:test";
// Structural tripwire (plan D4, defense-in-depth): NIP-49 backup material
// handling in the webview is confined to the identity/backup/import UI and
// its API wrappers. Anything else in `desktop/src` touching `ncryptsec` is
// structural drift toward an unguarded egress path and must be reviewed —
// the runtime guarantee lives in src-tauri's egress guard, this scan only
// keeps the blob from quietly spreading through the frontend.
//
// Mirror of the Rust-side scan in
// `src-tauri/src/egress_guard_tests.rs::ncryptsec_handling_is_confined_to_allowlisted_files`.
const SRC_ROOT = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"../..",
);
const ALLOWLIST = [
"shared/api/tauriIdentity.ts",
"features/onboarding/lib/encryptedBackup.ts",
"features/onboarding/lib/encryptedBackup.test.mjs",
"features/onboarding/lib/keyImportInput.ts",
"features/onboarding/lib/keyImportInput.test.mjs",
"features/onboarding/ui/BackupStep.tsx",
"features/onboarding/ui/BackupTestFlow.tsx",
"features/onboarding/ui/EncryptedBackupCreator.tsx",
"features/onboarding/ui/NostrKeyImportForm.tsx",
"features/onboarding/ui/NsecMaskedDisplay.tsx",
"features/settings/ui/ProfileSettingsCard.tsx",
// e2e-only mock bridge (never in the production bundle):
"testing/e2eBridge.ts",
// this scan:
"shared/lib/ncryptsecSourceScan.test.mjs",
];
function* walk(dir) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
yield* walk(full);
} else if (/\.(ts|tsx|mjs|js|jsx)$/.test(entry.name)) {
yield full;
}
}
}
test("ncryptsec handling is confined to allowlisted frontend files", () => {
const violations = [];
for (const file of walk(SRC_ROOT)) {
const rel = path.relative(SRC_ROOT, file).replaceAll("\\", "/");
if (ALLOWLIST.includes(rel)) continue;
const content = fs.readFileSync(file, "utf8");
if (content.toLowerCase().includes("ncryptsec")) {
violations.push(rel);
}
}
assert.deepEqual(
violations,
[],
`NIP-49 material outside allowlisted files — wire it through the ` +
`identity layer (and its egress-guarded Rust commands) instead:\n` +
violations.join("\n"),
);
});