import assert from 'node:assert/strict'; import fs from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import test from 'node:test'; import { verifyArtifact } from './phase10-artifact-verify.mjs'; import { createHash } from 'node:crypto'; import { encryptPortalStream, portalAlgorithm } from '../src/utils/portal-crypto.mjs'; async function fixture(mode = 'staging', forms = 'live') { const root = await fs.mkdtemp(path.join(os.tmpdir(), 'aia-phase10-artifact-')); const contactLandingFrames = [ ['contact/index.html', 'https://form.jotform.com/262946078314059?formContext=contact&language=en'], ['es/contact/index.html', 'https://form.jotform.com/262946078314059?formContext=contact&language=es'], ['lp/aba-therapy/index.html', 'https://form.jotform.com/262946078314059?formContext=landing&language=en'], ['lp/aba-insurance/index.html', 'https://form.jotform.com/262946078314059?formContext=landing&language=en'], ['lp/aba-ahcccs/index.html', 'https://form.jotform.com/262946078314059?formContext=landing&language=en'], ['lp/aba-private-pay/index.html', 'https://form.jotform.com/262946078314059?formContext=landing&language=en'], ['lp/early-intervention/index.html', 'https://form.jotform.com/262946078314059?formContext=landing&language=en'], ]; const consultationFrames = [ ['client-consultation/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=en'], ['es/client-consultation/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=es'], ['schedule-consultation/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=en'], ]; const consultationDrawers = [ ['aba-therapy/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=en'], ['autism-evaluations/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=en'], ['learner-social-club/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=en'], ['es/aba-therapy/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=es'], ['es/autism-evaluations/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=es'], ['es/learner-social-club/index.html', 'https://form.jotform.com/262946078314059?formContext=consultation&language=es'], ]; const robots = mode === 'staging' ? 'noindex,nofollow' : 'index,follow'; const pages = [['index.html', robots, '']]; if (mode === 'staging') pages.push(['lp/index.html', robots, '']); if (forms === 'live') { pages.push(...[...contactLandingFrames,...consultationFrames].map(([file, frame]) => [file, robots, `
`])); pages.push(...consultationDrawers.map(([file, frame]) => [file, robots, `
`])); } for (const [file, robots, body] of pages) { const target = path.join(root, file); await fs.mkdir(path.dirname(target), { recursive: true }); await fs.writeFile(target, `${file}

${file}

${body}
`); } await fs.writeFile(path.join(root, 'sitemap.xml'), mode === 'staging' ? '' : 'https://www.azinstitute4autism.com/'); return root; } test('staging artifact requires noindex, empty sitemap, no hreflang and review index', async () => { const result = await verifyArtifact(await fixture('staging'), 'staging'); assert.equal(result.passed, true); assert.equal(result.sitemapUrls, 0); assert.equal(result.reviewIndex, true); }); test('indexing artifact requires sitemap and excludes review index', async () => { const result = await verifyArtifact(await fixture('indexing'), 'indexing'); assert.equal(result.passed, true); assert.equal(result.sitemapUrls, 1); assert.equal(result.reviewIndex, false); }); test('live forms have ten immediate and six deferred placements independently of publication mode', async () => { for (const mode of ['staging','indexing']) { const result = await verifyArtifact(await fixture(mode), mode); assert.equal(result.passed, true, result.errors.join('; ')); assert.equal(result.formAIframes, 10); assert.equal(result.deferredFormAIframes, 6); assert.equal(result.reviewIndex, mode === 'staging'); } }); test('off and mock artifacts contain no real frames independently of publication mode', async () => { for (const mode of ['staging','indexing']) for (const forms of ['off','mock']) { const root = await fixture(mode, forms); const result = await verifyArtifact(root, mode, forms); assert.equal(result.passed, true); assert.equal(result.formAIframes + result.deferredFormAIframes, 0); await fs.appendFile(path.join(root, 'index.html'), ''); assert.equal((await verifyArtifact(root,mode,forms)).passed,false); } }); test('indexing artifact rejects an invalid Form A URL', async () => { const root = await fixture('indexing'); const contact = path.join(root, 'contact/index.html'); const html = await fs.readFile(contact, 'utf8'); await fs.writeFile(contact, html.replace('formContext=contact&language=en', 'formContext=landing&language=en')); const result = await verifyArtifact(root, 'indexing'); assert.equal(result.passed, false); assert.ok(result.errors.some((error) => error.includes('invalid approved Form A iframe URL'))); }); test('staging artifact rejects active native form actions', async () => { const root = await fixture('staging'); await fs.appendFile(path.join(root, 'index.html'), '
'); const result = await verifyArtifact(root, 'staging'); assert.equal(result.passed, false); assert.ok(result.errors.some((error) => error.includes('native form action'))); }); test('artifact rejects production API origin even when Form A is approved', async () => { const root = await fixture('staging'); await fs.appendFile(path.join(root, 'index.html'), '
https://api.azinstitute4autism.com
'); const result = await verifyArtifact(root, 'staging'); assert.equal(result.passed, false); assert.ok(result.errors.some((error) => error.includes('unsafe artifact signals'))); }); test('live counters allow only the reviewed API origin and explicit live mode', async () => { const root = await fixture('indexing'); await fs.appendFile(path.join(root, 'index.html'), '
'); assert.equal((await verifyArtifact(root, 'indexing', 'live', { mode: 'none' }, 'live')).passed, true); assert.equal((await verifyArtifact(root, 'indexing', 'live', { mode: 'none' }, 'off')).passed, false); const wrong = await fixture('indexing'); await fs.appendFile(path.join(wrong, 'index.html'), '
'); const result = await verifyArtifact(wrong, 'indexing', 'live', { mode: 'none' }, 'live'); assert.equal(result.passed, false); assert.ok(result.errors.some((error) => error.includes('approved mode or API origin'))); }); test('artifact rejects Form A identity outside the exact approved HTML routes', async () => { const root = await fixture('staging'); await fs.writeFile(path.join(root, 'assets.js'), 'https://form.jotform.com/262946078314059?formContext=contact'); const result = await verifyArtifact(root, 'staging'); assert.equal(result.passed, false); assert.ok(result.errors.some((error) => error.includes('outside approved routes'))); }); test('artifact rejects root-relative URLs with terminal slashes', async () => { const root = await fixture('staging'); await fs.appendFile(path.join(root, 'index.html'), 'Campaign'); const result = await verifyArtifact(root, 'staging'); assert.equal(result.passed, false); assert.ok(result.errors.some((error) => error.includes('root-relative URL(s) end in a slash'))); }); test('artifact digest is deterministic for unchanged files', async () => { const root = await fixture('staging'); const first = await verifyArtifact(root, 'staging'); const second = await verifyArtifact(root, 'staging'); assert.equal(first.artifactSha256, second.artifactSha256); assert.equal(first.artifactFiles, second.artifactFiles); }); test('release verification rejects private portal resources and encrypted payloads', async () => { const root = await fixture('staging'); await fs.mkdir(path.join(root, 'private/employee-portal'), { recursive: true }); await fs.writeFile(path.join(root, 'private/employee-portal/manifest.json'), '{}'); await fs.appendFile(path.join(root, 'index.html'), ''); const result = await verifyArtifact(root, 'staging'); assert.equal(result.passed, false); assert.ok(result.errors.some((error) => error.includes('portal ciphertext'))); assert.ok(result.errors.some((error) => error.includes('private/legacy'))); }); test('approved production portal accepts only the expected two-stream ciphertext on the noindex route', async () => { const root = await fixture('indexing'); const payload = { alg: portalAlgorithm, streams: [ await encryptPortalStream('staff', '

Synthetic staff

', 'synthetic-staff-code'), await encryptPortalStream('management', '

Synthetic management

', 'synthetic-management-code'), ] }; const portal = path.join(root, 'employee-portal/index.html'); await fs.mkdir(path.dirname(portal), { recursive: true }); await fs.writeFile(portal, 'Portal'); const sha256 = createHash('sha256').update(JSON.stringify(payload)).digest('hex'); const result = await verifyArtifact(root, 'indexing', 'live', { mode: 'production', sha256 }); assert.equal(result.passed, true, result.errors.join('; ')); await fs.appendFile(portal, ''); assert.equal((await verifyArtifact(root, 'indexing', 'live', { mode: 'production', sha256 })).passed, true); const corrupted = JSON.parse(JSON.stringify(payload)); corrupted.streams[0].ct = (corrupted.streams[0].ct[0] === 'A' ? 'B' : 'A') + corrupted.streams[0].ct.slice(1); await fs.writeFile(portal, 'Portal'); assert.equal((await verifyArtifact(root, 'indexing', 'live', { mode: 'production', sha256 })).passed, false); }); test('artifact rejects extra routes, wrong origins and prematurely loaded drawers', async () => { const root = await fixture(); await fs.appendFile(path.join(root,'index.html'), ''); assert.equal((await verifyArtifact(root)).passed,false); const clean = await fixture(); const file = path.join(clean,'aba-therapy/index.html'); await fs.writeFile(file,(await fs.readFile(file,'utf8')).replace('data-jotform-iframe-url=', 'src=')); assert.ok((await verifyArtifact(clean)).errors.some(e => e.includes('before activation'))); const other = await fixture(); await fs.appendFile(path.join(other,'index.html'), ''); assert.ok((await verifyArtifact(other)).errors.some(e => e.includes('unauthorized iframe'))); }); test('obsolete artifact modes are rejected with separate publication/form guidance', async () => { await assert.rejects(verifyArtifact('/unused','isolated-test'), /--forms=live\|off\|mock/); await assert.rejects(verifyArtifact('/unused','staging','invalid'), /live, off, or mock/); await assert.rejects(verifyArtifact('/unused','staging','live',{ mode: 'none' },'invalid'), /counters must be live/); });