import { execFileSync } from "node:child_process"; import { existsSync, readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const browserRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const androidRoot = resolve(browserRoot, "../peach-android"); const localJavaHome = "/opt/homebrew/opt/openjdk@17"; const javaHome = process.env.JAVA_HOME ?? (existsSync(localJavaHome) ? localJavaHome : undefined); const browserCoordinator = readFileSync( resolve(browserRoot, "src/background/sync-coordinator.ts"), "utf8", ); const androidCoordinator = readFileSync( resolve(androidRoot, "app/src/main/java/com/peachpasswords/sync/SyncCoordinator.kt"), "utf8", ); const browserSyncTypes = readFileSync(resolve(browserRoot, "src/shared/sync-types.ts"), "utf8"); const androidManifest = readFileSync( resolve(androidRoot, "app/src/main/java/com/peachpasswords/sync/DeviceManifestSupport.kt"), "utf8", ); const browserPairedDevices = readFileSync( resolve(browserRoot, "src/background/paired-devices.ts"), "utf8", ); const androidPairedDevices = readFileSync( resolve(androidRoot, "app/src/main/java/com/peachpasswords/sync/PairedDeviceStore.kt"), "utf8", ); if (browserCoordinator.includes('helloIn.version === localVersion')) { throw new Error("Browser still contains the forbidden equal-version fast path"); } if (!browserCoordinator.includes("helloIn.deviceManifestVersion === DEVICE_MANIFEST_VERSION")) { throw new Error("Browser does not negotiate device manifests from SYNC_HELLO"); } if (!androidCoordinator.includes("val exchangeDeviceManifest = vault.negotiatesDeviceManifest(hello)")) { throw new Error("Android does not negotiate device manifests from SYNC_HELLO"); } if (!androidCoordinator.includes("peerVersion == DEVICE_MANIFEST_VERSION")) { throw new Error("Android does not require an exact device-manifest version match"); } if (!browserSyncTypes.includes("DEVICE_MANIFEST_VERSION = 0x04") || !androidManifest.includes("DEVICE_MANIFEST_VERSION = 0x04")) { throw new Error("Browser and Android device-manifest versions differ"); } if (!browserPairedDevices.includes("MAX_REVOCATIONS = 500") || !androidPairedDevices.includes("MAX_REVOCATION_RECORDS = 500")) { throw new Error("Browser and Android revocation ledger caps differ"); } if (!browserPairedDevices.includes("enqueueDeviceMutation") || !androidPairedDevices.includes("RegistryMutationGate")) { throw new Error("A paired-device registry lacks whole-list mutation serialization"); } if (!browserPairedDevices.includes("function capRevocations") || !androidPairedDevices.includes("fun capRevocationRecords")) { throw new Error("A client lacks largest-issuer-first revocation retention"); } execFileSync( "npm", [ "test", "--", "--run", "src/background/sync-coordinator.test.ts", "src/shared/sync-padding.test.ts", "src/shared/rendezvous.test.ts", "src/shared/device-manifest.test.ts", "src/crypto/peachPayload.test.ts", "src/shared/sync-entry-envelope.kat.test.ts", "src/shared/vault-adopt.test.ts", "src/background/paired-devices.test.ts", "src/background/relay-adoption-bg.test.ts", ], { cwd: browserRoot, stdio: "inherit" }, ); execFileSync( resolve(androidRoot, "gradlew"), [ "--no-configuration-cache", "testDebugUnitTest", "--tests", "com.peachpasswords.sync.SyncCoordinatorTest", "--tests", "com.peachpasswords.sync.LockedSyncSpoolModelTest", "--tests", "com.peachpasswords.sync.SyncPaddingTest", "--tests", "com.peachpasswords.sync.DeviceManifestSupportTest", "--tests", "com.peachpasswords.CrossPlatformKATTest", "--tests", "com.peachpasswords.vault.PeachScriptTest", "--tests", "com.peachpasswords.sync.SyncEntryEnvelopeKatTest", "--tests", "com.peachpasswords.sync.VaultAdoptTest", "--tests", "com.peachpasswords.sync.PairedDeviceRevocationTest", ], { cwd: androidRoot, env: { ...process.env, ...(javaHome ? { JAVA_HOME: javaHome } : {}) }, stdio: "inherit", }, ); console.log("Cross-client sync protocol gate passed.");