const assert = require('node:assert/strict') const test = require('node:test') const fs = require('node:fs') const path = require('node:path') const vm = require('node:vm') const { idle, assertIdleSnapshot, nativeQueues, queueStates, isActivatedRelease, assertPublicVerification, assertFixtureReconciliation, publicVerificationReports, fixtureReconciliationCounts } = require('./publish_public_runtime.cjs') test('a frontend-only release with an unchanged API image is a new activation', () => { const manifest = { release: 'public-20260920-165100', api_image_id: 'sha256:same-image' } assert.equal(isActivatedRelease({ image: manifest.api_image_id, release: 'public-20260920-160500' }, manifest), false) assert.equal(isActivatedRelease({ image: manifest.api_image_id, release: manifest.release }, manifest), true) assert.equal(isActivatedRelease({ image: 'sha256:other-image', release: manifest.release }, manifest), false) assert.equal(isActivatedRelease({ image: manifest.api_image_id, release: null }, manifest), false) }) function emptySnapshot() { return { workbench: 0, pending_ops: 0, queues: Object.fromEntries(nativeQueues.map(name => [name, Object.fromEntries(queueStates.map(state => [state, 0]))])) } } test('permits idle runtime while retaining archived and completed task history', () => { const snapshot = emptySnapshot() Object.assign(snapshot.queues.graph, { archived: 10, completed: 16 }) assert.doesNotThrow(() => assertIdleSnapshot(snapshot)) }) test('blocks persisted Wiki operations even when every Redis queue is empty', () => { const snapshot = emptySnapshot() snapshot.pending_ops = 1 assert.throws(() => assertIdleSnapshot(snapshot), /persisted background/) }) test('blocks workbench jobs, uploads or reserved balances', () => { const snapshot = emptySnapshot() snapshot.workbench = 1 assert.throws(() => assertIdleSnapshot(snapshot), /jobs, uploads or reserved/) }) for (const queue of nativeQueues) { for (const state of queueStates) { test(`blocks native ${queue} work in ${state} state`, () => { const snapshot = emptySnapshot() snapshot.queues[queue][state] = 1 assert.throws(() => assertIdleSnapshot(snapshot), /active or waiting/) }) } } test('blocks newly discovered queues instead of ignoring future worker types', () => { const snapshot = emptySnapshot() snapshot.queues.future_worker = { ...snapshot.queues.graph, active: 1 } assert.throws(() => assertIdleSnapshot(snapshot), /active or waiting/) }) test('fails closed on missing queues and invalid count shapes', () => { const snapshot = emptySnapshot() delete snapshot.queues.graph assert.throws(() => assertIdleSnapshot(snapshot), /Cannot verify/) for (const count of [undefined, null, '', '0', -1, NaN, Infinity, 0.1, Number.MAX_SAFE_INTEGER + 1]) { const item = emptySnapshot() item.queues.wiki.active = count assert.throws(() => assertIdleSnapshot(item), /Cannot verify/) assert.throws(() => assertIdleSnapshot({ ...emptySnapshot(), pending_ops: count }), /Cannot verify/) } }) function fakeRuntime(overrides = {}, transformRedis = value => value) { const runtime = { DB_NAME: 'yawan_native_acceptance_20260915', REDIS_ADDR: 'actual-redis:6379', REDIS_DB: '14', REDIS_USERNAME: 'worker', REDIS_PASSWORD: 'private-test-password', ...overrides, } const calls = [] const run = (binary, args, options) => { calls.push({ binary, args, options }) if (args.includes('psql')) { assert.match(args.at(-1), /count\(\*\) FROM task_pending_ops/) return JSON.stringify({ workbench: 0, pending_ops: 0 }) } if (args.includes('inspect')) return JSON.stringify(Object.entries(runtime).map(([key, value]) => `${key}=${value}`)) assert.ok(args.includes('redis-cli')) return transformRedis(JSON.stringify(emptySnapshot().queues)) } return { run, calls } } test('reads actual Redis identity and DB with no password in argv or parent env', () => { const previous = process.env.REDISCLI_AUTH const { run, calls } = fakeRuntime() assert.doesNotThrow(() => idle(run)) const command = calls.at(-1) assert.equal(command.binary, 'docker') assert.ok(command.args.includes('EVAL_RO')) assert.equal(command.args[command.args.indexOf('-h') + 1], 'actual-redis') assert.equal(command.args[command.args.indexOf('-n') + 1], '14') assert.equal(command.args[command.args.indexOf('--user') + 1], 'worker') assert.equal(command.options.env.REDISCLI_AUTH, 'private-test-password') assert.equal(process.env.REDISCLI_AUTH, previous) assert.ok(!command.args.join(' ').includes('private-test-password')) assert.ok(calls.every(call => call.options.timeout === 15000)) }) test('preserves runtime TLS verification and supports IPv6 Redis addresses', () => { const { run, calls } = fakeRuntime({ REDIS_ADDR: '[::1]:6380', REDIS_USE_TLS: 'true', REDIS_TLS_SERVER_NAME: 'redis.example.test' }) idle(run) const args = calls.at(-1).args assert.equal(args[args.indexOf('-h') + 1], '::1') assert.equal(args[args.indexOf('-p') + 1], '6380') assert.ok(args.includes('--tls')) assert.equal(args[args.indexOf('--sni') + 1], 'redis.example.test') assert.ok(!args.includes('--insecure')) }) test('does not publish when Redis auth, transport or response validation fails', () => { for (const transform of [() => 'NOAUTH private-test-password', () => '{invalid', () => { throw new Error('connection failed private-test-password') }]) { const { run } = fakeRuntime({}, transform) assert.throws(() => idle(run), error => { assert.match(error.message, /publication stopped/) assert.ok(!error.message.includes('private-test-password')) return true }) } for (const overrides of [{ REDIS_ADDR: '' }, { REDIS_DB: '' }, { REDIS_DB: 'broken' }, { DB_NAME: 'old_database' }]) { assert.throws(() => idle(fakeRuntime(overrides).run), /publication stopped/) } }) test('minimum queue coverage follows the native Go worker topology', () => { const source = fs.readFileSync(path.join(__dirname, '../internal/types/task.go'), 'utf8') const names = [...source.matchAll(/^\s*Queue\w+\s*=\s*"([^"]+)"/gm)].map(match => match[1]) assert.deepEqual([...nativeQueues].sort(), names.sort()) }) const clock = Date.parse('2026-09-19T18:00:00.000Z') function publicationFixture() { return { manifest: { url: 'https://agent.pducv.cn', activated_at: '2026-09-19T14:29:38.265Z', api_activated_at: '2026-09-19T14:51:44.349Z', frontend_built_at: '2026-09-19T15:18:58.094Z', frontend_activated_at: '2026-09-19T15:22:00.000Z', }, report: { started_at: '2026-09-19T15:23:00.000Z', checked_at: '2026-09-19T15:24:18.110Z', origin: 'https://agent.pducv.cn', api_origin: 'https://agent.pducv.cn', checks: [{passed: true}], failures: [], passed: true, }, } } const verifyPublication = (manifest, report) => assertPublicVerification(manifest, report, 'fixture-report', clock) for (const name of ['public-navigation', 'public-access-control']) { test(`${name} requires proof its API checks use the public origin`, () => { const {manifest, report} = publicationFixture() assert.doesNotThrow(() => assertPublicVerification(manifest, report, name, clock)) for (const api_origin of [undefined, '', 'invalid', 'http://127.0.0.1:18080', 'https://another.example']) { assert.throws(() => assertPublicVerification(manifest, {...report, api_origin}, name, clock), /Wrong verification API origin/) } }) } test('accepts complete verification begun after all runtime changes with either completion timestamp field', () => { const {manifest, report} = publicationFixture() assert.doesNotThrow(() => verifyPublication(manifest, report)) const legacyCompletion = {...report, time: report.checked_at, base: report.origin + '/api/v1'} delete legacyCompletion.checked_at delete legacyCompletion.origin assert.doesNotThrow(() => verifyPublication(manifest, legacyCompletion)) }) test('rejects checks begun before initial, API or UI activation even when completed afterward', () => { const {manifest, report} = publicationFixture() for (const field of ['activated_at', 'api_activated_at', 'frontend_activated_at']) { const start = new Date(Date.parse(manifest[field]) - 1).toISOString() assert.throws(() => verifyPublication(manifest, {...report, started_at: start}), /started before this runtime/) } // Building a new image does not mean it has replaced the served frontend. assert.throws(() => verifyPublication(manifest, {...report, started_at: '2026-09-19T15:20:00.000Z'}), /started before this runtime/) }) test('initial activation needs no fabricated API or UI refresh timestamps', () => { const {manifest, report} = publicationFixture() const initial = {url: manifest.url, activated_at: manifest.activated_at} assert.doesNotThrow(() => verifyPublication(initial, report)) assert.throws(() => verifyPublication({...initial, previous_apis: [{}]}, report), /Missing API/) assert.throws(() => verifyPublication({...initial, previous_frontends: [{}]}, report), /Invalid publication timestamp/) }) test('requires actual UI activation after every frontend rebuild', () => { const {manifest, report} = publicationFixture() const missingActivation = {...manifest} delete missingActivation.frontend_activated_at assert.throws(() => verifyPublication(missingActivation, report), /frontend_activated_at/) const missingBuild = {...manifest} delete missingBuild.frontend_built_at assert.throws(() => verifyPublication(missingBuild, report), /frontend_built_at/) assert.throws(() => verifyPublication({...manifest, frontend_activated_at: '2026-09-19T15:00:00.000Z'}, report), /activation predates its build/) }) test('fails closed for every invalid manifest timestamp instead of comparing against NaN', () => { const {manifest, report} = publicationFixture() const invalid = [undefined, null, '', false, 0, 'invalid', '2026-02-30T00:00:00.000Z', '2026-09-20T00:00:00.000Z'] for (const field of ['activated_at', 'api_activated_at', 'frontend_built_at', 'frontend_activated_at']) { for (const value of invalid) { assert.throws(() => verifyPublication({...manifest, [field]: value}, report), /Invalid publication timestamp/) } } assert.throws(() => verifyPublication({url: manifest.url}, report), /activated_at/) assert.throws(() => verifyPublication({...manifest, api_activated_at: '2026-09-19T13:00:00.000Z'}, report), /predates activation/) }) test('rejects missing, invalid, future and reversed report timing rather than using completion as start', () => { const {manifest, report} = publicationFixture() for (const field of ['started_at', 'checked_at']) { for (const value of [undefined, null, '', false, 0, 'invalid', '2026-02-30T00:00:00.000Z', '2026-09-20T00:00:00.000Z']) { assert.throws(() => verifyPublication(manifest, {...report, [field]: value}), /Invalid publication timestamp/) } } assert.throws(() => verifyPublication(manifest, {...report, checked_at: '2026-09-19T15:22:30.000Z'}), /finished before it started/) }) test('rejects truthy pass flags, empty checks, individual failures and a different origin', () => { const {manifest, report} = publicationFixture() for (const change of [{passed: 'true'}, {checks: []}, {checks: [{passed: false}]}, {checks: [{passed: 'true'}]}, {failures: ['cleanup failed']}, {failures: undefined}]) { assert.throws(() => verifyPublication(manifest, {...report, ...change}), /did not pass/) } assert.throws(() => verifyPublication(manifest, {...report, origin: 'http://127.0.0.1:18088'}), /Wrong verification origin/) }) test('rejects failed, malformed or contradictory cleanup results even when the top-level report passed', () => { const {manifest, report} = publicationFixture() for (const cleanup of [undefined, null, {}, false, 'passed', [], [null], [true], [{name: 'knowledge fixture', passed: false}], [{name: 'knowledge fixture', passed: 'true'}], [{name: '', passed: true}], [{passed: true}], [{name: 'knowledge fixture', passed: true, error: 'cleanup failed'}]]) { assert.throws(() => verifyPublication(manifest, {...report, cleanup}), /cleanup did not pass/) } assert.doesNotThrow(() => verifyPublication(manifest, {...report, cleanup: [{name: 'knowledge fixture', passed: true}]})) }) function reconciliationFixture() { const {manifest, report} = publicationFixture() Object.assign(manifest, {release: 'public-20260919-223000', stage: 'origin-ready', frontend_built_at: '2026-09-19T16:50:23.481Z', frontend_activated_at: '2026-09-19T16:50:27.512Z'}) const reports = Object.fromEntries(publicVerificationReports.map((name, index) => [name, {...structuredClone(report), started_at: `2026-09-19T17:0${index}:00.000Z`, checked_at: `2026-09-19T17:0${index}:30.000Z` }])) reports['public-resource-files'].prefix = 'file-isolation-1758300000000' const indexed = reports['public-indexed-retrieval-isolation'] indexed.fixtures = {kbs: ['00000000-0000-4000-8000-000000000001']} indexed.cleanup = indexed.fixtures.kbs.map(id => ({name: `knowledge ${id}`, passed: true})) const reconciliation = {release: manifest.release, origin: manifest.url, read_only: true, checked_at: '2026-09-19T17:07:00.000Z', passed: true, failures: [], reports: Object.fromEntries(publicVerificationReports.map(name => [name, { started_at: reports[name].started_at, completed_at: reports[name].checked_at, }])), checks: [...fixtureReconciliationCounts.map(name => ({name, count: 0, passed: true})), { name: 'file_fixture_directory_removed', passed: true, path: path.resolve(__dirname, '../../acceptance/files/10059/exports/file-isolation-1758300000000'), }]} return {manifest, reports, reconciliation} } const invalidIndexedCleanup = [ ['missing cleanup', report => {delete report.cleanup}, /Incomplete indexed knowledge cleanup/], ['empty cleanup', report => {report.cleanup = []}, /cleanup did not pass/], ['only account cleanup', report => {report.cleanup = [{name: 'user fixture', passed: true}]}, /Incomplete indexed knowledge cleanup/], ['mismatched knowledge cleanup', report => {report.cleanup[0].name = 'knowledge 00000000-0000-4000-8000-000000000002'}, /Incomplete indexed knowledge cleanup/], ['duplicate knowledge cleanup', report => {report.cleanup.push({...report.cleanup[0]})}, /Incomplete indexed knowledge cleanup/], ['unmatched extra knowledge cleanup', report => {report.cleanup.push({name: 'knowledge 00000000-0000-4000-8000-000000000002', passed: true})}, /Incomplete indexed knowledge cleanup/], ['second knowledge fixture without cleanup', report => {report.fixtures.kbs.push('00000000-0000-4000-8000-000000000002')}, /Incomplete indexed knowledge cleanup/], ['failed knowledge cleanup', report => {report.cleanup[0].passed = false}, /cleanup did not pass/], ['missing fixtures', report => {delete report.fixtures}, /Invalid indexed knowledge fixtures/], ['missing knowledge fixtures', report => {delete report.fixtures.kbs}, /Invalid indexed knowledge fixtures/], ['empty knowledge fixtures', report => {report.fixtures.kbs = []}, /Invalid indexed knowledge fixtures/], ['invalid knowledge fixture', report => {report.fixtures.kbs = ['fixture']; report.cleanup[0].name = 'knowledge fixture'}, /Invalid indexed knowledge fixtures/], ['duplicate knowledge fixtures', report => {report.fixtures.kbs.push(report.fixtures.kbs[0])}, /Invalid indexed knowledge fixtures/], ] for (const [label, mutate, pattern] of invalidIndexedCleanup) { test(`blocks final publication for indexed retrieval with ${label}`, async () => { const value = reconciliationFixture() mutate(value.reports['public-indexed-retrieval-isolation']) assert.throws(() => assertFixtureReconciliation(value.manifest, value.reconciliation, value.reports, clock), pattern) const publisher = injectedPublisher(value) await assert.rejects(publisher.publish(), pattern) assert.deepEqual(publisher.writes, []) }) } test('indexed retrieval accepts every knowledge cleanup alongside account and role cleanup', () => { const {manifest, reports, reconciliation} = reconciliationFixture() const indexed = reports['public-indexed-retrieval-isolation'] indexed.fixtures.kbs.push('00000000-0000-4000-8000-000000000002') indexed.cleanup.push({name: `knowledge ${indexed.fixtures.kbs[1]}`, passed: true}, {name: 'user fixture', passed: true}, {name: 'role fixture', passed: true}) assert.doesNotThrow(() => assertFixtureReconciliation(manifest, reconciliation, reports, clock)) }) test('accepts complete zero-residue reconciliation tied to all seven reports after the latest activation', () => { const {manifest, reports, reconciliation} = reconciliationFixture() assert.doesNotThrow(() => assertFixtureReconciliation(manifest, reconciliation, reports, clock)) const indexed = reports['public-indexed-retrieval-isolation'] indexed.time = indexed.checked_at delete indexed.checked_at assert.doesNotThrow(() => assertFixtureReconciliation(manifest, reconciliation, reports, clock)) }) for (const name of publicVerificationReports) { test(`rejects reconciliation that refers to a previous execution of ${name}`, () => { for (const field of ['started_at', 'completed_at']) { const {manifest, reports, reconciliation} = reconciliationFixture() reconciliation.reports[name][field] = '2026-09-19T16:55:00.000Z' assert.throws(() => assertFixtureReconciliation(manifest, reconciliation, reports, clock), /does not match current report/) } }) test(`rejects ${name} started before the latest activation even with matching reconciliation metadata`, () => { const {manifest, reports, reconciliation} = reconciliationFixture() reports[name].started_at = '2026-09-19T16:50:27.511Z' reconciliation.reports[name].started_at = reports[name].started_at assert.throws(() => assertFixtureReconciliation(manifest, reconciliation, reports, clock), /started before this runtime/) }) } for (const [label, mutate, pattern] of [ ['different release', value => {value.reconciliation.release = 'public-20260919-000000'}, /identity/], ['different origin', value => {value.reconciliation.origin = 'http://127.0.0.1:18088'}, /identity/], ['non-read-only result', value => {value.reconciliation.read_only = false}, /identity/], ['failed result', value => {value.reconciliation.passed = false}, /did not pass/], ['reported failure', value => {value.reconciliation.failures.push('residual rows')}, /did not pass/], ['future check', value => {value.reconciliation.checked_at = '2026-09-20T00:00:00.000Z'}, /Invalid publication timestamp/], ['missing check time', value => {delete value.reconciliation.checked_at}, /Invalid publication timestamp/], ['check before final source completes', value => {value.reconciliation.checked_at = '2026-09-19T17:06:29.999Z'}, /predates source report/], ['missing source metadata', value => {delete value.reconciliation.reports['public-navigation']}, /all seven/], ['renamed source metadata', value => {value.reconciliation.reports.wrong = value.reconciliation.reports['public-navigation']; delete value.reconciliation.reports['public-navigation']}, /does not match/], ['extra source metadata', value => {value.reconciliation.reports.extra = {}}, /all seven/], ['missing source report', value => {delete value.reports['public-navigation']}, /did not pass/], ['failed source report', value => {value.reports['public-navigation'].passed = false}, /did not pass/], ['failed source cleanup', value => {value.reports['public-indexed-retrieval-isolation'].cleanup[0].passed = false}, /cleanup did not pass/], ['missing residual check', value => {value.reconciliation.checks.pop()}, /missing required residual checks/], ['duplicate residual check', value => {value.reconciliation.checks[1] = value.reconciliation.checks[0]}, /missing required residual checks/], ['unknown residual check', value => {value.reconciliation.checks[0].name = 'unrelated'}, /missing required residual checks/], ['invalid numeric count', value => {value.reconciliation.checks[0].count = '0'}, /residual rows/], ['positive count with passed true', value => {value.reconciliation.checks[0].count = 1}, /residual rows/], ['missing count', value => {delete value.reconciliation.checks[0].count}, /residual rows/], ['wrong directory', value => {value.reconciliation.checks.at(-1).path = '/unrelated/path'}, /wrong attachment directory/], ['missing directory', value => {delete value.reconciliation.checks.at(-1).path}, /wrong attachment directory/], ['unsafe file prefix', value => {value.reports['public-resource-files'].prefix = '../../private'}, /wrong attachment directory/], ]) { test(`blocks publication for ${label}`, () => { const value = reconciliationFixture() mutate(value) assert.throws(() => assertFixtureReconciliation(value.manifest, value.reconciliation, value.reports, clock), pattern) }) } function injectedPublisher(value, missingReconciliation = false) { const writes = [], reads = [] const module = {exports: {}} const injectedRequire = name => { if (name === 'node:fs') return { readFileSync: file => { reads.push(path.basename(file)) if (file.endsWith('/manifest.json')) return JSON.stringify(value.manifest) if (file.endsWith('/public-fixture-reconciliation.json')) { if (missingReconciliation) throw new Error('Missing reconciliation file') return JSON.stringify(value.reconciliation) } const report = value.reports[path.basename(file, '.json')] assert.ok(report, 'Unexpected file read') return JSON.stringify(report) }, writeFileSync: (file, contents) => writes.push({file, value: JSON.parse(contents)}), } if (name === 'node:child_process') return {execFileSync: () => assert.fail('External command forbidden')} return require(name) } class FrozenDate extends Date { constructor(...args) { super(...(args.length ? args : [clock])) } static now() { return clock } } const context = {require: injectedRequire, module, __dirname, URL, AbortSignal, Date: FrozenDate, fetch: async () => ({ok: true, json: async () => ({release: value.manifest.release})}), console: {log() {}}} vm.runInNewContext(fs.readFileSync(path.join(__dirname, 'publish_public_runtime.cjs'), 'utf8') + '\n;globalThis.publish = markPublished;', context) return {writes, reads, publish: () => context.publish(value.manifest.release)} } test('mark-published cannot write either manifest when reconciliation is absent or failed', async () => { for (const absent of [true, false]) { const value = reconciliationFixture() value.reconciliation.passed = false const publisher = injectedPublisher(value, absent) await assert.rejects(publisher.publish(), /Missing reconciliation file|did not pass/) assert.deepEqual(publisher.writes, []) assert.ok(publisher.reads.includes('public-fixture-reconciliation.json')) } }) test('mark-published persists only after current reports and their final reconciliation pass', async () => { const value = reconciliationFixture() const publisher = injectedPublisher(value) await publisher.publish() assert.equal(publisher.writes.length, 2) assert.ok(publisher.reads.includes('public-fixture-reconciliation.json')) for (const write of publisher.writes) { assert.equal(write.value.stage, 'published') assert.equal(write.value.fixture_reconciliation_checked_at, value.reconciliation.checked_at) assert.deepEqual(write.value.public_verification_reports, publicVerificationReports) } }) test('every required producer captures execution start before requests and writes it in its report', () => { for (const name of ['verify_public_release', 'verify_navigation_parity', 'verify_access_control', 'verify_resource_isolation_live', 'verify_resource_files_live', 'verify_public_tenant_isolation', 'verify_indexed_retrieval_isolation']) { const source = fs.readFileSync(path.join(__dirname, `${name}.cjs`), 'utf8') const start = source.indexOf('const startedAt = new Date().toISOString()') assert.ok(start >= 0 && start < source.indexOf('fetch('), `${name}: capture start before requests`) assert.match(source, /started_at:\s*startedAt/, `${name}: persist captured start`) } })