import assert from 'node:assert/strict'; import { createHash } from 'node:crypto'; import fs from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import test from 'node:test'; import { prepareResourcePlan } from './deploy-portal-resources.mjs'; const digest = (value) => createHash('sha256').update(value).digest('hex'); test('resource plan copies only hash-verified approved protected resources', async () => { const root = await fs.mkdtemp(path.join(os.tmpdir(), 'aia-resource-plan-')); try { const hubfs = path.join(root, 'hubfs'), stage = path.join(root, 'stage'); await fs.mkdir(hubfs, { recursive: true }); const bytes = Buffer.from('synthetic non-phi document'); const localFile = 'a'.repeat(64); await fs.writeFile(path.join(hubfs, localFile), bytes, { mode: 0o600 }); await fs.writeFile(path.join(root, 'manifest.json'), JSON.stringify({ resources: [{ classification: 'STAFF-INTERNAL', deliveryPath: '/staff-resources/guide.pdf', destinationImplemented: true, destinationVerified: true, destinationAccessControlled: true, rewriteApproved: true, localFile, sha256: digest(bytes), size: bytes.length, }] })); const plan = await prepareResourcePlan(root, stage, 'a'.repeat(40)); assert.equal(plan.files.length, 1); assert.equal((await fs.readFile(path.join(stage, 'staff', localFile))).toString(), bytes.toString()); await fs.writeFile(path.join(root, 'manifest.json'), JSON.stringify({ resources: [{ classification: 'STAFF-INTERNAL', deliveryPath: '/staff-resources/../bad', localFile, sha256: digest(bytes), size: bytes.length }] })); await assert.rejects(prepareResourcePlan(root, path.join(root, 'second'), 'a'.repeat(40)), /destination/); } finally { await fs.rm(root, { recursive: true, force: true }); } });