import assert from "node:assert/strict"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { pathToFileURL } from "node:url"; import test from "node:test"; import ts from "typescript"; const repoRoot = path.resolve(import.meta.dirname, "../../.."); const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "sequencer-codec-probe-unit-")); function transpile(sourceName, outputName, replacements = []) { const sourcePath = path.join(repoRoot, "web/protocol", sourceName); const result = ts.transpileModule(fs.readFileSync(sourcePath, "utf8"), { compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 }, fileName: sourcePath, reportDiagnostics: true, }); assert.deepEqual(result.diagnostics, []); fs.writeFileSync(path.join(temporary, outputName), replacements.reduce((value, [from, to]) => value.replaceAll(from, to), result.outputText)); } transpile("capability-gates.ts", "capability-gates.mjs"); transpile("asset-path.ts", "asset-path.mjs"); transpile("sequencer.ts", "sequencer.mjs", [ ['from "./capability-gates"', 'from "./capability-gates.mjs"'], ['from "./asset-path"', 'from "./asset-path.mjs"'], ]); const sequencer = await import(pathToFileURL(path.join(temporary, "sequencer.mjs"))); const requests = [ { schemaVersion: 1, stripType: "IMAGE", mimeType: "image/png", byteLength: 261, sourceSha256: "a".repeat(64) }, { schemaVersion: 1, stripType: "SOUND", mimeType: "audio/wav", byteLength: 16_044, sourceSha256: "b".repeat(64) }, { schemaVersion: 1, stripType: "MOVIE", mimeType: "video/mp4", byteLength: 1_484, sourceSha256: "c".repeat(64) }, ]; const ready = [ { backend: "IMAGE_BITMAP", decoded: { width: 8, height: 8 } }, { backend: "WEB_AUDIO", decoded: { sampleRate: 8_000, channels: 1, durationFrames: 8_000 } }, { backend: "HTML_MEDIA", decoded: { width: 16, height: 16, durationMicros: 1_000_000 } }, ]; test("M11-09 gates IMAGE, SOUND and MOVIE only with identity-bound ready probe receipts", () => { for (const [index, request] of requests.entries()) { assert.deepEqual(sequencer.parseSequencerCodecProbeRequest(request), request); const result = { ...request, status: "READY", backend: ready[index].backend, reason: null, decoded: ready[index].decoded }; assert.equal(sequencer.gateSequencerCodec(request, result).status, "READY"); } }); test("M11-09 rejects extension fields, family mismatch, forged backend and source drift", () => { assert.throws(() => sequencer.parseSequencerCodecProbeRequest({ ...requests[0], sourcePath: "image.mp4" }), { code: "SEQUENCER_SCHEMA_INVALID" }); assert.throws(() => sequencer.parseSequencerCodecProbeRequest({ ...requests[0], mimeType: "video/mp4" }), { code: "SEQUENCER_SCHEMA_INVALID" }); const forged = { ...requests[0], status: "READY", backend: "HTML_MEDIA", reason: null, decoded: { width: 8, height: 8 } }; assert.deepEqual(sequencer.gateSequencerCodec(requests[0], forged).issues.map((issue) => issue.code), ["SEQUENCER_CODEC_UNSUPPORTED"]); const drift = { ...requests[0], sourceSha256: "d".repeat(64), status: "READY", backend: "IMAGE_BITMAP", reason: null, decoded: { width: 8, height: 8 } }; assert.deepEqual(sequencer.gateSequencerCodec(requests[0], drift).issues.map((issue) => issue.code), ["SEQUENCER_CODEC_UNSUPPORTED"]); }); test("M11-09 keeps runtime unavailability and decode failure blocked", () => { for (const [index, request] of requests.entries()) { const result = { ...request, status: "BLOCKED", backend: ready[index].backend, reason: "DECODE_FAILED", decoded: null }; const gate = sequencer.gateSequencerCodec(request, result); assert.equal(gate.status, "BLOCKED"); assert.deepEqual(gate.issues.map((issue) => issue.code), ["SEQUENCER_CODEC_UNSUPPORTED"]); } }); test.after(() => fs.rmSync(temporary, { recursive: true, force: true }));