import { test, after, before } from "node:test"; import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import { execFileSync } from "node:child_process"; import { chmodSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, symlinkSync, writeFileSync, } from "node:fs"; import os from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; import type { Paths } from "../lib/paths"; import { CLONE_URL, MIRROR_DIR, TARBALL_HREF, TREE_HREF } from "../lib/sourceManifest"; import { MAX_FILES, MAX_FILE_BYTES, NO_REPOSITORY, BUILT_IN_SESSION_RULE, SESSION_LINK_LITERAL, SESSION_LINK_RULES, SESSION_TRAILER, SOURCE_STEP_VERSION, SourceRefusal, clearPublishedSource, limitProblem, loadSourceRules, parseScrubRules, publishSource, publishedSourceProblem, gitleaksIdentity, historyCacheFor, historyDigest, resolveFilterRepo, rulesHashOf, scratchRootProblem, sourceDigest, type SourcePublishOpts, } from "./source"; import { writeFakeStagit } from "./__fixtures__/fakeStagit"; import { HISTORY_BACK_LINK } from "./sourceHistory"; // Run with: // pnpm --filter yt-dlp-transcript-common test // // `archilyzer source publish` (source.ts) over temp repos. The two tests that // rewrite history need git-filter-repo; they SKIP when resolveFilterRepo() // cannot find one (say so in a gate: the release gate requires they RAN). // Every repo, public dir and scratch dir is under the OS temp dir, and the git // variables a hook or a wrapper might export are cleared first. for (const key of ["GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE", "GIT_PREFIX"]) { delete process.env[key]; } const TMP = mkdtempSync(path.join(os.tmpdir(), "source-publish-")); after(() => rmSync(TMP, { recursive: true, force: true })); // Planted, never real: the home dir the built-in rule scrubs, and the paths. const HOME = "/home/not-a-real-user"; const PLANTED = "plantedhome"; const SECRET = "plantedsecret"; let filterRepoProblem: string | null = null; before(async () => { try { await resolveFilterRepo({}); } catch (err) { filterRepoProblem = (err as Error).message; } }); let n = 0; function dir(name: string): string { const d = path.join(TMP, `${name}-${n++}`); mkdirSync(d, { recursive: true }); return d; } function gitIn(cwd: string, ...args: string[]): string { return execFileSync("git", args, { cwd, stdio: "pipe" }).toString().trim(); } // A repo with `main` of three commits: a planted path in one blob and one // message, and the names the tree pages must encode. function sourceRepo(extra: Record = {}): string { const repo = dir("src"); gitIn(repo, "init", "-q", "-b", "main"); gitIn(repo, "config", "user.name", "source test"); gitIn(repo, "config", "user.email", "source@example.invalid"); gitIn(repo, "config", "commit.gpgsign", "false"); const put = (files: Record, message: string) => { for (const [f, text] of Object.entries(files)) { mkdirSync(path.dirname(path.join(repo, f)), { recursive: true }); writeFileSync(path.join(repo, f), text); } gitIn(repo, "add", "-A"); gitIn(repo, "commit", "-q", "-m", message); }; put( { "README.md": "hello\n", "app/[slug]/page.tsx": "export default 1;\n", "fonts/Archivo[wdth,wght].ttf": "not really a font\n", }, "first", ); put({ "notes.txt": `data lives at /srv/${PLANTED}/x\n`, ...extra }, "add notes"); put({ "README.md": "hello again\n" }, `moved from /srv/${PLANTED}`); return repo; } function operatorFiles(scrub: string, deny: string): { scrubFile: string; denylistFile: string } { const d = dir("config"); writeFileSync(path.join(d, "source-scrub.txt"), scrub); writeFileSync(path.join(d, "source-denylist.txt"), deny); return { scrubFile: path.join(d, "source-scrub.txt"), denylistFile: path.join(d, "source-denylist.txt") }; } // A checkout of its own (never TMP itself, which holds the scratch root: the // step refuses a scratch dir inside the checkout). function opts(repo: string, files: { scrubFile: string; denylistFile: string }, logs: string[], extra: Partial = {}): SourcePublishOpts { return { paths: { monorepoRoot: dir("checkout") } as Paths, sourceRepo: path.join(repo, ".git"), publicDir: path.join(dir("site"), "public"), scratchRoot: path.join(TMP, "scratch"), gitleaks: null, // No history pages unless a test gives a stagit (the machine may have one). stagit: null, homeDir: HOME, onLog: (l) => logs.push(l), now: () => new Date("2026-09-28T12:00:00.000Z"), ...files, ...extra, }; } const sha256 = (file: string) => createHash("sha256").update(readFileSync(file)).digest("hex"); // A manifest the page would believe, for the tests that fake a publish. function fakeManifest(sourceCommit: string, mirrorHead: string, sha = "b".repeat(64)): string { return JSON.stringify({ version: 1, generatedAt: "2026-09-28T12:00:00.000Z", branch: "main", sourceCommit, mirrorHead, subject: "s", files: 1, bytes: 1, mirror: { files: 1, bytes: 1, packs: 1 }, tree: { files: 1, dirs: 1, bytes: 1 }, tarball: { href: TARBALL_HREF, bytes: 7, sha256: sha }, cloneUrl: CLONE_URL, treeHref: TREE_HREF, audit: { objects: 1, commits: 1, gitleaks: "skipped" }, tools: { git: "x", filterRepo: "x" }, }); } test("scrub rules: the home-dir rule first, comments and blanks dropped, every literal left side denied", () => { const rules = parseScrubRules( ["# a comment", "", `/srv/${PLANTED}==>/home/user`, " # indented comment", "literal:abc==>x", "regex:a+b==>c", "glob:*.x==>y", "bare-line", "a==>b==>c", "\r"].join("\n"), HOME, ); assert.deepEqual(rules.lines, [ `${HOME}==>/home/user`, `/srv/${PLANTED}==>/home/user`, "literal:abc==>x", "regex:a+b==>c", "glob:*.x==>y", "bare-line", "a==>b==>c", ]); // filter-repo splits at the LAST ==>; regex and glob rules deny nothing. // Each denial is named by where it was written (the report's label). assert.deepEqual(rules.denied, [ { text: HOME, from: "built-in home rule" }, { text: `/srv/${PLANTED}`, from: "scrub line 3 lhs" }, { text: "abc", from: "scrub line 5 lhs" }, { text: "bare-line", from: "scrub line 8 lhs" }, { text: "a==>b", from: "scrub line 9 lhs" }, ]); // A home dir of `/`, or one that IS the replacement, gets no built-in rule; // a trailing slash is dropped, or the rule would match nothing. assert.deepEqual(parseScrubRules("", "/").lines, []); assert.deepEqual(parseScrubRules("", "/home/user").lines, []); assert.deepEqual(parseScrubRules("", `${HOME}/`).lines, [`${HOME}==>/home/user`]); }); test("scrub rules: a byte-order mark and CRLF are dropped; an empty left side refuses (review L2)", () => { // The reviewer's reproduction: a BOM made the first rule — and its implied // denial — `\uFEFF/srv/…`, which matches nothing. const bom = parseScrubRules(`\uFEFF/srv/${PLANTED}==>/home/user\r\nx==>y\r\n`, HOME); assert.deepEqual(bom.lines, [`${HOME}==>/home/user`, `/srv/${PLANTED}==>/home/user`, "x==>y"]); assert.deepEqual(bom.denied.map((d) => d.text), [HOME, `/srv/${PLANTED}`, "x"]); for (const line of ["==>user", "literal:==>user", "regex:==>user", "glob:"]) { assert.throws( () => parseScrubRules(`ok==>fine\n${line}\n`, HOME), (e) => e instanceof SourceRefusal && /scrub line 2 has an empty left side/.test(e.message), line, ); } }); test("the operator's files: a missing one refuses by name; the denylist's i: and the implied left sides; the hash moves with them", async () => { const d = dir("cfg"); await assert.rejects( loadSourceRules({ scrubFile: path.join(d, "nope.txt"), denylistFile: path.join(d, "deny.txt"), homeDir: HOME }), (e) => e instanceof SourceRefusal && /no scrub rules at .*nope\.txt — create it/.test(e.message), ); writeFileSync(path.join(d, "scrub.txt"), `/srv/${PLANTED}==>/home/user\n`); await assert.rejects( loadSourceRules({ scrubFile: path.join(d, "scrub.txt"), denylistFile: path.join(d, "deny.txt"), homeDir: HOME }), (e) => e instanceof SourceRefusal && /no denylist at .*deny\.txt/.test(e.message), ); writeFileSync(path.join(d, "deny.txt"), `\uFEFF# mine\r\ni:${SECRET.toUpperCase()}\r\n`); const a = await loadSourceRules({ scrubFile: path.join(d, "scrub.txt"), denylistFile: path.join(d, "deny.txt"), homeDir: HOME }); assert.deepEqual( a.literals.map((l) => [l.bytes.toString(), l.ci, l.from]), [ [SECRET, true, "denylist line 2"], [HOME, false, "built-in home rule"], [`/srv/${PLANTED}`, false, "scrub line 1 lhs"], [SESSION_LINK_LITERAL, true, BUILT_IN_SESSION_RULE], ], ); writeFileSync(path.join(d, "deny.txt"), `i:${SECRET}\nanother\n`); const b = await loadSourceRules({ scrubFile: path.join(d, "scrub.txt"), denylistFile: path.join(d, "deny.txt"), homeDir: HOME }); assert.notEqual(a.rulesHash, b.rulesHash, "a new literal must defeat the skip"); }); test("the limits: 15,000 files and 24 MiB a file, inside Pages' 20,000 and 25 MiB", () => { assert.equal(MAX_FILES, 15_000); assert.equal(MAX_FILE_BYTES, 24 * 1024 * 1024); assert.equal(limitProblem([{ rel: "a", bytes: MAX_FILE_BYTES }]), null); assert.match(limitProblem([{ rel: "big.pack", bytes: MAX_FILE_BYTES + 1 }])!, /^big\.pack is 24\.0 MiB, over the step's limit of 24\.0 MiB/); const many = Array.from({ length: MAX_FILES + 1 }, (_, i) => ({ rel: `f${i}`, bytes: 1 })); assert.match(limitProblem(many)!, /^15001 files to publish, over the step's limit of 15000/); assert.equal(limitProblem(many.slice(1)), null); }); test("skip: an unchanged main with unchanged rules, tools and files does nothing; each part of the key defeats it; a refusal withdraws", async () => { const repo = sourceRepo(); const files = operatorFiles(`/srv/${PLANTED}==>/home/user\n`, ""); const logs: string[] = []; // filter-repo is `false`: reaching it would refuse, so a 0 proves the skip // and a 1 proves the key did NOT match (review R2-L3: every case below goes // through the skip, never `check: true`, which skips nothing). const o = opts(repo, files, logs, { filterRepo: ["false"] }); const pub = o.publicDir!; const sourceCommit = gitIn(repo, "rev-parse", "main"); const rules = await loadSourceRules({ ...files, homeDir: HOME }); const mirrorHead = "a".repeat(40); const state = path.join(path.dirname(pub), ".source-publish.json"); const plant = async (tweak: Record = {}) => { mkdirSync(path.join(pub, "source", MIRROR_DIR, "info"), { recursive: true }); mkdirSync(path.join(pub, "downloads"), { recursive: true }); writeFileSync(path.join(pub, "source", MIRROR_DIR, "info", "refs"), "x\trefs/heads/main\n"); writeFileSync(path.join(pub, "downloads", path.basename(TARBALL_HREF)), "tarball"); writeFileSync(path.join(pub, "downloads", "snapshot.json"), "{}"); writeFileSync(path.join(pub, "source", "manifest.json"), fakeManifest(sourceCommit, mirrorHead)); const key = { sourceCommit, mirrorHead, rulesHash: rules.rulesHash, filterRepo: "false (given)", gitleaks: "skipped", contentDigest: await sourceDigest(pub), stagit: "absent", history: null, }; writeFileSync(state, JSON.stringify({ ...key, ...tweak })); }; const run = async () => { logs.length = 0; return publishSource(o); }; await plant(); assert.equal(await run(), 0); assert.match(logs.join("\n"), new RegExp(`up to date at ${sourceCommit.slice(0, 12)}; skipping`)); // Each part of the key, changed alone, reaches the rewrite (and the refusal // withdraws the planted publish, so it is planted again each time). for (const [what, tweak] of [ ["another filter-repo", { filterRepo: "git filter-repo 0.1" }], ["another gitleaks", { gitleaks: "gitleaks 8.0 (abc)" }], ["other files", { contentDigest: "0".repeat(64) }], ["other rules", { rulesHash: "0".repeat(64) }], ["another stagit", { stagit: "stagit (sha256 0123456789ab)" }], ] as Array<[string, Record]>) { await plant(tweak); assert.equal(await run(), 1, `${what} must not skip`); assert.match(logs.join("\n"), /REFUSED: false --force --quiet exited 1/, what); } // A published file edited in place defeats the skip too. await plant(); writeFileSync(path.join(pub, "downloads", "snapshot.json"), '{"edited":true}'); assert.equal(await run(), 1, "an edited public/ file must not skip"); // A changed rule refuses AND withdraws the last publish. await plant(); writeFileSync(files.denylistFile, "a-new-literal\n"); assert.equal(await run(), 1, "the new rule reached the rewrite"); assert.match(logs.join("\n"), /REFUSED: false --force --quiet exited 1/); assert.match(logs.join("\n"), /the previous publish was WITHDRAWN/); assert.ok(!existsSync(path.join(pub, "source")), "the last publish is withdrawn"); assert.ok(!existsSync(path.join(pub, "downloads", path.basename(TARBALL_HREF)))); assert.ok(!existsSync(path.join(pub, "downloads", "snapshot.json"))); assert.ok(!existsSync(state)); assert.equal(readdirSync(o.scratchRoot!).length, 0, "the scratch dir is removed"); }); test("the rules hash moves with the step's version (review R2-L3), and loadSourceRules uses the current one", async () => { const lines = ["a==>b"]; const literals = [{ bytes: Buffer.from("a"), ci: false }]; assert.notEqual(rulesHashOf(lines, literals, 1), rulesHashOf(lines, literals, 2)); assert.notEqual(rulesHashOf(lines, literals, 1), rulesHashOf(lines, [{ bytes: Buffer.from("a"), ci: true }], 1)); const files = operatorFiles("a==>b\n", ""); const rules = await loadSourceRules({ ...files, homeDir: "/" }); // The operator's rules, then the built-in session-link rules (applied last). assert.deepEqual(rules.scrub.lines, ["a==>b", ...SESSION_LINK_RULES]); assert.equal(rules.rulesHash, rulesHashOf(rules.scrub.lines, rules.literals, SOURCE_STEP_VERSION)); assert.ok(SOURCE_STEP_VERSION >= 4, "release 15 slice SG: the history pages"); }); test("gitleaksIdentity: skipped, absent, or the version line with the binary's sha256 (review R2-L4)", async () => { const bin = dir("gl-bin"); assert.equal(await gitleaksIdentity(null, { PATH: bin }), "skipped"); assert.equal(await gitleaksIdentity("gitleaks", { PATH: bin }), "absent"); const fake = path.join(bin, "gitleaks"); writeFileSync(fake, "#!/bin/sh\necho 'version is set by build process'\n"); chmodSync(fake, 0o755); const a = await gitleaksIdentity("gitleaks", { PATH: bin }); assert.match(a, /^version is set by build process \([0-9a-f]{12}\)$/); // Same version line, another binary (an upgrade on a distribution that // prints a constant line): another identity. writeFileSync(fake, "#!/bin/sh\necho 'version is set by build process'\n# 8.30\n"); assert.notEqual(await gitleaksIdentity("gitleaks", { PATH: bin }), a); }); test("the scratch root: refused inside the checkout or the public dir, through a symlink too (review L12)", async () => { const checkout = dir("chk"); const pub = path.join(dir("site"), "public"); const places: Array<[string, string]> = [["the checkout", checkout], ["the public dir", pub]]; assert.match((await scratchRootProblem(path.join(checkout, "tmp", "x"), places))!, /inside the checkout/); assert.match((await scratchRootProblem(path.join(pub, "s"), places))!, /inside the public dir/); const link = path.join(dir("links"), "into-checkout"); symlinkSync(checkout, link); assert.match((await scratchRootProblem(path.join(link, "new"), places))!, /inside the checkout/); assert.equal(await scratchRootProblem(path.join(TMP, "scratch"), places), null); // …and publishSource says so before making anything. const repo = sourceRepo(); const logs: string[] = []; const o = opts(repo, operatorFiles("", ""), logs, { filterRepo: ["false"] }); assert.equal(await publishSource({ ...o, scratchRoot: path.join(o.publicDir!, "scratch") }), 1); assert.match(logs.join("\n"), /REFUSED: the scratch root .* is inside the public dir/); assert.ok(!existsSync(path.join(o.publicDir!, "scratch"))); }); test("no git repository here (a docker runtime, a tarball install): the build gets the empty state, the CLI a sentence (review L8)", async () => { const bare = dir("no-git"); const pub = path.join(dir("site"), "public"); mkdirSync(path.join(pub, "source"), { recursive: true }); writeFileSync(path.join(pub, "source", "manifest.json"), "{}"); const logs: string[] = []; const o: SourcePublishOpts = { paths: { monorepoRoot: bare } as Paths, publicDir: pub, onLog: (l) => logs.push(l), // No operator files at all: nothing is read before the repository check. scrubFile: path.join(bare, "none.txt"), denylistFile: path.join(bare, "none.txt"), }; assert.equal(await publishSource({ ...o, check: true }), 1); assert.ok(existsSync(path.join(pub, "source", "manifest.json")), "--check writes nothing"); logs.length = 0; assert.equal(await publishSource(o), 1, "the CLI refuses"); assert.equal(logs[0], `[source] ${NO_REPOSITORY}`); assert.ok(!logs.join("\n").includes("fatal"), "no raw git error"); assert.ok(!existsSync(path.join(pub, "source")), "an old publish is removed"); mkdirSync(path.join(pub, "source"), { recursive: true }); writeFileSync(path.join(pub, "source", "manifest.json"), "{}"); logs.length = 0; assert.equal(await publishSource({ ...o, noRepository: "empty" }), 0, "buildHomepage builds on"); assert.equal(logs[0], `[source] ${NO_REPOSITORY}`); assert.ok(!existsSync(path.join(pub, "source"))); }); test("ARCHILYZER_SOURCE_REPO names the repository where the checkout has none (the container's mount); one that names nothing refuses by name (release 18)", async () => { const bare = dir("no-git-env"); const pub = path.join(dir("site"), "public"); const logs: string[] = []; const base: SourcePublishOpts = { paths: { monorepoRoot: bare } as Paths, publicDir: pub, onLog: (l) => logs.push(l), scrubFile: path.join(bare, "none.txt"), denylistFile: path.join(bare, "none.txt"), check: true, }; // A mounted repository: found, so the publish goes on to the next step — // here, the operator's files, which this scenario leaves out on purpose. // It is a git DIR — what the overlay mounts (the host's common dir), and what // the checkout lookup answers. const repo = path.join(sourceRepo(), ".git"); assert.equal(await publishSource({ ...base, env: { ...process.env, ARCHILYZER_SOURCE_REPO: repo } }), 1); assert.ok(!logs.includes(`[source] ${NO_REPOSITORY}`), logs.join("\n")); assert.match(logs.join("\n"), /none\.txt/, "it reached the operator's files"); // A variable naming a path that is not there: a refusal that names it, never // the "no repository" sentence. logs.length = 0; const gone = path.join(bare, "not-mounted.git"); assert.equal(await publishSource({ ...base, env: { ...process.env, ARCHILYZER_SOURCE_REPO: gone } }), 1); assert.match(logs.join("\n"), /REFUSED: ARCHILYZER_SOURCE_REPO names .*not-mounted\.git, which is not there/); assert.ok(!logs.includes(`[source] ${NO_REPOSITORY}`)); }); test("round trip: --check writes nothing; publish; a dumb clone of the mirror is main, scrubbed, from static files", async (t) => { if (filterRepoProblem) return t.skip(`git-filter-repo unavailable: ${filterRepoProblem}`); const repo = sourceRepo(); // A byte-order mark and CRLF endings, as some editors write them: the rule // must still scrub, and its left side must still be denied (review L2). const files = operatorFiles(`\uFEFF# the planted path\r\n/srv/${PLANTED}==>/home/user\r\n`, `i:${PLANTED}\r\n`); const logs: string[] = []; const o = opts(repo, files, logs); const pub = o.publicDir!; const site = path.dirname(pub); assert.equal(await publishSource({ ...o, check: true }), 0, logs.join("\n")); assert.match(logs.join("\n"), /check passed — would publish main .* nothing written/); assert.ok(!existsSync(pub), "--check wrote nothing"); assert.ok(!existsSync(path.join(site, ".source-publish.json"))); logs.length = 0; assert.equal(await publishSource(o), 0, logs.join("\n")); assert.match(logs.join("\n"), /\[source\] audit clean: \d+ objects \(3 commits\), \d+ staged files against 4 denied literals; gitleaks skipped/); assert.match(logs.join("\n"), /\[source\] published main [0-9a-f]{12} as [0-9a-f]{12}: \d+ files/); const manifest = JSON.parse(readFileSync(path.join(pub, "source", "manifest.json"), "utf8")); const sourceCommit = gitIn(repo, "rev-parse", "main"); assert.equal(manifest.version, 1); assert.equal(manifest.branch, "main"); assert.equal(manifest.sourceCommit, sourceCommit); assert.notEqual(manifest.mirrorHead, sourceCommit, "scrubbed history, different ids"); assert.equal(manifest.subject, "moved from /home/user"); assert.equal(manifest.cloneUrl, CLONE_URL); assert.equal(manifest.treeHref, TREE_HREF); assert.deepEqual(manifest.tree, { files: 4, dirs: 4, bytes: manifest.tree.bytes }); assert.ok(manifest.mirror.packs >= 1); assert.equal(manifest.audit.commits, 3); assert.equal(manifest.audit.gitleaks, "skipped"); assert.ok(!("rulesHash" in manifest), "the rules hash is never published"); assert.ok(!("literals" in manifest.audit), "nor how many literals there are (review L3)"); assert.ok(existsSync(path.join(site, ".source-publish.json")), "…it is kept beside public/"); // The mirror: the allowlist and the dumb-HTTP files. const mirror = path.join(pub, "source", MIRROR_DIR); for (const f of ["config", "hooks", "description", "filter-repo", "logs", "info/exclude"]) { assert.ok(!existsSync(path.join(mirror, f)), `${f} is never published`); } assert.equal(readFileSync(path.join(mirror, "HEAD"), "utf8"), "ref: refs/heads/main\n"); assert.equal(readFileSync(path.join(mirror, "info", "refs"), "utf8"), `${manifest.mirrorHead}\trefs/heads/main\n`); assert.match(readFileSync(path.join(mirror, "objects", "info", "packs"), "utf8"), /^P pack-[0-9a-f]+\.pack$/m); // Only packs and their indexes: git 2.55 also writes .rev files, which the // allowlist leaves behind. const packDir = readdirSync(path.join(mirror, "objects", "pack")); assert.ok(packDir.length >= 2); for (const f of packDir) assert.match(f, /^pack-[0-9a-f]+\.(pack|idx)$/); // EVERY object in the published packs, reachable or not — what a dumb-HTTP // reader gets — read from a plain copy of the published files (review L9). const copy = path.join(dir("copy"), "m.git"); cpSync(mirror, copy, { recursive: true }); const all = execFileSync("git", ["--git-dir", copy, "cat-file", "--batch-all-objects", "--batch"], { maxBuffer: 1 << 26 }); assert.equal(all.indexOf(PLANTED), -1, "no object in the packs holds the planted path"); assert.ok(all.includes(Buffer.from("/home/user")), "…which was scrubbed, not dropped"); assert.ok(!existsSync(path.join(pub, "source", "index.html")), "the /source/ page keeps its route"); // The clone. const clone = path.join(dir("clone"), "c"); execFileSync("git", ["clone", "-q", `file://${mirror}`, clone], { stdio: "pipe" }); assert.equal(gitIn(clone, "rev-parse", "HEAD"), manifest.mirrorHead); assert.equal(gitIn(clone, "log", "-1", "--format=%s"), "moved from /home/user"); assert.equal(readFileSync(path.join(clone, "notes.txt"), "utf8"), "data lives at /home/user/x\n"); const revs = gitIn(clone, "rev-list", "--all").split("\n"); assert.equal(revs.length, 3); assert.throws( () => execFileSync("git", ["grep", "-F", PLANTED, ...revs], { cwd: clone, stdio: "pipe" }), (e: { status?: number }) => e.status === 1, "no revision holds the planted path", ); assert.ok(!gitIn(clone, "log", "--all", "--format=%B%an%ae").includes(PLANTED)); // The tarball and its sidecar agree with the manifest and the bytes. const tarball = path.join(pub, "downloads", path.basename(TARBALL_HREF)); const snapshot = JSON.parse(readFileSync(path.join(pub, "downloads", "snapshot.json"), "utf8")); assert.equal(snapshot.sha256, sha256(tarball)); assert.equal(snapshot.sha256, manifest.tarball.sha256); assert.equal(snapshot.bytes, statSync(tarball).size); assert.equal(snapshot.commit, manifest.mirrorHead); assert.equal(snapshot.subject, "moved from /home/user"); // The tree pages. const tree = path.join(pub, "source", "tree"); for (const d of ["", "app", "app/[slug]", "fonts"]) assert.ok(existsSync(path.join(tree, d, "index.html")), d); assert.match(readFileSync(path.join(tree, "fonts", "index.html"), "utf8"), /href="Archivo%5Bwdth%2Cwght%5D\.ttf"/); assert.equal(readFileSync(path.join(tree, "notes.txt"), "utf8"), "data lives at /home/user/x\n"); assert.equal(readdirSync(o.scratchRoot!).length, 0, "the scratch dir is removed"); // Nothing changed: the next publish skips. logs.length = 0; assert.equal(await publishSource(o), 0); assert.match(logs.join("\n"), /up to date at/); // The deploy check (M1): a build's out/ that is this publish deploys… const out = path.join(dir("out"), "out"); const check = { ...files, homeDir: HOME, publicDir: pub, sourceRepo: path.join(repo, ".git"), gitleaks: null }; const checkPaths = o.paths!; // A build's out/ always has the /source page; a --no-source one, nothing more. mkdirSync(path.join(out, "source"), { recursive: true }); writeFileSync(path.join(out, "source", "index.html"), "

