Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit eea3f3327802f839df1c30f382026fb74ef69a63
parent 056cfc2fff24cbf93a81d2962bf1aaf333771b4e
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Thu,  8 Oct 2026 22:32:54 -0400

common: a report's notes.json is never published, exported or committed to history

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Mcommon/publish/composeReports.test.ts | 28++++++++++++++++++++++++++++
1 file changed, 28 insertions(+), 0 deletions(-)

diff --git a/common/publish/composeReports.test.ts b/common/publish/composeReports.test.ts @@ -54,6 +54,8 @@ const VIDEOS = "demo-channel"; const SOCIAL = "demo-social"; const REPORT = "demo-report"; const NOW_FLOOR = new Date().toISOString(); +// What a report's notes.json says: if it shows up in anything built, a note leaked. +const NOTES_SENTINEL = "operator-note-never-published-7f3a"; const writeJson = (file: string, value: unknown) => { mkdirSync(path.dirname(file), { recursive: true }); @@ -172,6 +174,8 @@ function seedSite(siteId: string, extra: Record<string, unknown> = {}, withRepor writeJson(path.join(dir, "report.json"), report()); writeText(path.join(dir, "stills", "a01.png"), "png-bytes"); writeText(path.join(dir, "sources", "s0", "page.html"), "<p>saved copy, never published</p>"); + // umtool's operator notes live beside report.json and are never published. + writeJson(path.join(dir, "notes.json"), { format: "umtool-notes", version: 1, notes: [{ text: NOTES_SENTINEL }] }); seedMedia(siteId); } @@ -786,3 +790,27 @@ test("reports export: no browser skips the PDF with a note; no zip fails the pac assert.equal(await exportMain({ siteId: "cited", formats: ["zip"], zipBin: path.join(ROOT, "no-such-zip") }, quiet), 1); assert.equal(await exportMain({ siteId: "cited", formats: ["html", "md"] }, quiet), 0); }); + +test("a report's notes.json (umtool's operator notes) is never published, exported or committed to its history", async () => { + const { reportHistoryGitDir } = await import("./reportHistory"); + const { execFileSync } = await import("node:child_process"); + const notes = path.join(paths.sitesDir, "cited", "reports", REPORT, "notes.json"); + assert.ok(existsSync(notes)); + await exportSiteReports({ siteId: "cited", paths, now: () => new Date("2026-10-08T08:00:00Z"), openPdfPrinter: fakePrinter([]), onLog: () => {} }); + await compose("cited"); + const leaks = (root: string) => + filesUnder(root).filter((f) => f.endsWith("notes.json") || readFileSync(path.join(root, f)).includes(NOTES_SENTINEL)); + assert.deepEqual(leaks(paths.exportPublicDir), []); + assert.deepEqual(leaks(reportExportDir(paths, "cited", REPORT)), []); + const gitDir = reportHistoryGitDir(paths, "cited", REPORT); + const revs = execFileSync("git", ["--git-dir", gitDir, "rev-list", "--all"], { encoding: "utf8" }).trim().split("\n").filter(Boolean); + assert.ok(revs.length > 0); + for (const rev of revs) { + const names = execFileSync("git", ["--git-dir", gitDir, "ls-tree", "-r", "--name-only", rev], { encoding: "utf8" }).trim().split("\n"); + assert.deepEqual(names.filter((n) => n.includes("notes")), [], rev); + for (const n of names) { + const blob = execFileSync("git", ["--git-dir", gitDir, "cat-file", "blob", `${rev}:${n}`]); + assert.ok(!blob.includes(NOTES_SENTINEL), `${rev}:${n}`); + } + } +});