12345import { describe, expect, it } from "vitest";6import { readFileSync } from "node:fs";7import { resolve } from "node:path";89const here = __dirname;10const src = (rel: string) => readFileSync(resolve(here, rel), "utf8");1112describe("vault sync — static safety assertions", () => {13 it("no WebSocket server in any browser-extension sync source file", () => {14 const files = [15 "./sync-trigger.ts",16 "./sync-runner.ts",17 "./sync-coordinator.ts",18 "./sync-vault-adapter.ts",19 "../shared/sync-transport.ts",20 ];21 const forbidden = /WebSocketServer|wss\.listen|createServer|http\.listen|net\.listen/;22 for (const f of files) {23 expect(src(f), `${f} must not start a WebSocket server`).not.toMatch(forbidden);24 }25 });2627 it("applyMergedRemoteEntries does not call fireSyncTrigger or TRIGGER_SYNC", () => {28 const vaultSrc = src("./vault.ts");29 const fnStart = vaultSrc.indexOf("applyMergedRemoteEntries");30 expect(fnStart, "applyMergedRemoteEntries must exist in vault.ts").toBeGreaterThan(-1);31 32 33 const fnBody = vaultSrc.slice(fnStart, fnStart + 4000);34 expect(fnBody).not.toMatch(/triggerSyncIfReachable|TRIGGER_SYNC|fireSyncTrigger/);35 });3637 it("addEntryDirect / updateEntryDirect / deleteEntryDirect do not call fireSyncTrigger", () => {38 const vaultSrc = src("./vault.ts");39 for (const fn of ["addEntryDirect", "updateEntryDirect", "deleteEntryDirect"]) {40 const start = vaultSrc.indexOf(`function ${fn}`);41 if (start === -1) continue;42 43 44 const nextExport = vaultSrc.indexOf("\nexport ", start + fn.length);45 const end = nextExport > start ? nextExport : start + 600;46 const body = vaultSrc.slice(start, end);47 expect(body, `${fn} must not call fireSyncTrigger`).not.toMatch(48 /triggerSyncIfReachable|TRIGGER_SYNC|fireSyncTrigger/,49 );50 }51 });5253 it("device registry is stored in chrome.storage.local, not chrome.storage.sync", () => {54 const registrySrc = src("./paired-devices.ts");55 expect(registrySrc).toContain("storage.local");56 expect(registrySrc).not.toMatch(57 /storage\.sync[^;]*peach_paired_devices|peach_paired_devices[^;]*storage\.sync/,58 );59 });6061 it("setSyncRunner and productionSyncRunner are called in entry.ts", () => {62 const entrySrc = src("./entry.ts");63 expect(entrySrc).toContain("setSyncRunner");64 expect(entrySrc).toContain("productionSyncRunner");65 });6667 it("sync-trigger syncs both direct and user-confirmed vouched hosts", () => {68 const triggerSrc = src("./sync-trigger.ts");69 expect(triggerSrc).toMatch(/trustSource === "direct"/);70 71 72 expect(triggerSrc).toMatch(/trustSource === "vouched"/);73 });7475 it("pairing stays relay-only with no local server or audio-chirp module", () => {76 const appSrc = src("../popup/App.tsx");77 expect(appSrc).not.toContain("openPairingServer");78 expect(appSrc).not.toContain("chirp-pair-capacitor");79 80 81 82 83 expect(appSrc).not.toContain("dialRelayPairingChannel");84 const sharedTypes = src("../shared/types.ts");85 expect(sharedTypes).toContain("START_ADOPTION_RECEIVER");86 expect(appSrc).not.toContain("openPairingSocket");87 });8889 it("vault_id uses the full 64-char BLAKE3 hex digest", () => {90 const identitySrc = src("../shared/sync-identity.ts");91 expect(identitySrc).toContain("VAULT_ID_HEX_LENGTH = 64");92 expect(identitySrc).not.toContain("VAULT_ID_HEX_LENGTH = 16");93 });9495 it("per-entry key derivation uses entryId as part of HKDF info", () => {96 const adapterSrc = src("./sync-vault-adapter.ts");97 expect(adapterSrc).toContain("ENTRY_KEY_INFO_SUFFIX");98 expect(adapterSrc).toContain("sync-entry-v1");99 100 expect(adapterSrc).toMatch(/entryId.*ENTRY_KEY_INFO_SUFFIX|ENTRY_KEY_INFO_SUFFIX.*entryId/);101 });102});