No source published in this build.

"); assert.equal(await publishedSourceProblem(checkPaths, out, check), null, "--no-source deploys as before"); cpSync(path.join(pub, "source"), path.join(out, "source"), { recursive: true }); cpSync(path.join(pub, "downloads"), path.join(out, "downloads"), { recursive: true }); assert.equal(await publishedSourceProblem(checkPaths, out, check), null); // Review R2-L3: a state naming another mirror head, or another gitleaks, // refuses — each by its own sentence (the digest below would refuse // neither, since out/ is untouched). const stateFile = path.join(site, ".source-publish.json"); const good = readFileSync(stateFile, "utf8"); const stateWith = (tweak: object) => writeFileSync(stateFile, JSON.stringify({ ...JSON.parse(good), ...tweak })); stateWith({ mirrorHead: "f".repeat(40) }); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /is not the last publish \(ffffffffffff\)/); stateWith({ gitleaks: "gitleaks 8.0 (abc)" }); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /scanned by another gitleaks/); writeFileSync(stateFile, good); // Review R2-L2: a mixed out/ — one tree file swapped, or one pack byte // flipped — does not match the digest of what was audited. const readme = path.join(out, "source", "tree", "README.md"); const readmeWas = readFileSync(readme); writeFileSync(readme, "another publish's README\n"); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /not the ones that were audited/); writeFileSync(readme, readmeWas); const packDirOut = path.join(out, "source", MIRROR_DIR, "objects", "pack"); const pack = path.join(packDirOut, readdirSync(packDirOut).find((f) => f.endsWith(".pack"))!); const packWas = readFileSync(pack); chmodSync(pack, 0o644); // git writes packs read-only; the digest reads bytes, not modes const flipped = Buffer.from(packWas); flipped[Math.floor(flipped.length / 2)] ^= 0x01; writeFileSync(pack, flipped); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /not the ones that were audited/); writeFileSync(pack, packWas); assert.equal(await publishedSourceProblem(checkPaths, out, check), null, "restored, it deploys again"); // …a tampered tarball does not… writeFileSync(path.join(out, "downloads", path.basename(TARBALL_HREF)), "other bytes"); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /tarball is not the one its manifest describes/); cpSync(path.join(pub, "downloads"), path.join(out, "downloads"), { recursive: true }); // …nor one of an older main. writeFileSync(path.join(repo, "later.txt"), "x\n"); gitIn(repo, "add", "-A"); gitIn(repo, "commit", "-q", "-m", "later"); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /main is now [0-9a-f]{12} — run `archilyzer publish homepage`/); // A REFUSAL WITHDRAWS THE PUBLISH (M1): deny a literal the mirror holds. // The deploy check refuses first (other rules), then the publish refuses // and removes public/source and the downloads. writeFileSync(files.denylistFile, `i:${PLANTED}\nhello again\n`); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /audited under other rules/); logs.length = 0; assert.equal(await publishSource(o), 1); assert.match(logs.join("\n"), /AUDIT REFUSED/); assert.match(logs.join("\n"), /denylist line 2 \(len 11\)/); assert.ok(!logs.join("\n").includes("hello again"), "the report never prints the literal"); assert.ok(!existsSync(path.join(pub, "source")), "public/source is withdrawn"); assert.ok(!existsSync(tarball), "the tarball is withdrawn"); assert.ok(!existsSync(path.join(pub, "downloads", "snapshot.json"))); assert.ok(!existsSync(path.join(site, ".source-publish.json"))); assert.match((await publishedSourceProblem(checkPaths, out, check))!, /no record of the rules/); }); test("session links never ship: the trailer goes from every message and file, a bare link becomes a placeholder, and none is left in any object (operator, 2026-10-09)", async (t) => { if (filterRepoProblem) return t.skip(`git-filter-repo unavailable: ${filterRepoProblem}`); // Assembled from parts, as source.ts does: this file is published too. const link = `https://${SESSION_LINK_LITERAL}_01Planted${"X".repeat(18)}`; const trailer = `${SESSION_TRAILER} ${link}`; const repo = dir("src"); gitIn(repo, "init", "-q", "-b", "main"); gitIn(repo, "config", "user.name", "source test"); gitIn(repo, "config", "user.email", "source@example.invalid"); gitIn(repo, "config", "commit.gpgsign", "false"); writeFileSync(path.join(repo, "README.md"), "hello\n"); gitIn(repo, "add", "-A"); gitIn(repo, "commit", "-q", "-m", `first\n\nCo-Authored-By: an agent \n${trailer}`); writeFileSync(path.join(repo, "rules.md"), `End every commit with:\n\n ${trailer}\n\nor see ${link} for the run.\n`); gitIn(repo, "add", "-A"); gitIn(repo, "commit", "-q", "-m", `second\n\n${trailer}`); const logs: string[] = []; const o = opts(repo, operatorFiles("", ""), logs); assert.equal(await publishSource(o), 0, logs.join("\n")); // Every object in the published packs, reachable or not. const mirror = path.join(o.publicDir!, "source", MIRROR_DIR); const copy = path.join(dir("copy"), "m.git"); cpSync(mirror, copy, { recursive: true }); const all = execFileSync("git", ["--git-dir", copy, "cat-file", "--batch-all-objects", "--batch"], { maxBuffer: 1 << 26 }); assert.equal(all.toString("latin1").toLowerCase().indexOf(SESSION_LINK_LITERAL), -1, "no object holds a session link"); assert.equal(all.indexOf(SESSION_TRAILER), -1, "no object holds the trailer"); const clone = path.join(dir("clone"), "c"); execFileSync("git", ["clone", "-q", `file://${mirror}`, clone], { stdio: "pipe" }); assert.equal(gitIn(clone, "log", "-1", "--format=%B"), "second"); assert.equal(gitIn(clone, "log", "-1", "--format=%B", "HEAD~1"), "first\n\nCo-Authored-By: an agent "); assert.equal(readFileSync(path.join(clone, "rules.md"), "utf8"), "End every commit with:\n\n\nor see [session link removed] for the run.\n"); }); test("a denied literal no rule removes: refused, nothing written, the report never prints it", async (t) => { if (filterRepoProblem) return t.skip(`git-filter-repo unavailable: ${filterRepoProblem}`); const repo = sourceRepo({ "keys.txt": `the ${SECRET} is here\n` }); const files = operatorFiles(`/srv/${PLANTED}==>/home/user\n`, `${SECRET}\n`); const logs: string[] = []; const o = opts(repo, files, logs); const downloads = path.join(o.publicDir!, "downloads"); mkdirSync(downloads, { recursive: true }); writeFileSync(path.join(downloads, "snapshot.json"), "yesterday's"); assert.equal(await publishSource({ ...o, keepScratch: true }), 1); const report = logs.join("\n"); assert.ok(!report.includes(SECRET), report); assert.ok(!report.includes("is here"), "no byte from beside the hit (review L4)"); assert.match(report, /AUDIT REFUSED: 1 hit in \d+ objects/); assert.match(report, /denylist line 1 \(len 13\): 1 in blob/); assert.match(report, /blob [0-9a-f]{12} keys\.txt \(byte 4\): denylist line 1 \(len 13\)/); assert.match(report, /add a rule to .*source-scrub\.txt or drop the file from history, then re-run\./); assert.ok(!existsSync(path.join(o.publicDir!, "source")), "no manifest, no mirror"); assert.ok(!existsSync(path.join(downloads, "snapshot.json")), "yesterday's snapshot is withdrawn too"); // --keep-scratch keeps the clone for a look, never the scrub rules. const kept = /scratch kept at (\S+) \(replace\.txt, the scrub rules, deleted\)/.exec(report); assert.ok(kept, report); // The log tildifies with the real home dir, so a TMPDIR under it prints "~/…". const keptDir = kept[1].replace(/^~(?=\/|$)/, os.homedir()); assert.ok(existsSync(path.join(keptDir, MIRROR_DIR)), "the clone is named as the mirror is (stagit names it after its directory)"); assert.ok(!existsSync(path.join(keptDir, "replace.txt"))); rmSync(keptDir, { recursive: true, force: true }); }); test("a refusal naming a tree path masks a literal that spans path components (review R2-L1)", async (t) => { if (filterRepoProblem) return t.skip(`git-filter-repo unavailable: ${filterRepoProblem}`); // `plant/secret` is invisible to the object walk (which reads entry names // one at a time), so the first refusal to name it is the tree's own: a // tracked symlink below it, then a tracked index.html. const spanning = "plant/secret"; const repo = sourceRepo(); mkdirSync(path.join(repo, "plant", "secret"), { recursive: true }); symlinkSync("../../README.md", path.join(repo, "plant", "secret", "link")); gitIn(repo, "add", "-A"); gitIn(repo, "commit", "-q", "-m", "a link"); const files = operatorFiles(`/srv/${PLANTED}==>/home/user\n`, `${spanning}\n`); const logs: string[] = []; assert.equal(await publishSource(opts(repo, files, logs)), 1); let log = logs.join("\n"); assert.match(log, /REFUSED: the tree holds a symlink \(\[REDACTED\]\/link\)/); assert.ok(!log.includes(spanning), log); gitIn(repo, "rm", "-q", "plant/secret/link"); mkdirSync(path.join(repo, "plant", "secret"), { recursive: true }); writeFileSync(path.join(repo, "plant", "secret", "index.html"), "

