import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { createRequire } from "node:module"; import { fileURLToPath } from "node:url"; import ts from "../../web/node_modules/typescript/lib/typescript.js"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const reportPath = path.join(root, "tests/golden/M13-02F/signature-negative-report.json"); const manifestPath = path.join(root, "tests/golden/M13-02F/manifest.json"); const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "m13-02f-signature-")); const hashFile = (file) => crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex"); const publicKey = "03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8"; const signature = "fc396c6c68e6f6eb38a18c147becfaec1621a167f6db0a0d76874209accf3cb80dfa1fac1528ebc1bc6b090801a3ad397cae18e6ddb41740766678711c0a8804"; const script = (id = "clean", overrides = {}) => ({ id, name: id, entryPath: `scripts/${id}.py`, sourceByteLength: 128, sourceSha256: "a".repeat(64), publisher: "Team", signature, keyId: "key:new", permissions: ["READ_MAIN"], dependencies: [], module: false, cpuMs: 1000, memoryBytes: 1024 * 1024, wallMs: 5000, network: false, autorun: false, driverExpressions: false, addonInstall: false, ...overrides }); const manifest = (scripts = [script()]) => ({ schemaVersion: 1, scripts }); const key = (overrides = {}) => ({ keyId: "key:new", publisher: "Team", algorithm: "ED25519", publicKey, status: "ACTIVE", notBefore: "2026-01-01T00:00:00.000Z", notAfter: "2027-01-01T00:00:00.000Z", ...overrides }); const policy = (overrides = {}) => ({ schemaVersion: 1, issuer: "web-trust", issuedAt: "2026-01-01T00:00:00.000Z", expiresAt: "2027-01-01T00:00:00.000Z", maxClockSkewMs: 300000, keys: [key()], ...overrides }); for (const name of ["asset-path", "capability-gates", "scripting-platform"]) { const source = fs.readFileSync(path.join(root, `web/protocol/${name}.ts`), "utf8"); const output = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 }, fileName: `${name}.ts` }).outputText .replace('require("./asset-path")', 'require("./asset-path.cjs")') .replace('require("./capability-gates")', 'require("./capability-gates.cjs")'); fs.writeFileSync(path.join(temporary, `${name}.cjs`), output); } const protocol = createRequire(import.meta.url)(path.join(temporary, "scripting-platform.cjs")); try { const at = "2026-08-18T12:00:00.000Z"; const decisions = { missing: await protocol.verifyScriptManifestSignature(manifest(), "clean", policy({ keys: [] }), at), expired: await protocol.verifyScriptManifestSignature(manifest(), "clean", policy({ keys: [key({ notAfter: "2026-06-01T00:00:00.000Z" })] }), at), notYetValid: await protocol.verifyScriptManifestSignature(manifest(), "clean", policy({ keys: [key({ notBefore: "2026-09-01T00:00:00.000Z" })] }), at), publisherMismatch: await protocol.verifyScriptManifestSignature(manifest(), "clean", policy({ keys: [key({ publisher: "Other" })] }), at), swapped: await protocol.verifyScriptManifestSignature(manifest([script("other")]), "other", policy(), at), }; for (const name of ["missing", "expired", "notYetValid", "publisherMismatch"]) assert.equal(decisions[name].code, "SCRIPT_POLICY_DENIED"); assert.equal(decisions.swapped.code, "SCRIPT_SIGNATURE_INVALID"); const report = { schemaVersion: 1, task: "M13-02F", operation: "SCRIPT_SIGNATURE_NEGATIVE_CASES", decisions: Object.fromEntries(Object.entries(decisions).map(([name, result]) => [name, result.code])), invariants: { missingKeyDenied: true, expiredKeyDenied: true, notYetValidKeyDenied: true, publisherConfusionDenied: true, swappedSignatureDenied: true, noExecution: true }, nextTask: "M13-03A" }; if (process.env.UPDATE_M13_02F_REPORT === "1") { fs.mkdirSync(path.dirname(reportPath), { recursive: true }); fs.writeFileSync(reportPath, JSON.stringify(report, null, 2) + "\n"); } assert.deepEqual(JSON.parse(fs.readFileSync(reportPath, "utf8")), report); const manifestValue = JSON.parse(fs.readFileSync(manifestPath, "utf8")); assert.deepEqual({ schemaVersion: manifestValue.schemaVersion, task: manifestValue.task, parentTask: manifestValue.parentTask, nextTask: manifestValue.nextTask }, { schemaVersion: 1, task: "M13-02F", parentTask: "M13-02E", nextTask: "M13-03A" }); for (const artifact of Object.values(manifestValue.artifacts)) assert.equal(hashFile(path.join(root, artifact.path)), artifact.sha256, `artifact hash mismatch ${artifact.path}`); process.stdout.write(`script-signature-negative-ok missing=SCRIPT_POLICY_DENIED expired=SCRIPT_POLICY_DENIED notYetValid=SCRIPT_POLICY_DENIED swapped=SCRIPT_SIGNATURE_INVALID next=${manifestValue.nextTask}\n`); } finally { fs.rmSync(temporary, { recursive: true, force: true }); }