/* --provenance-sources (EXPERIMENTAL): the provenance-assisted static * compilation pipeline, offline — the fixture manifest * (SCRIPTC_PROVENANCE_MANIFEST) stands in for the live attestation + * source fetch, so these tests exercise everything AFTER the network: * source-entry mapping, the registry chokepoints (preflight edges, tsgo * "paths", the npm-import bypass), the @__PURE__ dead-const elision, the * per-package attribution, and the island fallback notes. * * The differential contract is the thesis itself: the binary compiled * from the ATTESTED SOURCE (static, no island) must byte-match the * binary island-running the PUBLISHED dist — and both must byte-match * Node running the published package. */ import { execFile } from "node:child_process"; import { mkdirSync } from "node:fs"; import { join } from "node:path"; import { promisify } from "node:util"; import { afterEach, describe, expect, test } from "vitest"; import { analyze, compile, resolveProvenanceSources, setProvenanceSources, } from "@scriptc/compiler"; const execFileAsync = promisify(execFile); const repoRoot = join(import.meta.dirname, "../.."); const fixtureDir = join(repoRoot, "tests/fixtures/provenance"); const entry = join(fixtureDir, "cases/greet/main.ts"); /* Suite-flavor segment: the plain and SCRIPTC_SAN=1 suites both run these * same (unsanitized) builds and may run concurrently — the suite lock is * per flavor — so they must never share a build dir. */ const flavor = process.env["SCRIPTC_SAN"] === "1" ? "san" : "plain"; const outDir = join(repoRoot, "node_modules/.cache/scriptc-tests/provenance", flavor); const EXPECTED = "hello, world\nHELLO, COMPILER!\nhello, chain!\n"; async function buildAndRun(name: string, dynamic: boolean, program = entry): Promise { mkdirSync(outDir, { recursive: true }); const outPath = join(outDir, name); // Pinned: the provenance thesis compares a source-static binary against // a dist-island binary — holding both on the C lane keeps that byte // comparison about PROVENANCE, never about which backend each build drew. const result = await compile(program, { outPath, outDir, dynamic, backend: "llvm" }); if (!result.ok) { throw new Error(result.diagnostics.map((d) => `${d.code}: ${d.message}`).join("\n")); } const { stdout } = await execFileAsync(outPath, [], { encoding: "utf8" }); return stdout; } afterEach(() => { setProvenanceSources(null); delete process.env["SCRIPTC_PROVENANCE_MANIFEST"]; }); describe("provenance sources", () => { test("attested source compiles STATIC and byte-matches the island's published dist", async () => { // Flag off: the published dist embeds in the island (--dynamic). const island = await buildAndRun("greet-island", true); expect(island).toBe(EXPECTED); // Flag on: the manifest maps greeter to its source tree; the driver // compiles WITHOUT --dynamic — possible only because the source // became program modules (a bare npm import would fence a static // build), which IS the assertion that nothing islanded. process.env["SCRIPTC_PROVENANCE_MANIFEST"] = join(fixtureDir, "manifest.json"); const sources = await resolveProvenanceSources(entry); expect(sources.packages).toHaveLength(1); const pkg = sources.packages[0]!; expect(pkg.name).toBe("greeter"); expect(pkg.version).toBe("1.2.3"); expect(pkg.entries["greeter"]).toMatch(/attested-src\/greeter\/src\/index\.ts$/); setProvenanceSources(sources); const fromSource = await buildAndRun("greet-static", false); expect(fromSource).toBe(island); }); test("maps a published dist/esm subpath to its unmodified TypeScript source", async () => { const subpathEntry = join(fixtureDir, "cases/echo/main.ts"); const node = await execFileAsync("node", [subpathEntry], { encoding: "utf8" }); process.env["SCRIPTC_PROVENANCE_MANIFEST"] = join(fixtureDir, "manifest.json"); const sources = await resolveProvenanceSources(subpathEntry); expect(sources.packages[0]?.entries["greeter/echo"]).toMatch(/attested-src\/greeter\/src\/echo\.ts$/); setProvenanceSources(sources); expect(await buildAndRun("echo-static", false, subpathEntry)).toBe(node.stdout); }); test("per-package attribution counts the source static; the @__PURE__ dead const elides", async () => { process.env["SCRIPTC_PROVENANCE_MANIFEST"] = join(fixtureDir, "manifest.json"); setProvenanceSources(await resolveProvenanceSources(entry)); const { coverage } = analyze(entry); expect(coverage.preflightFailed).toBe(false); // No blockers anywhere: the dead const elided instead of fencing. expect(coverage.diagnostics).toHaveLength(0); expect(coverage.provenanceElided ?? []).toHaveLength(1); expect(coverage.provenanceElided![0]!.message).toContain("'Legacy'"); // Attribution: every counted statement of the greeter source is // static (the elided declaration never counts — it lowers to nothing). const srcStats = [...(coverage.statsByFile ?? [])].filter(([f]) => f.includes("attested-src/greeter/")); expect(srcStats.length).toBeGreaterThan(0); for (const [, s] of srcStats) { expect(s.failed).toBe(0); expect(s.island).toBe(0); } }); test("an unmappable package falls back to the island with a note, never a failure", async () => { process.env["SCRIPTC_PROVENANCE_MANIFEST"] = join(fixtureDir, "manifest-broken.json"); const sources = await resolveProvenanceSources(entry); expect(sources.packages).toHaveLength(0); expect(sources.notes).toHaveLength(1); expect(sources.notes[0]).toContain("greeter"); expect(sources.notes[0]).toContain("island path used"); setProvenanceSources(sources); // The island path still works under the flag — the fallback contract. const island = await buildAndRun("greet-fallback", true); expect(island).toBe(EXPECTED); }); });