// payload-trees.test.mjs — the materialized trees are byte-identical to the // fixtures that used to sit on disk (sha256 measured before deletion, S1), // and so are the encoded example archives (S2). import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync, readdirSync } from 'node:fs'; import { join, relative, basename } from 'node:path'; import { createHash } from 'node:crypto'; import { PAYLOAD_TREES, materializeTree } from './payload-trees.mjs'; import { DEMO_ARCHIVE, readArchive, materializeArchive } from '../../examples/malicious-skill-demo/materialize.mjs'; function walk(dir) { return readdirSync(dir, { withFileTypes: true, recursive: true }) .filter(e => e.isFile()) .map(e => join(e.parentPath, e.name)); } describe('payload-trees: materialized bytes match the retired on-disk fixtures', () => { for (const name of Object.keys(PAYLOAD_TREES)) { it(name, () => { const { dir, cleanup } = materializeTree(name); try { const written = walk(dir).map(f => relative(dir, f)).sort(); assert.deepEqual(written, Object.keys(PAYLOAD_TREES[name]).sort(), 'file set changed'); for (const [rel, { sha256 }] of Object.entries(PAYLOAD_TREES[name])) { const got = createHash('sha256').update(readFileSync(join(dir, rel))).digest('hex'); assert.equal(got, sha256, `${name}/${rel} differs from the retired fixture`); } } finally { cleanup(); } }); } }); // S2 (2026-09-22): the example trees are encoded archives next to their // examples; same check, sha256 measured from the retired on-disk files. const EXAMPLE_ARCHIVES = { 'malicious-skill-demo/evil-project-health': DEMO_ARCHIVE, }; describe('example archives: materialized bytes match the retired on-disk trees', () => { for (const [name, archivePath] of Object.entries(EXAMPLE_ARCHIVES)) { it(name, () => { const { files } = readArchive(archivePath); const { dir, cleanup } = materializeArchive(archivePath); try { assert.equal(basename(dir), basename(name), 'leaf directory name changed'); const written = walk(dir).map(f => relative(dir, f)).sort(); assert.deepEqual(written, Object.keys(files).sort(), 'file set changed'); for (const [rel, { sha256 }] of Object.entries(files)) { assert.match(sha256, /^[0-9a-f]{64}$/, `${name}/${rel} has no recorded sha256`); const got = createHash('sha256').update(readFileSync(join(dir, rel))).digest('hex'); assert.equal(got, sha256, `${name}/${rel} differs from the retired fixture`); } } finally { cleanup(); } }); } });