x

"); gitIn(repo, "add", "-A"); gitIn(repo, "commit", "-q", "-m", "an index"); logs.length = 0; assert.equal(await publishSource(opts(repo, files, logs)), 1); log = logs.join("\n"); assert.match(log, /REFUSED: the tree already has \[REDACTED\]\/index\.html/); assert.ok(!log.includes(spanning), log); }); test("--no-source's clear: the manifest, mirror, tree, tarball and skip key go; a linked downloads/ goes as a link", async () => { const site = dir("clear"); const pub = path.join(site, "public"); mkdirSync(path.join(pub, "source", MIRROR_DIR), { recursive: true }); writeFileSync(path.join(pub, "source", "manifest.json"), "{}"); const elsewhere = dir("elsewhere"); writeFileSync(path.join(elsewhere, "snapshot.json"), "the other checkout's"); symlinkSync(elsewhere, path.join(pub, "downloads")); writeFileSync(path.join(site, ".source-publish.json"), "{}"); const logs: string[] = []; await clearPublishedSource({ paths: {} as Paths, publicDir: pub, onLog: (l) => logs.push(l) }); assert.ok(!existsSync(path.join(pub, "source"))); assert.ok(!existsSync(path.join(site, ".source-publish.json"))); assert.equal(lstatSync(path.join(pub, "downloads"), { throwIfNoEntry: false }), undefined); assert.equal(readFileSync(path.join(elsewhere, "snapshot.json"), "utf8"), "the other checkout's"); assert.match(logs.join("\n"), /previously published source .* was removed/); }); // ── the history pages (release 15 slice SG) ───────────────────────────────── // // Over a fake stagit that writes what stagit writes (sourceHistory.test.ts // runs the real one), and with filter-repo replaced by `true` — no rewrite, // so these run on any machine; the history does not care what the rewrite did. const TOKENS_FILE = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "styles", "tokens.css"); // The fake (__fixtures__/fakeStagit.ts) writes what stagit writes, with -c // and -l as stagit.c has them. function fakeStagit(log: string, o: { exit?: number; extra?: string; pad?: number } = {}): string { return writeFakeStagit(path.join(dir("fake-stagit"), "stagit"), log, o); } // A render cache of its own, where XDG_CACHE_HOME would put it. const cacheDirIn = (root: string) => path.join(root, "archilyzer", "source-history"); const stagitCalls = (log: string) => (existsSync(log) ? readFileSync(log, "utf8").trim().split("\n") : []); test("history: published with the source — the allowlist at /source/git/, the manifest's block, the skip key, incremental, and the deploy check names it", async () => { const repo = sourceRepo(); const files = operatorFiles("", ""); const logs: string[] = []; const log = path.join(dir("stagit-log"), "calls"); const cacheDir = cacheDirIn(dir("cache-home")); const o = opts(repo, files, logs, { filterRepo: ["true"], stagit: fakeStagit(log), tokensFile: TOKENS_FILE, historyCacheDir: cacheDir }); const pub = o.publicDir!; const site = path.dirname(pub); assert.equal(await publishSource(o), 0, logs.join("\n")); let text = logs.join("\n"); assert.match(text, /\[source\] history: stagit \(sha256 [0-9a-f]{12}\) — 3 commits, 3 pages rendered; 9 files, [\d.]+ MB, the largest git\/\S+ [\d.]+ MB/); assert.match(text, /\[source\] published main .* tree \d+ dirs, history 3 commits in 9 files\)/); assert.deepEqual(stagitCalls(log), [ `cache=${path.join(cacheDir, "stagit.cache")} limit= base=https://archilyzer.pages.dev/source/git/ repo=${MIRROR_DIR}`, ]); const manifest = JSON.parse(readFileSync(path.join(pub, "source", "manifest.json"), "utf8")); assert.deepEqual(Object.keys(manifest.history).sort(), ["bytes", "commits", "files", "head", "href", "sha256", "tool", "total"]); assert.equal(manifest.history.href, "/source/git/log.html"); assert.equal(manifest.history.commits, 3); assert.equal(manifest.history.total, 3); assert.equal(manifest.history.head, manifest.mirrorHead); assert.equal(manifest.history.files, 9); assert.equal(manifest.history.sha256, await historyDigest(pub)); assert.match(manifest.history.tool, /^stagit \(sha256 [0-9a-f]{12}\)$/); assert.ok(manifest.files >= 9, "the manifest's count includes the history"); const git = path.join(pub, "source", "git"); assert.deepEqual(readdirSync(git).sort(), ["atom.xml", "commit", "files.html", "log.html", "refs.html", "style.css", "tags.xml"]); const logHtml = readFileSync(path.join(git, "log.html"), "utf8"); assert.ok(logHtml.includes(`Archilyzer ${CLONE_URL} `), "stagit's header: the name and the clone URL"); assert.ok(logHtml.includes(HISTORY_BACK_LINK)); assert.match(logHtml, /