From ca7270fff88e74cb3d34bd7c65075b6e90850229 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Fri, 2 Oct 2026 17:19:49 +0530 Subject: [PATCH 1/7] fix: validate dependency audit results --- package.json | 4 +- pnpm-lock.yaml | 28 ++++----- scripts/check-code-health.mjs | 29 ++------- scripts/dependency-audit.mjs | 93 +++++++++++++++++++++++++++++ scripts/dependency-audit.test.mjs | 98 +++++++++++++++++++++++++++++++ vitest.config.ts | 1 + 6 files changed, 211 insertions(+), 42 deletions(-) create mode 100644 scripts/dependency-audit.mjs create mode 100644 scripts/dependency-audit.test.mjs diff --git a/package.json b/package.json index 1d3e5f3..16b7b33 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,9 @@ }, "pnpm": { "overrides": { - "nanoid@>=3.0.0 <4.0.0": "3.3.18" + "brace-expansion@>=5.0.0 <6.0.0": "5.0.11", + "nanoid@>=3.0.0 <4.0.0": "3.3.18", + "undici@^5.28.5": "6.29.0" } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef17351..f87ddb1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,9 @@ settings: excludeLinksFromLockfile: false overrides: + brace-expansion@>=5.0.0 <6.0.0: 5.0.11 nanoid@>=3.0.0 <4.0.0: 3.3.18 + undici@^5.28.5: 6.29.0 importers: @@ -483,10 +485,6 @@ packages: cpu: [x64] os: [win32] - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -957,8 +955,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - brace-expansion@5.0.9: - resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + brace-expansion@5.0.11: + resolution: {integrity: sha512-awigjhi6cLTh90bdw6+QJ9CtmJmyYhEIi70iCbc8Rozn04Fw9FeQIBjv/E22FFGuCGx1bLJyUfB64x/szUSXUg==} engines: {node: 20 || >=22} capnp-ts@0.7.0: @@ -1495,9 +1493,9 @@ packages: resolution: {integrity: sha512-b7zoBQvpWp0vuN5q2vK2RRBR2SvuruQAs50DApdDveBSn3eSYd84IaHodFqQIMlvY9K2VnyBUEXgwOBuGU9GBg==} engines: {node: '>=14'} - undici@5.29.0: - resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} - engines: {node: '>=14.0'} + undici@6.29.0: + resolution: {integrity: sha512-R+RODBqp6i2pPflGdq+xIOUkl+RNfGgHwoinecKu/JCuf2uO06cOKoDbI2P7Dn6KcswdKwrczbU6IYJ6K8X+wg==} + engines: {node: '>=18.17'} unenv@2.0.0-rc.0: resolution: {integrity: sha512-H0kl2w8jFL/FAk0xvjVing4bS3jd//mbg1QChDnn58l9Sc5RtduaKmLAL8n+eBw5jJo8ZjYV7CrEGage5LAOZQ==} @@ -1895,8 +1893,6 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@fastify/busboy@2.1.1': {} - '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -2210,7 +2206,7 @@ snapshots: balanced-match@4.0.4: {} - brace-expansion@5.0.9: + brace-expansion@5.0.11: dependencies: balanced-match: 4.0.4 @@ -2527,7 +2523,7 @@ snapshots: exit-hook: 2.2.1 glob-to-regexp: 0.4.1 stoppable: 1.1.0 - undici: 5.29.0 + undici: 6.29.0 workerd: 1.20240718.0 ws: 8.21.1 youch: 3.3.4 @@ -2539,7 +2535,7 @@ snapshots: minimatch@10.2.6: dependencies: - brace-expansion: 5.0.9 + brace-expansion: 5.0.11 minipass@7.1.3: {} @@ -2802,9 +2798,7 @@ snapshots: unbash@4.0.10: {} - undici@5.29.0: - dependencies: - '@fastify/busboy': 2.1.1 + undici@6.29.0: {} unenv@2.0.0-rc.0: dependencies: diff --git a/scripts/check-code-health.mjs b/scripts/check-code-health.mjs index 45f55b6..2eb83f3 100644 --- a/scripts/check-code-health.mjs +++ b/scripts/check-code-health.mjs @@ -6,6 +6,7 @@ import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import process from "node:process"; import { fileURLToPath } from "node:url"; +import { summarizeDependencyAudit } from "./dependency-audit.mjs"; const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const productionPaths = ["protocol", "server/src", "web/src", "ios/Sources"]; @@ -216,37 +217,17 @@ function checkDuplication() { function checkDependencies() { const result = run("pnpm", ["audit", "--json"], { allowFailure: true }); - const report = JSON.parse(result.stdout); - const severe = Object.entries(report.advisories ?? {}).filter( - ([, advisory]) => ["critical", "high"].includes(advisory.severity) - ); - const allowedHigh = new Set(["1114638", "1114640", "1121245"]); - const unexpected = severe.filter(([id]) => !allowedHigh.has(id)); - const missing = [...allowedHigh].filter( - (id) => !severe.some(([observedId]) => observedId === id) - ); - const reviewDate = new Date("2026-09-12T00:00:00Z"); + const { dependencies, severe } = summarizeDependencyAudit(result); log( - `Dependencies: ${severe.length} critical/high advisories; ` + - `${severe.length - unexpected.length} accepted PartyKit/Miniflare findings.` + `Dependencies: ${dependencies} audited, ${severe.length} critical/high advisories.` ); - if (Date.now() >= reviewDate.getTime()) { - throw new Error( - "PartyKit dependency-risk exception expired on 2026-09-12 (#26)." - ); - } - if (unexpected.length > 0) { + if (severe.length > 0) { throw new Error( - `Unexpected critical/high advisories: ${unexpected + `Critical/high advisories must be resolved before passing: ${severe .map(([id, advisory]) => `${id}/${advisory.github_advisory_id}`) .join(", ")}` ); } - if (missing.length > 0) { - log( - `Dependency risk improved; remove resolved exceptions: ${missing.join(", ")}.` - ); - } } function countMatches(pattern) { diff --git a/scripts/dependency-audit.mjs b/scripts/dependency-audit.mjs new file mode 100644 index 0000000..a269bbf --- /dev/null +++ b/scripts/dependency-audit.mjs @@ -0,0 +1,93 @@ +const severities = new Set(["info", "low", "moderate", "high", "critical"]); +const advisoryLevels = ["critical", "high", "moderate", "low", "info"]; + +export function summarizeDependencyAudit(result) { + if (![0, 1].includes(result.status)) { + throw new Error( + `Dependency audit exited unexpectedly with status ${result.status}.` + ); + } + + let report; + try { + report = JSON.parse(result.stdout); + } catch { + throw new Error("Dependency audit returned invalid JSON."); + } + + if ( + !report || + typeof report !== "object" || + Array.isArray(report) || + report.error || + !report.advisories || + typeof report.advisories !== "object" || + Array.isArray(report.advisories) || + !report.metadata?.vulnerabilities || + typeof report.metadata.vulnerabilities !== "object" || + !Number.isInteger(report.metadata.dependencies) || + report.metadata.dependencies < 0 || + !Number.isInteger(report.metadata.totalDependencies) || + report.metadata.totalDependencies < report.metadata.dependencies + ) { + throw new Error( + "Dependency audit returned an incomplete or unexpected report." + ); + } + + for (const severity of advisoryLevels) { + if ( + !Number.isInteger(report.metadata.vulnerabilities[severity]) || + report.metadata.vulnerabilities[severity] < 0 + ) { + throw new Error( + "Dependency audit returned malformed vulnerability counts." + ); + } + } + + for (const [id, advisory] of Object.entries(report.advisories)) { + if ( + !/^\d+$/u.test(id) || + !advisory || + typeof advisory !== "object" || + !severities.has(advisory.severity) || + typeof advisory.github_advisory_id !== "string" + ) { + throw new Error( + `Dependency audit returned a malformed advisory (${id}).` + ); + } + } + + if (result.status === 1 && Object.keys(report.advisories).length === 0) { + throw new Error("Dependency audit failure has no advisory explanation."); + } + + const advisoryCounts = Object.fromEntries( + advisoryLevels.map((severity) => [ + severity, + Object.values(report.advisories).filter( + (advisory) => advisory.severity === severity + ).length, + ]) + ); + if ( + advisoryLevels.some( + (severity) => + report.metadata.vulnerabilities[severity] !== advisoryCounts[severity] + ) + ) { + throw new Error( + "Dependency audit advisory details do not match its vulnerability counts." + ); + } + + const severe = Object.entries(report.advisories).filter(([, advisory]) => + ["critical", "high"].includes(advisory.severity) + ); + return { + dependencies: report.metadata.totalDependencies, + severe, + }; +} diff --git a/scripts/dependency-audit.test.mjs b/scripts/dependency-audit.test.mjs new file mode 100644 index 0000000..4e15437 --- /dev/null +++ b/scripts/dependency-audit.test.mjs @@ -0,0 +1,98 @@ +import { describe, expect, it } from "vitest"; +import { summarizeDependencyAudit } from "./dependency-audit.mjs"; + +function auditResult({ status = 0, advisories = {}, error } = {}) { + const vulnerabilities = { + info: 0, + low: 0, + moderate: 0, + high: 0, + critical: 0, + }; + for (const advisory of Object.values(advisories)) { + vulnerabilities[advisory.severity] += 1; + } + return { + status, + stdout: JSON.stringify({ + ...(error ? { error } : {}), + advisories, + metadata: { + vulnerabilities, + dependencies: 10, + totalDependencies: 10, + }, + }), + }; +} + +describe("dependency audit gate", () => { + it("accepts a clean, valid report", () => { + expect(summarizeDependencyAudit(auditResult())).toEqual({ + dependencies: 10, + severe: [], + }); + }); + + it("accepts nonzero status for a valid advisory report and returns severe findings", () => { + const advisory = { severity: "high", github_advisory_id: "GHSA-test" }; + const result = summarizeDependencyAudit( + auditResult({ status: 1, advisories: { 123: advisory } }) + ); + + expect(result.severe).toEqual([["123", advisory]]); + }); + + it("rejects registry errors even when they exit nonzero", () => { + expect(() => + summarizeDependencyAudit( + auditResult({ status: 1, error: { code: "ENOTFOUND" } }) + ) + ).toThrow(/incomplete or unexpected report/u); + }); + + it.each(["not json", "{}", JSON.stringify({ advisories: {} })])( + "rejects malformed reports: %s", + (stdout) => { + expect(() => summarizeDependencyAudit({ status: 0, stdout })).toThrow(); + } + ); + + it("rejects unexpected audit process statuses", () => { + expect(() => summarizeDependencyAudit({ status: 2, stdout: "{}" })).toThrow( + /exited unexpectedly/u + ); + }); + + it("rejects failure status without an advisory explanation", () => { + expect(() => summarizeDependencyAudit(auditResult({ status: 1 }))).toThrow( + /no advisory explanation/u + ); + }); + + it.each([ + { dependencies: -1, totalDependencies: 10 }, + { dependencies: 10, totalDependencies: 9 }, + ])("rejects invalid dependency totals: %j", (counts) => { + const result = auditResult(); + const report = JSON.parse(result.stdout); + Object.assign(report.metadata, counts); + expect(() => + summarizeDependencyAudit({ ...result, stdout: JSON.stringify(report) }) + ).toThrow(/incomplete or unexpected report/u); + }); + + it("rejects report counts that do not match advisory details", () => { + const result = auditResult({ + advisories: { + 123: { severity: "high", github_advisory_id: "GHSA-test" }, + }, + }); + const report = JSON.parse(result.stdout); + report.metadata.vulnerabilities.high = 0; + + expect(() => + summarizeDependencyAudit({ ...result, stdout: JSON.stringify(report) }) + ).toThrow(/do not match/u); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 657f41c..915a2ea 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -11,6 +11,7 @@ export default defineConfig({ reportsDirectory: "coverage", }, include: [ + "scripts/**/*.test.mjs", "protocol/**/*.test.ts", "server/src/**/*.test.ts", "web/src/**/*.test.ts", From e1b0c962391c991e94d3f290f53bd5ee6c532672 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Fri, 2 Oct 2026 17:44:55 +0530 Subject: [PATCH 2/7] fix: preserve dependency audit parse cause --- scripts/dependency-audit.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dependency-audit.mjs b/scripts/dependency-audit.mjs index a269bbf..e21c905 100644 --- a/scripts/dependency-audit.mjs +++ b/scripts/dependency-audit.mjs @@ -11,8 +11,8 @@ export function summarizeDependencyAudit(result) { let report; try { report = JSON.parse(result.stdout); - } catch { - throw new Error("Dependency audit returned invalid JSON."); + } catch (error) { + throw new Error("Dependency audit returned invalid JSON.", { cause: error }); } if ( From cc9913c367a68dd48996f6d0e792fd35e2fd575b Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Fri, 2 Oct 2026 19:50:08 +0530 Subject: [PATCH 3/7] style: format dependency audit helper --- scripts/dependency-audit.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/dependency-audit.mjs b/scripts/dependency-audit.mjs index e21c905..82efa9b 100644 --- a/scripts/dependency-audit.mjs +++ b/scripts/dependency-audit.mjs @@ -12,7 +12,9 @@ export function summarizeDependencyAudit(result) { try { report = JSON.parse(result.stdout); } catch (error) { - throw new Error("Dependency audit returned invalid JSON.", { cause: error }); + throw new Error("Dependency audit returned invalid JSON.", { + cause: error, + }); } if ( From 0a1841bfce670aa4998d161fce5f6ff819d0283e Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Sat, 3 Oct 2026 00:16:03 +0530 Subject: [PATCH 4/7] fix: guard code health tooling and retain bounded relay checks --- scripts/check-code-health.mjs | 5 +- scripts/qualify-relay.mjs | 282 +++++++++++++++++++++++++++ scripts/qualify-relay.test.mjs | 19 ++ scripts/relay-fixture-guard.cjs | 71 +++++++ scripts/relay-fixture-guard.test.mjs | 35 ++++ scripts/swift-format-result.mjs | 15 ++ scripts/swift-format-result.test.mjs | 37 ++++ 7 files changed, 461 insertions(+), 3 deletions(-) create mode 100644 scripts/qualify-relay.mjs create mode 100644 scripts/qualify-relay.test.mjs create mode 100644 scripts/relay-fixture-guard.cjs create mode 100644 scripts/relay-fixture-guard.test.mjs create mode 100644 scripts/swift-format-result.mjs create mode 100644 scripts/swift-format-result.test.mjs diff --git a/scripts/check-code-health.mjs b/scripts/check-code-health.mjs index 2eb83f3..134db20 100644 --- a/scripts/check-code-health.mjs +++ b/scripts/check-code-health.mjs @@ -7,6 +7,7 @@ import { dirname, join, resolve } from "node:path"; import process from "node:process"; import { fileURLToPath } from "node:url"; import { summarizeDependencyAudit } from "./dependency-audit.mjs"; +import { countSwiftFormatDiagnostics } from "./swift-format-result.mjs"; const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const productionPaths = ["protocol", "server/src", "web/src", "ios/Sources"]; @@ -278,9 +279,7 @@ function checkSwiftFormat() { ["swift-format", "lint", "--strict", "--recursive", "ios/Sources"], { allowFailure: true } ); - const diagnostics = `${result.stdout}\n${result.stderr}` - .split("\n") - .filter((line) => line.includes("error:")).length; + const diagnostics = countSwiftFormatDiagnostics(result); log(`Swift format debt: ${diagnostics} diagnostics.`); // Ratcheted legacy debt: https://github.com/Significant-Hobbies/motion/issues/26 failRegressions("Swift format", { diagnostics }, { diagnostics: 4553 }); diff --git a/scripts/qualify-relay.mjs b/scripts/qualify-relay.mjs new file mode 100644 index 0000000..0d5950c --- /dev/null +++ b/scripts/qualify-relay.mjs @@ -0,0 +1,282 @@ +// Bounded real PartyKit qualification; no login, deployment, camera or provider. +import assert from "node:assert/strict"; +import { spawn } from "node:child_process"; +import { createHash } from "node:crypto"; +import { mkdtempSync, readFileSync, realpathSync } from "node:fs"; +import { builtinModules, createRequire } from "node:module"; +import { tmpdir } from "node:os"; +import { dirname, resolve, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { setTimeout as delay } from "node:timers/promises"; + +const root = fileURLToPath(new URL("../", import.meta.url)); +const binary = realpathSync( + resolve(root, "server/node_modules/partykit/dist/bin.mjs") +); +const partyRequire = createRequire(new URL(`file://${binary}`)); +const runtimeRequire = createRequire(partyRequire.resolve("miniflare")); +const { WebSocket } = runtimeRequire("undici"); +const map = JSON.parse(readFileSync(`${binary}.map`, "utf8")); +const manifest = JSON.parse( + map.sourcesContent[map.sources.indexOf("../package.json")] +); +const inventory = { + node: process.version, + partykit: manifest.version, + binarySha256: createHash("sha256").update(readFileSync(binary)).digest("hex"), + embeddedUndiciDeclaration: manifest.devDependencies.undici, + embeddedUndiciSources: map.sources.filter((source) => + source.includes("/undici/") + ).length, + miniflare: runtimeRequire("miniflare/package.json").version, + resolvedUndici: runtimeRequire("undici/package.json").version, + securityRemediation: "unproven: override does not rewrite embedded bytes", +}; +if (process.argv[2] === "--inspect-bundle") { + // Execute the executable's own CommonJS factories, stopping before CLI code. + // No source-map recompilation or substituted external Undici implementation. + const bytes = readFileSync(binary, "utf8"); + const start = bytes.indexOf("var __create = Object.create;"); + const factory = bytes.indexOf("var require_undici = __commonJS({"); + const end = bytes.indexOf("\n// ", factory); + assert(start > 0 && factory > start && end > factory); + const builtins = new Set( + builtinModules.map((name) => name.replace(/^node:/u, "")) + ); + const embedded = new Function( + "require", + "__filename", + "__dirname", + `${bytes.slice(start, end)}\nreturn require_undici();\n//# sourceURL=${binary}` + )( + (name) => { + assert( + builtins.has(name.replace(/^node:/u, "")), + `Unexpected bundled dependency: ${name}` + ); + return partyRequire(name); + }, + binary, + dirname(binary) + ); + const mock = new embedded.MockAgent(); + mock.disableNetConnect(); + mock + .get("http://fixture.invalid") + .intercept({ path: "/bundled", method: "GET" }) + .reply(200, "embedded-bytes-ok"); + try { + const response = await embedded.fetch("http://fixture.invalid/bundled", { + dispatcher: mock, + }); + assert.equal(await response.text(), "embedded-bytes-ok"); + mock.assertNoPendingInterceptors(); + } finally { + await mock.close(); + } + const sources = map.sources.flatMap((source, index) => + source.includes("/undici/") ? [[source, map.sourcesContent[index]]] : [] + ); + const installedRoot = dirname(runtimeRequire.resolve("undici/package.json")); + const changedSources = sources.filter(([source, content]) => { + const localPath = source.split("/undici/")[1]; + try { + return readFileSync(join(installedRoot, localPath), "utf8") !== content; + } catch { + return true; + } + }).length; + const report = JSON.stringify( + { + ...inventory, + embeddedMockFetch: + "PASS: executable factories; network disabled; not a relay assertion", + embeddedSourcesSha256: createHash("sha256") + .update(JSON.stringify(sources)) + .digest("hex"), + sourcesDifferentFromResolvedUndici: changedSources, + embeddedExactVersion: + "unknown: no embedded package version metadata; source fingerprint retained", + }, + null, + 2 + ); + await new Promise((done) => process.stdout.write(`${report}\n`, done)); + process.exit(0); +} +const fixtureDirectory = mkdtempSync(join(tmpdir(), "motion-relay-fixture-")); +const port = Number(process.argv[2] ?? 21999); +assert(Number.isInteger(port) && port > 1024 && port < 65536); +let output = ""; +const child = spawn( + process.execPath, + [ + "--require", + resolve(root, "scripts/relay-fixture-guard.cjs"), + binary, + "dev", + "--port", + String(port), + "--no-hotkeys", + "--disable-request-cf-fetch", + "--persist", + join(fixtureDirectory, "state"), + ], + { + cwd: resolve(root, "server"), + env: { + XDG_CONFIG_HOME: fixtureDirectory, + CI: "1", + NO_UPDATE_NOTIFIER: "1", + NODE_OPTIONS: `--require=${resolve(root, "scripts/relay-fixture-guard.cjs")}`, + PATH: "/usr/bin:/bin", + }, + stdio: ["ignore", "pipe", "pipe"], + } +); +child.stdout.on("data", (chunk) => { + output += chunk; +}); +child.stderr.on("data", (chunk) => { + output += chunk; +}); +const sockets = []; +const checks = []; +const deadline = setTimeout(() => child.kill("SIGTERM"), 25000); +function client() { + const socket = new WebSocket(`ws://127.0.0.1:${port}/parties/main/FIX234`); + const messages = []; + socket.addEventListener("message", ({ data }) => + messages.push(JSON.parse(data)) + ); + sockets.push(socket); + return { + socket, + messages, + send: (message) => socket.send(JSON.stringify(message)), + }; +} +async function until(predicate, label) { + for (let i = 0; i < 100; i++) { + if (predicate()) return; + if (child.exitCode !== null || child.signalCode !== null) + throw new Error(`PartyKit exited: ${output}`); + await delay(50); + } + throw new Error(`Timed out: ${label}\n${output}`); +} +async function connect(role) { + const connection = client(); + await until(() => connection.socket.readyState === WebSocket.OPEN, "connect"); + connection.send({ v: 1, type: "join", role }); + return connection; +} +try { + await until( + () => output.includes("http://") && output.includes(String(port)), + "relay ready" + ); + const display = await connect("display"); + const controller = await connect("controller"); + await until( + () => display.messages.some((m) => m.type === "peer" && m.connected), + "presence" + ); + checks.push("real relay handshake and presence"); + controller.send({ v: 1, type: "ping", t: 123 }); + await until( + () => controller.messages.some((m) => m.type === "pong" && m.t === 123), + "pong" + ); + checks.push("ping/pong"); + const pose = { + v: 1, + type: "pose", + seq: 1, + sentAt: 12, + quality: 1, + joints: Object.fromEntries( + [ + "head", + "leftHand", + "rightHand", + "torso", + "leftKnee", + "rightKnee", + "leftFoot", + "rightFoot", + ].map((name) => [name, [0.5, 0.5]]) + ), + }; + controller.send(pose); + await until( + () => display.messages.some((m) => m.type === "pose"), + "pose relay" + ); + assert.deepEqual( + display.messages.find((m) => m.type === "pose"), + pose + ); + display.send({ v: 1, type: "start" }); + await until( + () => controller.messages.some((m) => m.type === "start"), + "start relay" + ); + checks.push("normalized pose and start relay"); + const duplicate = await connect("display"); + await until( + () => duplicate.messages.some((m) => m.code === "room_full"), + "duplicate role" + ); + const replacement = await connect("controller"); + await until( + () => controller.socket.readyState === WebSocket.CLOSED, + "controller eviction" + ); + replacement.socket.send("{bad-json"); + await until( + () => replacement.messages.some((m) => m.code === "bad_message"), + "malformed input" + ); + replacement.socket.close(); + await until( + () => + display.messages.at(-1)?.type === "peer" && + !display.messages.at(-1).connected, + "disconnect presence" + ); + checks.push( + "duplicate display rejection, controller replacement, malformed input, disconnect presence" + ); + await until( + () => output.includes('"path":"/json","bundled":true'), + "bundled inspector fetch" + ); + checks.push( + "PartyKit embedded Undici inspector fetch through actual dev runtime" + ); + console.log( + JSON.stringify( + { + ...inventory, + checks, + }, + null, + 2 + ) + ); +} finally { + clearTimeout(deadline); + for (const socket of sockets) socket.close(); + child.kill("SIGTERM"); + await new Promise((done) => { + if (child.exitCode !== null) done(); + else { + child.once("exit", done); + setTimeout(() => { + child.kill("SIGKILL"); + done(); + }, 2000).unref(); + } + }); +} diff --git a/scripts/qualify-relay.test.mjs b/scripts/qualify-relay.test.mjs new file mode 100644 index 0000000..c8bf817 --- /dev/null +++ b/scripts/qualify-relay.test.mjs @@ -0,0 +1,19 @@ +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; +import { expect, it } from "vitest"; + +it("executes embedded Undici without sockets and emits complete parseable evidence", () => { + const script = fileURLToPath(new URL("./qualify-relay.mjs", import.meta.url)); + const result = spawnSync(process.execPath, [script, "--inspect-bundle"], { + encoding: "utf8", + timeout: 3000, + env: { PATH: "/usr/bin:/bin" }, + }); + expect(result.status, result.stderr).toBe(0); + const report = JSON.parse(result.stdout); + expect(report.embeddedMockFetch).toMatch(/^PASS:/u); + expect(report.binarySha256).toMatch(/^[a-f0-9]{64}$/u); + expect(report.embeddedSourcesSha256).toMatch(/^[a-f0-9]{64}$/u); + expect(report.embeddedUndiciSources).toBeGreaterThan(0); + expect(report.embeddedExactVersion).toMatch(/^unknown:/u); +}); diff --git a/scripts/relay-fixture-guard.cjs b/scripts/relay-fixture-guard.cjs new file mode 100644 index 0000000..6fcd3fb --- /dev/null +++ b/scripts/relay-fixture-guard.cjs @@ -0,0 +1,71 @@ +// Only the isolated local qualification child loads this guard. +"use strict"; +const net = require("node:net"); +const fs = require("node:fs"); +const diagnostics = require("node:diagnostics_channel"); +const { homedir } = require("node:os"); +const { resolve } = require("node:path"); +const { fileURLToPath } = require("node:url"); +const { syncBuiltinESMExports } = require("node:module"); +const personalDirectory = homedir(); +const connect = net.Socket.prototype.connect; +net.Socket.prototype.connect = function (...args) { + const options = net._normalizeArgs(args)[0]; + if ( + options.host && + !["127.0.0.1", "localhost", "::1"].includes(options.host) + ) { + throw new Error(`Fixture blocked external connection: ${options.host}`); + } + return connect.apply(this, args); +}; +function guardPath(path) { + const text = resolve( + path instanceof URL ? fileURLToPath(path) : String(path) + ); + if ( + text === personalDirectory || + text.startsWith(`${personalDirectory}/`) || + /(^|\/)\.env(?:\.|$)|\.partykit\/config\.json|\/\.ssh\/|\/\.aws\//u.test( + text + ) + ) { + throw new Error(`Fixture blocked sensitive read: ${text}`); + } +} +for (const name of [ + "readFileSync", + "readFile", + "openSync", + "open", + "writeFileSync", + "writeFile", + "createReadStream", + "createWriteStream", +]) { + const original = fs[name]; + fs[name] = function (path, ...args) { + guardPath(path); + return original.call(this, path, ...args); + }; +} +for (const name of ["readFile", "open", "writeFile"]) { + const original = fs.promises[name]; + fs.promises[name] = async function (path, ...args) { + guardPath(path); + return await original.call(this, path, ...args); + }; +} +syncBuiltinESMExports(); +diagnostics.channel("undici:request:create").subscribe(({ request }) => { + const origin = String(request.origin); + if (!/^http:\/\/(127\.0\.0\.1|localhost|\[::1\]):\d+$/u.test(origin)) { + throw new Error(`Fixture blocked external Undici request: ${origin}`); + } + const bundled = new Error("Fixture request provenance").stack.includes( + "partykit/dist/bin.mjs" + ); + console.log( + `FIXTURE_UNDICI ${JSON.stringify({ origin, path: request.path, bundled })}` + ); +}); diff --git a/scripts/relay-fixture-guard.test.mjs b/scripts/relay-fixture-guard.test.mjs new file mode 100644 index 0000000..ea819a2 --- /dev/null +++ b/scripts/relay-fixture-guard.test.mjs @@ -0,0 +1,35 @@ +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; +import { expect, it } from "vitest"; + +it("blocks sync, promise and ESM sensitive I/O plus external sockets before I/O", () => { + const guard = fileURLToPath( + new URL("./relay-fixture-guard.cjs", import.meta.url) + ); + const result = spawnSync( + process.execPath, + [ + "--require", + guard, + "--input-type=module", + "-e", + ` + import assert from 'node:assert/strict'; + import { readFileSync } from 'node:fs'; + import { readFile, writeFile } from 'node:fs/promises'; + import { Socket } from 'node:net'; + // These fixture paths need not exist: guards must fire before any I/O. + assert.throws(() => readFileSync('/tmp/.env.synthetic-fixture'), /Fixture blocked/); + await assert.rejects(readFile('/tmp/.env.synthetic-fixture'), /Fixture blocked/); + await assert.rejects(writeFile('/tmp/.env.synthetic-fixture', 'synthetic'), /Fixture blocked/); + const socket = new Socket(); + assert.throws(() => socket.connect({ host: 'external.invalid', port: 80 }), /Fixture blocked external/); + socket.destroy(); + console.log('guards passed'); + `, + ], + { encoding: "utf8", timeout: 3000, env: { PATH: "/usr/bin:/bin" } } + ); + expect(result.status, result.stderr).toBe(0); + expect(result.stdout).toContain("guards passed"); +}); diff --git a/scripts/swift-format-result.mjs b/scripts/swift-format-result.mjs new file mode 100644 index 0000000..280086a --- /dev/null +++ b/scripts/swift-format-result.mjs @@ -0,0 +1,15 @@ +export function countSwiftFormatDiagnostics(result) { + const diagnostics = `${result.stdout ?? ""}\n${result.stderr ?? ""}` + .split("\n") + .filter((line) => /\.swift:\d+:\d+: error:/u.test(line)).length; + if (result.error) throw result.error; + if ( + ![0, 1].includes(result.status) || + (result.status === 1 && diagnostics === 0) + ) { + throw new Error( + `Swift format exited ${result.status} without valid lint diagnostics.` + ); + } + return diagnostics; +} diff --git a/scripts/swift-format-result.test.mjs b/scripts/swift-format-result.test.mjs new file mode 100644 index 0000000..a602358 --- /dev/null +++ b/scripts/swift-format-result.test.mjs @@ -0,0 +1,37 @@ +import { describe, expect, it } from "vitest"; +import { countSwiftFormatDiagnostics } from "./swift-format-result.mjs"; + +describe("Swift format tool result", () => { + it("accepts clean output and counts legacy lint debt", () => { + expect( + countSwiftFormatDiagnostics({ status: 0, stdout: "", stderr: "" }) + ).toBe(0); + expect( + countSwiftFormatDiagnostics({ + status: 1, + stderr: "A.swift:1:1: error: indentation\nB.swift:2:3: error: spacing", + }) + ).toBe(2); + }); + it.each([1, 2, null])( + "rejects unexplained failure %s instead of passing zero debt", + (status) => { + expect(() => + countSwiftFormatDiagnostics({ status, stderr: "tool failed" }) + ).toThrow(/without valid lint diagnostics/u); + } + ); + it("rejects abnormal exit even with diagnostic text", () => { + expect(() => + countSwiftFormatDiagnostics({ status: 2, stderr: "error: could not run" }) + ).toThrow(); + }); + it("does not count tool errors as ratchetable Swift lint debt", () => { + expect(() => + countSwiftFormatDiagnostics({ + status: 1, + stderr: "error: unable to load configuration", + }) + ).toThrow(); + }); +}); From 971c7ae2c4d17be54f285fe3f3ee06e128e088f0 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Sat, 3 Oct 2026 02:35:07 +0530 Subject: [PATCH 5/7] fix: retain bounded relay provenance diagnostics --- scripts/qualify-relay.mjs | 38 +++++++--- scripts/relay-diagnostics.cjs | 111 +++++++++++++++++++++++++++++ scripts/relay-diagnostics.test.mjs | 90 +++++++++++++++++++++++ scripts/relay-fixture-guard.cjs | 24 +++---- 4 files changed, 242 insertions(+), 21 deletions(-) create mode 100644 scripts/relay-diagnostics.cjs create mode 100644 scripts/relay-diagnostics.test.mjs diff --git a/scripts/qualify-relay.mjs b/scripts/qualify-relay.mjs index 0d5950c..6f92117 100644 --- a/scripts/qualify-relay.mjs +++ b/scripts/qualify-relay.mjs @@ -9,6 +9,9 @@ import { dirname, resolve, join } from "node:path"; import { fileURLToPath } from "node:url"; import { setTimeout as delay } from "node:timers/promises"; +const { createCollector } = createRequire(import.meta.url)("./relay-diagnostics.cjs"); + +try { const root = fileURLToPath(new URL("../", import.meta.url)); const binary = realpathSync( resolve(root, "server/node_modules/partykit/dist/bin.mjs") @@ -16,7 +19,8 @@ const binary = realpathSync( const partyRequire = createRequire(new URL(`file://${binary}`)); const runtimeRequire = createRequire(partyRequire.resolve("miniflare")); const { WebSocket } = runtimeRequire("undici"); -const map = JSON.parse(readFileSync(`${binary}.map`, "utf8")); +const mapBytes = readFileSync(`${binary}.map`); +const map = JSON.parse(mapBytes); const manifest = JSON.parse( map.sourcesContent[map.sources.indexOf("../package.json")] ); @@ -24,6 +28,7 @@ const inventory = { node: process.version, partykit: manifest.version, binarySha256: createHash("sha256").update(readFileSync(binary)).digest("hex"), + mapSha256: createHash("sha256").update(mapBytes).digest("hex"), embeddedUndiciDeclaration: manifest.devDependencies.undici, embeddedUndiciSources: map.sources.filter((source) => source.includes("/undici/") @@ -107,7 +112,9 @@ if (process.argv[2] === "--inspect-bundle") { const fixtureDirectory = mkdtempSync(join(tmpdir(), "motion-relay-fixture-")); const port = Number(process.argv[2] ?? 21999); assert(Number.isInteger(port) && port > 1024 && port < 65536); -let output = ""; +// No publisher has been qualified by this diagnostics-only correction. +const evidence = createCollector(port, { ...inventory, publisherQualified: false }); +let phase = "relay ready"; const child = spawn( process.execPath, [ @@ -127,6 +134,7 @@ const child = spawn( env: { XDG_CONFIG_HOME: fixtureDirectory, CI: "1", + RELAY_FIXTURE_PORT: String(port), NO_UPDATE_NOTIFIER: "1", NODE_OPTIONS: `--require=${resolve(root, "scripts/relay-fixture-guard.cjs")}`, PATH: "/usr/bin:/bin", @@ -134,11 +142,13 @@ const child = spawn( stdio: ["ignore", "pipe", "pipe"], } ); +let childFailed = false; +child.on("error", () => { childFailed = true; }); child.stdout.on("data", (chunk) => { - output += chunk; + evidence.push("stdout", chunk); }); child.stderr.on("data", (chunk) => { - output += chunk; + evidence.push("stderr", chunk); }); const sockets = []; const checks = []; @@ -157,13 +167,14 @@ function client() { }; } async function until(predicate, label) { + phase = label; for (let i = 0; i < 100; i++) { if (predicate()) return; - if (child.exitCode !== null || child.signalCode !== null) - throw new Error(`PartyKit exited: ${output}`); + if (childFailed || child.exitCode !== null || child.signalCode !== null) + throw new Error("PartyKit exited"); await delay(50); } - throw new Error(`Timed out: ${label}\n${output}`); + throw new Error("Qualification timed out"); } async function connect(role) { const connection = client(); @@ -173,7 +184,7 @@ async function connect(role) { } try { await until( - () => output.includes("http://") && output.includes(String(port)), + () => evidence.ready(), "relay ready" ); const display = await connect("display"); @@ -249,7 +260,7 @@ try { "duplicate display rejection, controller replacement, malformed input, disconnect presence" ); await until( - () => output.includes('"path":"/json","bundled":true'), + () => evidence.qualified(), "bundled inspector fetch" ); checks.push( @@ -265,6 +276,10 @@ try { 2 ) ); +} catch { + console.log(JSON.stringify({ status: "failed", phase, completedChecks: checks, + observations: evidence.observations(), provenance: "UNKNOWN" })); + process.exitCode = 1; } finally { clearTimeout(deadline); for (const socket of sockets) socket.close(); @@ -280,3 +295,8 @@ try { } }); } +} catch { + console.log(JSON.stringify({ status: "failed", phase: "setup", completedChecks: [], + observations: [], provenance: "UNKNOWN" })); + process.exitCode = 1; +} diff --git a/scripts/relay-diagnostics.cjs b/scripts/relay-diagnostics.cjs new file mode 100644 index 0000000..bb12edf --- /dev/null +++ b/scripts/relay-diagnostics.cjs @@ -0,0 +1,111 @@ +"use strict"; +const { createHash } = require("node:crypto"); +const { basename } = require("node:path"); +const { SourceMap } = require("node:module"); +const { fileURLToPath } = require("node:url"); +const hash = (value) => createHash("sha256").update(value).digest("hex"); +const digest = (value) => typeof value === "string" && /^[a-f0-9]{64}$/u.test(value) ? value : null; +const PREFIX = "FIXTURE_UNDICI "; +const LIMIT = 4096; +function safeObservation(value) { + if (!value || typeof value.source !== "string" || !/^[a-zA-Z0-9_.-]{1,80}$/u.test(value.source) || !digest(value.sourceSha256) || + ![value.line, value.column, value.sourceLine, value.sourceColumn].every((n) => Number.isSafeInteger(n) && n > 0)) return {}; + return { source: value.source, sourceSha256: value.sourceSha256, line: value.line, + column: value.column, sourceLine: value.sourceLine, sourceColumn: value.sourceColumn }; +} + +// Observations only: a mapped frame is never a publisher qualification. +function observe(stack, identity) { + try { + const frames = String(stack).split("\n").slice(1); + let frame; + let owned = false; + let dispatched = false; + for (const line of frames) { + const match = /(?:\(|^at )([^()]+):(\d+):(\d+)\)?$/u.exec(line.trim()); + if (!match) return {}; + if (!dispatched && [__filename, identity.guard].includes(match[1])) { + owned = true; + continue; + } + if (owned && match[1] === "node:diagnostics_channel") { + dispatched = true; + continue; + } + frame = match; + break; + } + if (!frame || !dispatched) return {}; + const executable = frame[1].startsWith("file:") ? fileURLToPath(frame[1]) : frame[1]; + if (executable !== identity.binary) return {}; + const line = Number(frame[2]); + const column = Number(frame[3]); + if (!Number.isSafeInteger(line) || !Number.isSafeInteger(column) || line < 1 || column < 1) return {}; + const entry = new SourceMap(identity.map).findEntry(line - 1, column - 1); + const indexes = identity.map.sources.flatMap((mappedSource, index) => + mappedSource === entry.originalSource ? [index] : []); + if (indexes.length !== 1) return {}; + const content = identity.map.sourcesContent[indexes[0]]; + const source = basename(entry.originalSource); + if (typeof content !== "string" || !/^[a-zA-Z0-9_.-]{1,80}$/u.test(source) || + !Number.isSafeInteger(entry.originalLine) || entry.originalLine < 0 || + !Number.isSafeInteger(entry.originalColumn) || entry.originalColumn < 0) return {}; + return { line, column, source, sourceSha256: hash(content), + sourceLine: entry.originalLine + 1, sourceColumn: entry.originalColumn + 1 }; + } catch { return {}; } +} + +function diagnosticCallback(identity, emit, capture = () => new Error("Fixture request observation").stack) { + return ({ request }) => { + const origin = String(request.origin); + if (!/^http:\/\/(127\.0\.0\.1|localhost|\[::1\]):\d+$/u.test(origin)) + throw new Error("Fixture blocked external Undici request"); + const matched = request.method === "GET" && request.path === "/json" && + ["127.0.0.1", "localhost", "[::1]"].some((host) => origin === `http://${host}:${identity.port}`); + emit(`${PREFIX}${JSON.stringify({ method: matched ? "GET" : null, + origin: matched ? origin : null, path: matched ? "/json" : null, + binarySha256: digest(identity.binarySha256), mapSha256: digest(identity.mapSha256), + bundled: "UNKNOWN", observation: observe(capture(), identity) })}\n`); + }; +} + +function createCollector(port, identity) { + const streams = new Map(); + const records = []; + let ready = false; + function push(stream, chunk) { + let state = streams.get(stream) ?? { tail: "", oversized: false }; + // Each stream is independently newline framed; no cross-stream joins. + for (const part of String(chunk).split(/(?<=\n)/u)) { + const complete = part.endsWith("\n"); + state.tail = (state.tail + part).slice(-LIMIT); + state.oversized ||= state.tail.length === LIMIT; + if (!complete) continue; + if (!state.oversized) { + const line = state.tail.trim(); + ready ||= new RegExp(`(?:^|\\s)http://(?:127\\.0\\.0\\.1|localhost|\\[::1\\]):${port}(?:/)?(?:\\s|$)`, "u").test(line); + if (line.startsWith(PREFIX) && records.length < 16) { + try { + const record = JSON.parse(line.slice(PREFIX.length)); + if (record?.method === "GET" && record.path === "/json" && + ["127.0.0.1", "localhost", "[::1]"].some((host) => record.origin === `http://${host}:${port}`) && + digest(record.binarySha256) && digest(record.mapSha256) && + record.binarySha256 === identity.binarySha256 && record.mapSha256 === identity.mapSha256) { + // Only sanitized matched observations enter failure reports. + records.push({ method: "GET", origin: record.origin, path: "/json", + binarySha256: record.binarySha256, mapSha256: record.mapSha256, + bundled: ["TRUE", "FALSE"].includes(record.bundled) ? record.bundled : "UNKNOWN", + observation: safeObservation(record.observation) }); + } + } catch { /* Malformed records provide no evidence. */ } + } + } + state = { tail: "", oversized: false }; + } + streams.set(stream, state); + } + return { push, ready: () => ready, + qualified: () => identity.publisherQualified === true && records.some((record) => record.bundled === "TRUE"), + observations: () => records.slice() }; +} +module.exports = { hash, diagnosticCallback, createCollector }; diff --git a/scripts/relay-diagnostics.test.mjs b/scripts/relay-diagnostics.test.mjs new file mode 100644 index 0000000..202e4cc --- /dev/null +++ b/scripts/relay-diagnostics.test.mjs @@ -0,0 +1,90 @@ +import { createRequire } from "node:module"; +import { expect, it } from "vitest"; + +const { diagnosticCallback, createCollector, hash } = createRequire(import.meta.url)("./relay-diagnostics.cjs"); +const identity = { port: 21999, binary: "/fixture/bin.mjs", guard: "/fixture/guard.cjs", + binarySha256: hash("executable fixture"), mapSha256: hash("map fixture"), + map: { version: 3, sources: ["request.js"], sourcesContent: ["mock source"], + names: [], mappings: "AAAA" } }; +const request = { method: "GET", origin: "http://127.0.0.1:21999", path: "/json" }; +const prefix = "Error\n at callback (/fixture/guard.cjs:1:1)\n at Channel.publish (node:diagnostics_channel:1:1)\n"; +function record(stack = `${prefix} at implementation (/fixture/bin.mjs:1:1)`) { + let emitted; + diagnosticCallback(identity, (value) => { emitted = value; }, () => stack)({ request }); + return emitted; +} + +it("observes the first implementation via Node SourceMap, always UNKNOWN", () => { + const result = JSON.parse(record("Error\n at callback (/fixture/guard.cjs:1:1)\n at Channel.publish (node:diagnostics_channel:1:1)\n at implementation (/fixture/bin.mjs:1:1)").slice(15)); + expect(result.bundled).toBe("UNKNOWN"); + expect(result.observation).toEqual({ source: "request.js", sourceSha256: hash("mock source"), + line: 1, column: 1, sourceLine: 1, sourceColumn: 1 }); + for (const stack of ["Error", "Error\n at native", `${prefix} at earlier (/other/request.js:1:1)\n at later (/fixture/bin.mjs:1:1)`, "Error\n at implementation (/fixture/bin.mjs:1:1)"]) { + expect(JSON.parse(record(stack).slice(15)).observation).toEqual({}); + } + for (const map of [null, { ...identity.map, sources: ["request.js", "request.js"] }]) { + let output; + diagnosticCallback({ ...identity, map }, (value) => { output = value; }, () => `${prefix} at implementation (/fixture/bin.mjs:1:1)`)({ request }); + expect(JSON.parse(output.slice(15)).observation).toEqual({}); + } +}); + +it("frames readiness at every stdout split and keeps stderr separate", () => { + const url = "Ready http://127.0.0.1:21999/\n"; + for (let split = 0; split <= url.length; split++) { + const collector = createCollector(identity.port, identity); + collector.push("stdout", url.slice(0, split)); + collector.push("stdout", url.slice(split)); + expect(collector.ready()).toBe(true); + } + const collector = createCollector(identity.port, identity); + collector.push("stdout", "http://127.0.0.1:"); + collector.push("stderr", "21999\n"); + collector.push("stderr", "http://127.0.0.1:219990\nhttp://external.invalid:21999\n"); + expect(collector.ready()).toBe(false); + collector.push("stderr", url); + expect(collector.ready()).toBe(true); +}); + +it("frames records across chunks and newlines with bounded, redacted retention", () => { + const value = record(); + for (let split = 0; split <= value.length; split++) { + const collector = createCollector(identity.port, identity); + collector.push("stdout", value.slice(0, split)); + collector.push("stdout", value.slice(split)); + expect(collector.observations()).toHaveLength(1); + expect(collector.qualified()).toBe(false); + } + const collector = createCollector(identity.port, identity); + collector.push("stdout", `${"secret/home/token?body".repeat(300)}${value}`); + expect(collector.observations()).toHaveLength(0); + const poisoned = JSON.parse(value.slice(15)); + poisoned.stack = "/home/person/token"; + poisoned.observation.extra = "secret query/body"; + for (let i = 0; i < 20; i++) collector.push("stdout", `FIXTURE_UNDICI ${JSON.stringify(poisoned)}\n`); + expect(collector.observations()).toHaveLength(16); + expect(JSON.stringify(collector.observations())).not.toMatch(/secret|home|token|extra|stack/u); +}); + +it("rejects unmatched GET, origin, path and identities and fails closed", () => { + const value = JSON.parse(record().slice(15)); + for (const changes of [{ method: "POST" }, { origin: "http://localhost:219990" }, + { origin: "http://external.invalid:21999" }, { path: "/json?token=secret" }, + { binarySha256: hash("other") }, { mapSha256: null }]) { + const collector = createCollector(identity.port, identity); + collector.push("stdout", `FIXTURE_UNDICI ${JSON.stringify({ ...value, ...changes })}\n`); + expect(collector.observations()).toHaveLength(0); + expect(collector.qualified()).toBe(false); + } + for (const bundled of ["UNKNOWN", "FALSE", false, null, {}, "malformed"]) { + // Even a separately affirmative gate cannot promote these observations. + const collector = createCollector(identity.port, { ...identity, publisherQualified: true }); + collector.push("stdout", `FIXTURE_UNDICI ${JSON.stringify({ ...value, bundled })}\nFIXTURE_UNDICI {bad-json}\n`); + expect(collector.qualified()).toBe(false); + } + let output; + const callback = diagnosticCallback(identity, (emitted) => { output = emitted; }); + callback({ request: { ...request, path: "/json?token=secret" } }); + expect(output).not.toContain("secret"); + expect(() => callback({ request: { ...request, origin: "https://external.invalid?token=secret" } })).toThrow("Fixture blocked external Undici request"); +}); diff --git a/scripts/relay-fixture-guard.cjs b/scripts/relay-fixture-guard.cjs index 6fcd3fb..c7e7a23 100644 --- a/scripts/relay-fixture-guard.cjs +++ b/scripts/relay-fixture-guard.cjs @@ -57,15 +57,15 @@ for (const name of ["readFile", "open", "writeFile"]) { }; } syncBuiltinESMExports(); -diagnostics.channel("undici:request:create").subscribe(({ request }) => { - const origin = String(request.origin); - if (!/^http:\/\/(127\.0\.0\.1|localhost|\[::1\]):\d+$/u.test(origin)) { - throw new Error(`Fixture blocked external Undici request: ${origin}`); - } - const bundled = new Error("Fixture request provenance").stack.includes( - "partykit/dist/bin.mjs" - ); - console.log( - `FIXTURE_UNDICI ${JSON.stringify({ origin, path: request.path, bundled })}` - ); -}); +const { hash, diagnosticCallback } = require("./relay-diagnostics.cjs"); +const identity = { guard: __filename, port: Number(process.env.RELAY_FIXTURE_PORT) }; +try { + identity.binary = fs.realpathSync(process.argv[1]); + identity.binarySha256 = hash(fs.readFileSync(identity.binary)); + const bytes = fs.readFileSync(`${identity.binary}.map`); + identity.mapSha256 = hash(bytes); + identity.map = JSON.parse(bytes); +} catch { /* Missing identity or map leaves provenance UNKNOWN. */ } +diagnostics.channel("undici:request:create").subscribe( + diagnosticCallback(identity, (record) => process.stdout.write(record)) +); From dbd9b66162daa35e7403d377cd49f8f7d8ae0142 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Sat, 3 Oct 2026 02:55:49 +0530 Subject: [PATCH 6/7] style: apply maintained relay script formatting --- scripts/qualify-relay.mjs | 572 +++++++++++++++-------------- scripts/relay-diagnostics.cjs | 145 ++++++-- scripts/relay-diagnostics.test.mjs | 127 +++++-- scripts/relay-fixture-guard.cjs | 17 +- 4 files changed, 521 insertions(+), 340 deletions(-) diff --git a/scripts/qualify-relay.mjs b/scripts/qualify-relay.mjs index 6f92117..0dec201 100644 --- a/scripts/qualify-relay.mjs +++ b/scripts/qualify-relay.mjs @@ -9,294 +9,316 @@ import { dirname, resolve, join } from "node:path"; import { fileURLToPath } from "node:url"; import { setTimeout as delay } from "node:timers/promises"; -const { createCollector } = createRequire(import.meta.url)("./relay-diagnostics.cjs"); +const { createCollector } = createRequire(import.meta.url)( + "./relay-diagnostics.cjs" +); try { -const root = fileURLToPath(new URL("../", import.meta.url)); -const binary = realpathSync( - resolve(root, "server/node_modules/partykit/dist/bin.mjs") -); -const partyRequire = createRequire(new URL(`file://${binary}`)); -const runtimeRequire = createRequire(partyRequire.resolve("miniflare")); -const { WebSocket } = runtimeRequire("undici"); -const mapBytes = readFileSync(`${binary}.map`); -const map = JSON.parse(mapBytes); -const manifest = JSON.parse( - map.sourcesContent[map.sources.indexOf("../package.json")] -); -const inventory = { - node: process.version, - partykit: manifest.version, - binarySha256: createHash("sha256").update(readFileSync(binary)).digest("hex"), - mapSha256: createHash("sha256").update(mapBytes).digest("hex"), - embeddedUndiciDeclaration: manifest.devDependencies.undici, - embeddedUndiciSources: map.sources.filter((source) => - source.includes("/undici/") - ).length, - miniflare: runtimeRequire("miniflare/package.json").version, - resolvedUndici: runtimeRequire("undici/package.json").version, - securityRemediation: "unproven: override does not rewrite embedded bytes", -}; -if (process.argv[2] === "--inspect-bundle") { - // Execute the executable's own CommonJS factories, stopping before CLI code. - // No source-map recompilation or substituted external Undici implementation. - const bytes = readFileSync(binary, "utf8"); - const start = bytes.indexOf("var __create = Object.create;"); - const factory = bytes.indexOf("var require_undici = __commonJS({"); - const end = bytes.indexOf("\n// ", factory); - assert(start > 0 && factory > start && end > factory); - const builtins = new Set( - builtinModules.map((name) => name.replace(/^node:/u, "")) - ); - const embedded = new Function( - "require", - "__filename", - "__dirname", - `${bytes.slice(start, end)}\nreturn require_undici();\n//# sourceURL=${binary}` - )( - (name) => { - assert( - builtins.has(name.replace(/^node:/u, "")), - `Unexpected bundled dependency: ${name}` - ); - return partyRequire(name); - }, - binary, - dirname(binary) + const root = fileURLToPath(new URL("../", import.meta.url)); + const binary = realpathSync( + resolve(root, "server/node_modules/partykit/dist/bin.mjs") ); - const mock = new embedded.MockAgent(); - mock.disableNetConnect(); - mock - .get("http://fixture.invalid") - .intercept({ path: "/bundled", method: "GET" }) - .reply(200, "embedded-bytes-ok"); - try { - const response = await embedded.fetch("http://fixture.invalid/bundled", { - dispatcher: mock, - }); - assert.equal(await response.text(), "embedded-bytes-ok"); - mock.assertNoPendingInterceptors(); - } finally { - await mock.close(); - } - const sources = map.sources.flatMap((source, index) => - source.includes("/undici/") ? [[source, map.sourcesContent[index]]] : [] + const partyRequire = createRequire(new URL(`file://${binary}`)); + const runtimeRequire = createRequire(partyRequire.resolve("miniflare")); + const { WebSocket } = runtimeRequire("undici"); + const mapBytes = readFileSync(`${binary}.map`); + const map = JSON.parse(mapBytes); + const manifest = JSON.parse( + map.sourcesContent[map.sources.indexOf("../package.json")] ); - const installedRoot = dirname(runtimeRequire.resolve("undici/package.json")); - const changedSources = sources.filter(([source, content]) => { - const localPath = source.split("/undici/")[1]; + const inventory = { + node: process.version, + partykit: manifest.version, + binarySha256: createHash("sha256") + .update(readFileSync(binary)) + .digest("hex"), + mapSha256: createHash("sha256").update(mapBytes).digest("hex"), + embeddedUndiciDeclaration: manifest.devDependencies.undici, + embeddedUndiciSources: map.sources.filter((source) => + source.includes("/undici/") + ).length, + miniflare: runtimeRequire("miniflare/package.json").version, + resolvedUndici: runtimeRequire("undici/package.json").version, + securityRemediation: "unproven: override does not rewrite embedded bytes", + }; + if (process.argv[2] === "--inspect-bundle") { + // Execute the executable's own CommonJS factories, stopping before CLI code. + // No source-map recompilation or substituted external Undici implementation. + const bytes = readFileSync(binary, "utf8"); + const start = bytes.indexOf("var __create = Object.create;"); + const factory = bytes.indexOf("var require_undici = __commonJS({"); + const end = bytes.indexOf("\n// ", factory); + assert(start > 0 && factory > start && end > factory); + const builtins = new Set( + builtinModules.map((name) => name.replace(/^node:/u, "")) + ); + const embedded = new Function( + "require", + "__filename", + "__dirname", + `${bytes.slice(start, end)}\nreturn require_undici();\n//# sourceURL=${binary}` + )( + (name) => { + assert( + builtins.has(name.replace(/^node:/u, "")), + `Unexpected bundled dependency: ${name}` + ); + return partyRequire(name); + }, + binary, + dirname(binary) + ); + const mock = new embedded.MockAgent(); + mock.disableNetConnect(); + mock + .get("http://fixture.invalid") + .intercept({ path: "/bundled", method: "GET" }) + .reply(200, "embedded-bytes-ok"); try { - return readFileSync(join(installedRoot, localPath), "utf8") !== content; - } catch { - return true; + const response = await embedded.fetch("http://fixture.invalid/bundled", { + dispatcher: mock, + }); + assert.equal(await response.text(), "embedded-bytes-ok"); + mock.assertNoPendingInterceptors(); + } finally { + await mock.close(); } - }).length; - const report = JSON.stringify( - { - ...inventory, - embeddedMockFetch: - "PASS: executable factories; network disabled; not a relay assertion", - embeddedSourcesSha256: createHash("sha256") - .update(JSON.stringify(sources)) - .digest("hex"), - sourcesDifferentFromResolvedUndici: changedSources, - embeddedExactVersion: - "unknown: no embedded package version metadata; source fingerprint retained", - }, - null, - 2 - ); - await new Promise((done) => process.stdout.write(`${report}\n`, done)); - process.exit(0); -} -const fixtureDirectory = mkdtempSync(join(tmpdir(), "motion-relay-fixture-")); -const port = Number(process.argv[2] ?? 21999); -assert(Number.isInteger(port) && port > 1024 && port < 65536); -// No publisher has been qualified by this diagnostics-only correction. -const evidence = createCollector(port, { ...inventory, publisherQualified: false }); -let phase = "relay ready"; -const child = spawn( - process.execPath, - [ - "--require", - resolve(root, "scripts/relay-fixture-guard.cjs"), - binary, - "dev", - "--port", - String(port), - "--no-hotkeys", - "--disable-request-cf-fetch", - "--persist", - join(fixtureDirectory, "state"), - ], - { - cwd: resolve(root, "server"), - env: { - XDG_CONFIG_HOME: fixtureDirectory, - CI: "1", - RELAY_FIXTURE_PORT: String(port), - NO_UPDATE_NOTIFIER: "1", - NODE_OPTIONS: `--require=${resolve(root, "scripts/relay-fixture-guard.cjs")}`, - PATH: "/usr/bin:/bin", - }, - stdio: ["ignore", "pipe", "pipe"], - } -); -let childFailed = false; -child.on("error", () => { childFailed = true; }); -child.stdout.on("data", (chunk) => { - evidence.push("stdout", chunk); -}); -child.stderr.on("data", (chunk) => { - evidence.push("stderr", chunk); -}); -const sockets = []; -const checks = []; -const deadline = setTimeout(() => child.kill("SIGTERM"), 25000); -function client() { - const socket = new WebSocket(`ws://127.0.0.1:${port}/parties/main/FIX234`); - const messages = []; - socket.addEventListener("message", ({ data }) => - messages.push(JSON.parse(data)) - ); - sockets.push(socket); - return { - socket, - messages, - send: (message) => socket.send(JSON.stringify(message)), - }; -} -async function until(predicate, label) { - phase = label; - for (let i = 0; i < 100; i++) { - if (predicate()) return; - if (childFailed || child.exitCode !== null || child.signalCode !== null) - throw new Error("PartyKit exited"); - await delay(50); - } - throw new Error("Qualification timed out"); -} -async function connect(role) { - const connection = client(); - await until(() => connection.socket.readyState === WebSocket.OPEN, "connect"); - connection.send({ v: 1, type: "join", role }); - return connection; -} -try { - await until( - () => evidence.ready(), - "relay ready" - ); - const display = await connect("display"); - const controller = await connect("controller"); - await until( - () => display.messages.some((m) => m.type === "peer" && m.connected), - "presence" - ); - checks.push("real relay handshake and presence"); - controller.send({ v: 1, type: "ping", t: 123 }); - await until( - () => controller.messages.some((m) => m.type === "pong" && m.t === 123), - "pong" - ); - checks.push("ping/pong"); - const pose = { - v: 1, - type: "pose", - seq: 1, - sentAt: 12, - quality: 1, - joints: Object.fromEntries( - [ - "head", - "leftHand", - "rightHand", - "torso", - "leftKnee", - "rightKnee", - "leftFoot", - "rightFoot", - ].map((name) => [name, [0.5, 0.5]]) - ), - }; - controller.send(pose); - await until( - () => display.messages.some((m) => m.type === "pose"), - "pose relay" - ); - assert.deepEqual( - display.messages.find((m) => m.type === "pose"), - pose - ); - display.send({ v: 1, type: "start" }); - await until( - () => controller.messages.some((m) => m.type === "start"), - "start relay" - ); - checks.push("normalized pose and start relay"); - const duplicate = await connect("display"); - await until( - () => duplicate.messages.some((m) => m.code === "room_full"), - "duplicate role" - ); - const replacement = await connect("controller"); - await until( - () => controller.socket.readyState === WebSocket.CLOSED, - "controller eviction" - ); - replacement.socket.send("{bad-json"); - await until( - () => replacement.messages.some((m) => m.code === "bad_message"), - "malformed input" - ); - replacement.socket.close(); - await until( - () => - display.messages.at(-1)?.type === "peer" && - !display.messages.at(-1).connected, - "disconnect presence" - ); - checks.push( - "duplicate display rejection, controller replacement, malformed input, disconnect presence" - ); - await until( - () => evidence.qualified(), - "bundled inspector fetch" - ); - checks.push( - "PartyKit embedded Undici inspector fetch through actual dev runtime" - ); - console.log( - JSON.stringify( + const sources = map.sources.flatMap((source, index) => + source.includes("/undici/") ? [[source, map.sourcesContent[index]]] : [] + ); + const installedRoot = dirname( + runtimeRequire.resolve("undici/package.json") + ); + const changedSources = sources.filter(([source, content]) => { + const localPath = source.split("/undici/")[1]; + try { + return readFileSync(join(installedRoot, localPath), "utf8") !== content; + } catch { + return true; + } + }).length; + const report = JSON.stringify( { ...inventory, - checks, + embeddedMockFetch: + "PASS: executable factories; network disabled; not a relay assertion", + embeddedSourcesSha256: createHash("sha256") + .update(JSON.stringify(sources)) + .digest("hex"), + sourcesDifferentFromResolvedUndici: changedSources, + embeddedExactVersion: + "unknown: no embedded package version metadata; source fingerprint retained", }, null, 2 - ) - ); -} catch { - console.log(JSON.stringify({ status: "failed", phase, completedChecks: checks, - observations: evidence.observations(), provenance: "UNKNOWN" })); - process.exitCode = 1; -} finally { - clearTimeout(deadline); - for (const socket of sockets) socket.close(); - child.kill("SIGTERM"); - await new Promise((done) => { - if (child.exitCode !== null) done(); - else { - child.once("exit", done); - setTimeout(() => { - child.kill("SIGKILL"); - done(); - }, 2000).unref(); + ); + await new Promise((done) => process.stdout.write(`${report}\n`, done)); + process.exit(0); + } + const fixtureDirectory = mkdtempSync(join(tmpdir(), "motion-relay-fixture-")); + const port = Number(process.argv[2] ?? 21999); + assert(Number.isInteger(port) && port > 1024 && port < 65536); + // No publisher has been qualified by this diagnostics-only correction. + const evidence = createCollector(port, { + ...inventory, + publisherQualified: false, + }); + let phase = "relay ready"; + const child = spawn( + process.execPath, + [ + "--require", + resolve(root, "scripts/relay-fixture-guard.cjs"), + binary, + "dev", + "--port", + String(port), + "--no-hotkeys", + "--disable-request-cf-fetch", + "--persist", + join(fixtureDirectory, "state"), + ], + { + cwd: resolve(root, "server"), + env: { + XDG_CONFIG_HOME: fixtureDirectory, + CI: "1", + RELAY_FIXTURE_PORT: String(port), + NO_UPDATE_NOTIFIER: "1", + NODE_OPTIONS: `--require=${resolve(root, "scripts/relay-fixture-guard.cjs")}`, + PATH: "/usr/bin:/bin", + }, + stdio: ["ignore", "pipe", "pipe"], } + ); + let childFailed = false; + child.on("error", () => { + childFailed = true; }); -} + child.stdout.on("data", (chunk) => { + evidence.push("stdout", chunk); + }); + child.stderr.on("data", (chunk) => { + evidence.push("stderr", chunk); + }); + const sockets = []; + const checks = []; + const deadline = setTimeout(() => child.kill("SIGTERM"), 25000); + function client() { + const socket = new WebSocket(`ws://127.0.0.1:${port}/parties/main/FIX234`); + const messages = []; + socket.addEventListener("message", ({ data }) => + messages.push(JSON.parse(data)) + ); + sockets.push(socket); + return { + socket, + messages, + send: (message) => socket.send(JSON.stringify(message)), + }; + } + async function until(predicate, label) { + phase = label; + for (let i = 0; i < 100; i++) { + if (predicate()) return; + if (childFailed || child.exitCode !== null || child.signalCode !== null) + throw new Error("PartyKit exited"); + await delay(50); + } + throw new Error("Qualification timed out"); + } + async function connect(role) { + const connection = client(); + await until( + () => connection.socket.readyState === WebSocket.OPEN, + "connect" + ); + connection.send({ v: 1, type: "join", role }); + return connection; + } + try { + await until(() => evidence.ready(), "relay ready"); + const display = await connect("display"); + const controller = await connect("controller"); + await until( + () => display.messages.some((m) => m.type === "peer" && m.connected), + "presence" + ); + checks.push("real relay handshake and presence"); + controller.send({ v: 1, type: "ping", t: 123 }); + await until( + () => controller.messages.some((m) => m.type === "pong" && m.t === 123), + "pong" + ); + checks.push("ping/pong"); + const pose = { + v: 1, + type: "pose", + seq: 1, + sentAt: 12, + quality: 1, + joints: Object.fromEntries( + [ + "head", + "leftHand", + "rightHand", + "torso", + "leftKnee", + "rightKnee", + "leftFoot", + "rightFoot", + ].map((name) => [name, [0.5, 0.5]]) + ), + }; + controller.send(pose); + await until( + () => display.messages.some((m) => m.type === "pose"), + "pose relay" + ); + assert.deepEqual( + display.messages.find((m) => m.type === "pose"), + pose + ); + display.send({ v: 1, type: "start" }); + await until( + () => controller.messages.some((m) => m.type === "start"), + "start relay" + ); + checks.push("normalized pose and start relay"); + const duplicate = await connect("display"); + await until( + () => duplicate.messages.some((m) => m.code === "room_full"), + "duplicate role" + ); + const replacement = await connect("controller"); + await until( + () => controller.socket.readyState === WebSocket.CLOSED, + "controller eviction" + ); + replacement.socket.send("{bad-json"); + await until( + () => replacement.messages.some((m) => m.code === "bad_message"), + "malformed input" + ); + replacement.socket.close(); + await until( + () => + display.messages.at(-1)?.type === "peer" && + !display.messages.at(-1).connected, + "disconnect presence" + ); + checks.push( + "duplicate display rejection, controller replacement, malformed input, disconnect presence" + ); + await until(() => evidence.qualified(), "bundled inspector fetch"); + checks.push( + "PartyKit embedded Undici inspector fetch through actual dev runtime" + ); + console.log( + JSON.stringify( + { + ...inventory, + checks, + }, + null, + 2 + ) + ); + } catch { + console.log( + JSON.stringify({ + status: "failed", + phase, + completedChecks: checks, + observations: evidence.observations(), + provenance: "UNKNOWN", + }) + ); + process.exitCode = 1; + } finally { + clearTimeout(deadline); + for (const socket of sockets) socket.close(); + child.kill("SIGTERM"); + await new Promise((done) => { + if (child.exitCode !== null) done(); + else { + child.once("exit", done); + setTimeout(() => { + child.kill("SIGKILL"); + done(); + }, 2000).unref(); + } + }); + } } catch { - console.log(JSON.stringify({ status: "failed", phase: "setup", completedChecks: [], - observations: [], provenance: "UNKNOWN" })); + console.log( + JSON.stringify({ + status: "failed", + phase: "setup", + completedChecks: [], + observations: [], + provenance: "UNKNOWN", + }) + ); process.exitCode = 1; } diff --git a/scripts/relay-diagnostics.cjs b/scripts/relay-diagnostics.cjs index bb12edf..bc0de4b 100644 --- a/scripts/relay-diagnostics.cjs +++ b/scripts/relay-diagnostics.cjs @@ -4,14 +4,29 @@ const { basename } = require("node:path"); const { SourceMap } = require("node:module"); const { fileURLToPath } = require("node:url"); const hash = (value) => createHash("sha256").update(value).digest("hex"); -const digest = (value) => typeof value === "string" && /^[a-f0-9]{64}$/u.test(value) ? value : null; +const digest = (value) => + typeof value === "string" && /^[a-f0-9]{64}$/u.test(value) ? value : null; const PREFIX = "FIXTURE_UNDICI "; const LIMIT = 4096; function safeObservation(value) { - if (!value || typeof value.source !== "string" || !/^[a-zA-Z0-9_.-]{1,80}$/u.test(value.source) || !digest(value.sourceSha256) || - ![value.line, value.column, value.sourceLine, value.sourceColumn].every((n) => Number.isSafeInteger(n) && n > 0)) return {}; - return { source: value.source, sourceSha256: value.sourceSha256, line: value.line, - column: value.column, sourceLine: value.sourceLine, sourceColumn: value.sourceColumn }; + if ( + !value || + typeof value.source !== "string" || + !/^[a-zA-Z0-9_.-]{1,80}$/u.test(value.source) || + !digest(value.sourceSha256) || + ![value.line, value.column, value.sourceLine, value.sourceColumn].every( + (n) => Number.isSafeInteger(n) && n > 0 + ) + ) + return {}; + return { + source: value.source, + sourceSha256: value.sourceSha256, + line: value.line, + column: value.column, + sourceLine: value.sourceLine, + sourceColumn: value.sourceColumn, + }; } // Observations only: a mapped frame is never a publisher qualification. @@ -36,36 +51,74 @@ function observe(stack, identity) { break; } if (!frame || !dispatched) return {}; - const executable = frame[1].startsWith("file:") ? fileURLToPath(frame[1]) : frame[1]; + const executable = frame[1].startsWith("file:") + ? fileURLToPath(frame[1]) + : frame[1]; if (executable !== identity.binary) return {}; const line = Number(frame[2]); const column = Number(frame[3]); - if (!Number.isSafeInteger(line) || !Number.isSafeInteger(column) || line < 1 || column < 1) return {}; + if ( + !Number.isSafeInteger(line) || + !Number.isSafeInteger(column) || + line < 1 || + column < 1 + ) + return {}; const entry = new SourceMap(identity.map).findEntry(line - 1, column - 1); const indexes = identity.map.sources.flatMap((mappedSource, index) => - mappedSource === entry.originalSource ? [index] : []); + mappedSource === entry.originalSource ? [index] : [] + ); if (indexes.length !== 1) return {}; const content = identity.map.sourcesContent[indexes[0]]; const source = basename(entry.originalSource); - if (typeof content !== "string" || !/^[a-zA-Z0-9_.-]{1,80}$/u.test(source) || - !Number.isSafeInteger(entry.originalLine) || entry.originalLine < 0 || - !Number.isSafeInteger(entry.originalColumn) || entry.originalColumn < 0) return {}; - return { line, column, source, sourceSha256: hash(content), - sourceLine: entry.originalLine + 1, sourceColumn: entry.originalColumn + 1 }; - } catch { return {}; } + if ( + typeof content !== "string" || + !/^[a-zA-Z0-9_.-]{1,80}$/u.test(source) || + !Number.isSafeInteger(entry.originalLine) || + entry.originalLine < 0 || + !Number.isSafeInteger(entry.originalColumn) || + entry.originalColumn < 0 + ) + return {}; + return { + line, + column, + source, + sourceSha256: hash(content), + sourceLine: entry.originalLine + 1, + sourceColumn: entry.originalColumn + 1, + }; + } catch { + return {}; + } } -function diagnosticCallback(identity, emit, capture = () => new Error("Fixture request observation").stack) { +function diagnosticCallback( + identity, + emit, + capture = () => new Error("Fixture request observation").stack +) { return ({ request }) => { const origin = String(request.origin); if (!/^http:\/\/(127\.0\.0\.1|localhost|\[::1\]):\d+$/u.test(origin)) throw new Error("Fixture blocked external Undici request"); - const matched = request.method === "GET" && request.path === "/json" && - ["127.0.0.1", "localhost", "[::1]"].some((host) => origin === `http://${host}:${identity.port}`); - emit(`${PREFIX}${JSON.stringify({ method: matched ? "GET" : null, - origin: matched ? origin : null, path: matched ? "/json" : null, - binarySha256: digest(identity.binarySha256), mapSha256: digest(identity.mapSha256), - bundled: "UNKNOWN", observation: observe(capture(), identity) })}\n`); + const matched = + request.method === "GET" && + request.path === "/json" && + ["127.0.0.1", "localhost", "[::1]"].some( + (host) => origin === `http://${host}:${identity.port}` + ); + emit( + `${PREFIX}${JSON.stringify({ + method: matched ? "GET" : null, + origin: matched ? origin : null, + path: matched ? "/json" : null, + binarySha256: digest(identity.binarySha256), + mapSha256: digest(identity.mapSha256), + bundled: "UNKNOWN", + observation: observe(capture(), identity), + })}\n` + ); }; } @@ -83,29 +136,53 @@ function createCollector(port, identity) { if (!complete) continue; if (!state.oversized) { const line = state.tail.trim(); - ready ||= new RegExp(`(?:^|\\s)http://(?:127\\.0\\.0\\.1|localhost|\\[::1\\]):${port}(?:/)?(?:\\s|$)`, "u").test(line); + ready ||= new RegExp( + `(?:^|\\s)http://(?:127\\.0\\.0\\.1|localhost|\\[::1\\]):${port}(?:/)?(?:\\s|$)`, + "u" + ).test(line); if (line.startsWith(PREFIX) && records.length < 16) { try { const record = JSON.parse(line.slice(PREFIX.length)); - if (record?.method === "GET" && record.path === "/json" && - ["127.0.0.1", "localhost", "[::1]"].some((host) => record.origin === `http://${host}:${port}`) && - digest(record.binarySha256) && digest(record.mapSha256) && - record.binarySha256 === identity.binarySha256 && record.mapSha256 === identity.mapSha256) { + if ( + record?.method === "GET" && + record.path === "/json" && + ["127.0.0.1", "localhost", "[::1]"].some( + (host) => record.origin === `http://${host}:${port}` + ) && + digest(record.binarySha256) && + digest(record.mapSha256) && + record.binarySha256 === identity.binarySha256 && + record.mapSha256 === identity.mapSha256 + ) { // Only sanitized matched observations enter failure reports. - records.push({ method: "GET", origin: record.origin, path: "/json", - binarySha256: record.binarySha256, mapSha256: record.mapSha256, - bundled: ["TRUE", "FALSE"].includes(record.bundled) ? record.bundled : "UNKNOWN", - observation: safeObservation(record.observation) }); + records.push({ + method: "GET", + origin: record.origin, + path: "/json", + binarySha256: record.binarySha256, + mapSha256: record.mapSha256, + bundled: ["TRUE", "FALSE"].includes(record.bundled) + ? record.bundled + : "UNKNOWN", + observation: safeObservation(record.observation), + }); } - } catch { /* Malformed records provide no evidence. */ } + } catch { + /* Malformed records provide no evidence. */ + } } } state = { tail: "", oversized: false }; } streams.set(stream, state); } - return { push, ready: () => ready, - qualified: () => identity.publisherQualified === true && records.some((record) => record.bundled === "TRUE"), - observations: () => records.slice() }; + return { + push, + ready: () => ready, + qualified: () => + identity.publisherQualified === true && + records.some((record) => record.bundled === "TRUE"), + observations: () => records.slice(), + }; } module.exports = { hash, diagnosticCallback, createCollector }; diff --git a/scripts/relay-diagnostics.test.mjs b/scripts/relay-diagnostics.test.mjs index 202e4cc..06d6681 100644 --- a/scripts/relay-diagnostics.test.mjs +++ b/scripts/relay-diagnostics.test.mjs @@ -1,30 +1,79 @@ import { createRequire } from "node:module"; import { expect, it } from "vitest"; -const { diagnosticCallback, createCollector, hash } = createRequire(import.meta.url)("./relay-diagnostics.cjs"); -const identity = { port: 21999, binary: "/fixture/bin.mjs", guard: "/fixture/guard.cjs", - binarySha256: hash("executable fixture"), mapSha256: hash("map fixture"), - map: { version: 3, sources: ["request.js"], sourcesContent: ["mock source"], - names: [], mappings: "AAAA" } }; -const request = { method: "GET", origin: "http://127.0.0.1:21999", path: "/json" }; -const prefix = "Error\n at callback (/fixture/guard.cjs:1:1)\n at Channel.publish (node:diagnostics_channel:1:1)\n"; -function record(stack = `${prefix} at implementation (/fixture/bin.mjs:1:1)`) { +const { diagnosticCallback, createCollector, hash } = createRequire( + import.meta.url +)("./relay-diagnostics.cjs"); +const identity = { + port: 21999, + binary: "/fixture/bin.mjs", + guard: "/fixture/guard.cjs", + binarySha256: hash("executable fixture"), + mapSha256: hash("map fixture"), + map: { + version: 3, + sources: ["request.js"], + sourcesContent: ["mock source"], + names: [], + mappings: "AAAA", + }, +}; +const request = { + method: "GET", + origin: "http://127.0.0.1:21999", + path: "/json", +}; +const prefix = + "Error\n at callback (/fixture/guard.cjs:1:1)\n at Channel.publish (node:diagnostics_channel:1:1)\n"; +function record( + stack = `${prefix} at implementation (/fixture/bin.mjs:1:1)` +) { let emitted; - diagnosticCallback(identity, (value) => { emitted = value; }, () => stack)({ request }); + diagnosticCallback( + identity, + (value) => { + emitted = value; + }, + () => stack + )({ request }); return emitted; } it("observes the first implementation via Node SourceMap, always UNKNOWN", () => { - const result = JSON.parse(record("Error\n at callback (/fixture/guard.cjs:1:1)\n at Channel.publish (node:diagnostics_channel:1:1)\n at implementation (/fixture/bin.mjs:1:1)").slice(15)); + const result = JSON.parse( + record( + "Error\n at callback (/fixture/guard.cjs:1:1)\n at Channel.publish (node:diagnostics_channel:1:1)\n at implementation (/fixture/bin.mjs:1:1)" + ).slice(15) + ); expect(result.bundled).toBe("UNKNOWN"); - expect(result.observation).toEqual({ source: "request.js", sourceSha256: hash("mock source"), - line: 1, column: 1, sourceLine: 1, sourceColumn: 1 }); - for (const stack of ["Error", "Error\n at native", `${prefix} at earlier (/other/request.js:1:1)\n at later (/fixture/bin.mjs:1:1)`, "Error\n at implementation (/fixture/bin.mjs:1:1)"]) { + expect(result.observation).toEqual({ + source: "request.js", + sourceSha256: hash("mock source"), + line: 1, + column: 1, + sourceLine: 1, + sourceColumn: 1, + }); + for (const stack of [ + "Error", + "Error\n at native", + `${prefix} at earlier (/other/request.js:1:1)\n at later (/fixture/bin.mjs:1:1)`, + "Error\n at implementation (/fixture/bin.mjs:1:1)", + ]) { expect(JSON.parse(record(stack).slice(15)).observation).toEqual({}); } - for (const map of [null, { ...identity.map, sources: ["request.js", "request.js"] }]) { + for (const map of [ + null, + { ...identity.map, sources: ["request.js", "request.js"] }, + ]) { let output; - diagnosticCallback({ ...identity, map }, (value) => { output = value; }, () => `${prefix} at implementation (/fixture/bin.mjs:1:1)`)({ request }); + diagnosticCallback( + { ...identity, map }, + (value) => { + output = value; + }, + () => `${prefix} at implementation (/fixture/bin.mjs:1:1)` + )({ request }); expect(JSON.parse(output.slice(15)).observation).toEqual({}); } }); @@ -40,7 +89,10 @@ it("frames readiness at every stdout split and keeps stderr separate", () => { const collector = createCollector(identity.port, identity); collector.push("stdout", "http://127.0.0.1:"); collector.push("stderr", "21999\n"); - collector.push("stderr", "http://127.0.0.1:219990\nhttp://external.invalid:21999\n"); + collector.push( + "stderr", + "http://127.0.0.1:219990\nhttp://external.invalid:21999\n" + ); expect(collector.ready()).toBe(false); collector.push("stderr", url); expect(collector.ready()).toBe(true); @@ -61,30 +113,53 @@ it("frames records across chunks and newlines with bounded, redacted retention", const poisoned = JSON.parse(value.slice(15)); poisoned.stack = "/home/person/token"; poisoned.observation.extra = "secret query/body"; - for (let i = 0; i < 20; i++) collector.push("stdout", `FIXTURE_UNDICI ${JSON.stringify(poisoned)}\n`); + for (let i = 0; i < 20; i++) + collector.push("stdout", `FIXTURE_UNDICI ${JSON.stringify(poisoned)}\n`); expect(collector.observations()).toHaveLength(16); - expect(JSON.stringify(collector.observations())).not.toMatch(/secret|home|token|extra|stack/u); + expect(JSON.stringify(collector.observations())).not.toMatch( + /secret|home|token|extra|stack/u + ); }); it("rejects unmatched GET, origin, path and identities and fails closed", () => { const value = JSON.parse(record().slice(15)); - for (const changes of [{ method: "POST" }, { origin: "http://localhost:219990" }, - { origin: "http://external.invalid:21999" }, { path: "/json?token=secret" }, - { binarySha256: hash("other") }, { mapSha256: null }]) { + for (const changes of [ + { method: "POST" }, + { origin: "http://localhost:219990" }, + { origin: "http://external.invalid:21999" }, + { path: "/json?token=secret" }, + { binarySha256: hash("other") }, + { mapSha256: null }, + ]) { const collector = createCollector(identity.port, identity); - collector.push("stdout", `FIXTURE_UNDICI ${JSON.stringify({ ...value, ...changes })}\n`); + collector.push( + "stdout", + `FIXTURE_UNDICI ${JSON.stringify({ ...value, ...changes })}\n` + ); expect(collector.observations()).toHaveLength(0); expect(collector.qualified()).toBe(false); } for (const bundled of ["UNKNOWN", "FALSE", false, null, {}, "malformed"]) { // Even a separately affirmative gate cannot promote these observations. - const collector = createCollector(identity.port, { ...identity, publisherQualified: true }); - collector.push("stdout", `FIXTURE_UNDICI ${JSON.stringify({ ...value, bundled })}\nFIXTURE_UNDICI {bad-json}\n`); + const collector = createCollector(identity.port, { + ...identity, + publisherQualified: true, + }); + collector.push( + "stdout", + `FIXTURE_UNDICI ${JSON.stringify({ ...value, bundled })}\nFIXTURE_UNDICI {bad-json}\n` + ); expect(collector.qualified()).toBe(false); } let output; - const callback = diagnosticCallback(identity, (emitted) => { output = emitted; }); + const callback = diagnosticCallback(identity, (emitted) => { + output = emitted; + }); callback({ request: { ...request, path: "/json?token=secret" } }); expect(output).not.toContain("secret"); - expect(() => callback({ request: { ...request, origin: "https://external.invalid?token=secret" } })).toThrow("Fixture blocked external Undici request"); + expect(() => + callback({ + request: { ...request, origin: "https://external.invalid?token=secret" }, + }) + ).toThrow("Fixture blocked external Undici request"); }); diff --git a/scripts/relay-fixture-guard.cjs b/scripts/relay-fixture-guard.cjs index c7e7a23..83c8050 100644 --- a/scripts/relay-fixture-guard.cjs +++ b/scripts/relay-fixture-guard.cjs @@ -58,14 +58,21 @@ for (const name of ["readFile", "open", "writeFile"]) { } syncBuiltinESMExports(); const { hash, diagnosticCallback } = require("./relay-diagnostics.cjs"); -const identity = { guard: __filename, port: Number(process.env.RELAY_FIXTURE_PORT) }; +const identity = { + guard: __filename, + port: Number(process.env.RELAY_FIXTURE_PORT), +}; try { identity.binary = fs.realpathSync(process.argv[1]); identity.binarySha256 = hash(fs.readFileSync(identity.binary)); const bytes = fs.readFileSync(`${identity.binary}.map`); identity.mapSha256 = hash(bytes); identity.map = JSON.parse(bytes); -} catch { /* Missing identity or map leaves provenance UNKNOWN. */ } -diagnostics.channel("undici:request:create").subscribe( - diagnosticCallback(identity, (record) => process.stdout.write(record)) -); +} catch { + /* Missing identity or map leaves provenance UNKNOWN. */ +} +diagnostics + .channel("undici:request:create") + .subscribe( + diagnosticCallback(identity, (record) => process.stdout.write(record)) + ); From b8c3e9ac2c459ad9d0c947db4e58b303d4ff8f95 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Sat, 3 Oct 2026 03:03:47 +0530 Subject: [PATCH 7/7] fix: load owned relay diagnostics before fixture I/O guards --- scripts/relay-fixture-guard.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/relay-fixture-guard.cjs b/scripts/relay-fixture-guard.cjs index 83c8050..95a3e79 100644 --- a/scripts/relay-fixture-guard.cjs +++ b/scripts/relay-fixture-guard.cjs @@ -7,6 +7,7 @@ const { homedir } = require("node:os"); const { resolve } = require("node:path"); const { fileURLToPath } = require("node:url"); const { syncBuiltinESMExports } = require("node:module"); +const { hash, diagnosticCallback } = require("./relay-diagnostics.cjs"); const personalDirectory = homedir(); const connect = net.Socket.prototype.connect; net.Socket.prototype.connect = function (...args) { @@ -57,7 +58,6 @@ for (const name of ["readFile", "open", "writeFile"]) { }; } syncBuiltinESMExports(); -const { hash, diagnosticCallback } = require("./relay-diagnostics.cjs"); const identity = { guard: __filename, port: Number(process.env.RELAY_FIXTURE_PORT),