// IV.7 — Static safety assertions for vault sync. // These tests read source files to enforce structural invariants that // are cheaper to verify statically than to exercise at runtime. import { describe, expect, it } from "vitest"; import { readFileSync } from "node:fs"; import { resolve } from "node:path"; const here = __dirname; const src = (rel: string) => readFileSync(resolve(here, rel), "utf8"); describe("vault sync — static safety assertions", () => { it("no WebSocket server in any browser-extension sync source file", () => { const files = [ "./sync-trigger.ts", "./sync-runner.ts", "./sync-coordinator.ts", "./sync-vault-adapter.ts", "../shared/sync-transport.ts", ]; const forbidden = /WebSocketServer|wss\.listen|createServer|http\.listen|net\.listen/; for (const f of files) { expect(src(f), `${f} must not start a WebSocket server`).not.toMatch(forbidden); } }); it("applyMergedRemoteEntries does not call fireSyncTrigger or TRIGGER_SYNC", () => { const vaultSrc = src("./vault.ts"); const fnStart = vaultSrc.indexOf("applyMergedRemoteEntries"); expect(fnStart, "applyMergedRemoteEntries must exist in vault.ts").toBeGreaterThan(-1); // Grab a generous slice starting from the function — large enough to cover // the implementation but not so large that it bleeds into unrelated code. const fnBody = vaultSrc.slice(fnStart, fnStart + 4000); expect(fnBody).not.toMatch(/triggerSyncIfReachable|TRIGGER_SYNC|fireSyncTrigger/); }); it("device registry is stored in chrome.storage.local, not chrome.storage.sync", () => { const registrySrc = src("./paired-devices.ts"); expect(registrySrc).toContain("storage.local"); expect(registrySrc).not.toMatch( /storage\.sync[^;]*peach_paired_devices|peach_paired_devices[^;]*storage\.sync/, ); }); it("setSyncRunner and productionSyncRunner are called in entry.ts", () => { const entrySrc = src("./entry.ts"); expect(entrySrc).toContain("setSyncRunner"); expect(entrySrc).toContain("productionSyncRunner"); }); it("sync-trigger syncs both direct and user-confirmed vouched hosts", () => { const triggerSrc = src("./sync-trigger.ts"); expect(triggerSrc).toMatch(/trustSource === "direct"/); // Mesh introduction is pointless if a device the user confirmed out of the // MV-7 pending queue is then never dialled. expect(triggerSrc).toMatch(/trustSource === "vouched"/); }); it("pairing stays relay-only with no local server or audio-chirp module", () => { const appSrc = src("../popup/App.tsx"); expect(appSrc).not.toContain("openPairingServer"); expect(appSrc).not.toContain("chirp-pair-capacitor"); // Onboarding adoption now has the browser source a pairing-request QR // (the phone scans it). The browser still doesn't dial — the phone does. // The relay socket that holds the rendezvous is opened in the background // via START_ADOPTION_RECEIVER, not in the popup itself. expect(appSrc).not.toContain("dialRelayPairingChannel"); const sharedTypes = src("../shared/types.ts"); expect(sharedTypes).toContain("START_ADOPTION_RECEIVER"); expect(appSrc).not.toContain("openPairingSocket"); }); it("vault_id uses the full 64-char BLAKE3 hex digest", () => { const identitySrc = src("../shared/sync-identity.ts"); expect(identitySrc).toContain("VAULT_ID_HEX_LENGTH = 64"); expect(identitySrc).not.toContain("VAULT_ID_HEX_LENGTH = 16"); }); it("per-entry key derivation uses entryId as part of HKDF info", () => { const adapterSrc = src("./sync-vault-adapter.ts"); expect(adapterSrc).toContain("ENTRY_KEY_INFO_SUFFIX"); expect(adapterSrc).toContain("sync-entry-v1"); // The info must be derived from entryId — look for the concat pattern. expect(adapterSrc).toMatch(/entryId.*ENTRY_KEY_INFO_SUFFIX|ENTRY_KEY_INFO_SUFFIX.*entryId/); }); });