91 lines
5.8 KiB
JavaScript
91 lines
5.8 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const crypto = require('node:crypto');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
const { parseKstuffRouteSelectionSnapshot } = require('../../src/services/ps5-fpkg-route-selection-trace');
|
|
|
|
const sha = value => crypto.createHash('sha256').update(value).digest('hex');
|
|
const lines = sample => [
|
|
'schema=chimera.p15-a7-route-selection-metrics.v1', 'status=attached', `sample=${sample}`,
|
|
'route nmount_dispatch=0 nmount_trap=0 nmount_emu=0',
|
|
'dbgarm attempt=0 read_fail=0 pcb_ptr_fail=0 pcb_state_fail=0 stack_fail=0 pcb_set_fail=0 write_fail=0 armed=0 rollback_restore_fail=0 finish=0 finish_restore_fail=0',
|
|
'mailbox total=0 fself=0 fpkg=0 npdrm=0 unhandled=0', 'fpkg verify=0 verify_emu=0', '',
|
|
].join('\n');
|
|
|
|
test('A7 active preflight embeds the same strict semantic parser used by the product', async () => {
|
|
const mod = await import('../../scripts/autonomous/p15-a7-active-preflight.mjs');
|
|
const runtimeFingerprint = 'a'.repeat(64);
|
|
const options = { sequence: 7, sampledAt: 1234, runtimeFingerprint };
|
|
assert.deepEqual(
|
|
mod.parseEmbeddedKstuffRouteSelectionSnapshot(lines(7), options),
|
|
parseKstuffRouteSelectionSnapshot(lines(7), options),
|
|
);
|
|
const unsafe = `${lines(7)}unexpected=raw-kernel-data\n`;
|
|
assert.throws(() => mod.parseEmbeddedKstuffRouteSelectionSnapshot(unsafe, options), {
|
|
code: 'PS5_FPKG_ROUTE_SELECTION_TRACE_UNSAFE_LINE',
|
|
});
|
|
});
|
|
|
|
// PS5Upload's identity must remain independent of kstuff execution identity.
|
|
for (const payloadIdentityCurrentBootExact of [false, true]) {
|
|
test(`A7 file hashes and advancing counters cannot attest kstuff execution (management payload attested: ${payloadIdentityCurrentBootExact})`, async t => {
|
|
const mod = await import('../../scripts/autonomous/p15-a7-active-preflight.mjs');
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-a7-active-'));
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
const manifest = Buffer.from(`\n\npldmgr_v0.4.2.elf\n${mod.EXPECTED.loaderName}\n!30000\n${mod.EXPECTED.readerName}\n!5000\netaHEN-2.6B.bin\nftpsrv.elf\nnanodns.elf\n`);
|
|
assert.equal(sha(manifest), mod.EXPECTED.manifestSha256);
|
|
const loader = Buffer.alloc(mod.EXPECTED.loaderSize); const reader = Buffer.alloc(mod.EXPECTED.readerSize);
|
|
const reads = new Map([
|
|
[`${mod.REMOTE_DIR}/autoload.txt`, manifest], [`${mod.REMOTE_DIR}/${mod.EXPECTED.loaderName}`, loader],
|
|
[`${mod.REMOTE_DIR}/${mod.EXPECTED.readerName}`, reader], [mod.METRICS_PATH, Buffer.from(lines(4))],
|
|
]);
|
|
// Matching file bytes do not prove which kstuff runtime executed this boot.
|
|
const expected = { ...mod.EXPECTED, loaderSha256: sha(loader), readerSha256: sha(reader) };
|
|
let metricsRead = 0;
|
|
const result = await mod.qualifyActiveRuntime({
|
|
ftp: {
|
|
list: async () => ['autoload.txt', mod.EXPECTED.loaderName, mod.EXPECTED.readerName, mod.EXPECTED.currentLoaderName, mod.EXPECTED.currentReaderName].map(name => ({ name })),
|
|
download: async (source, target) => { const bytes = source === mod.METRICS_PATH ? Buffer.from(lines(++metricsRead + 3)) : reads.get(source); fs.writeFileSync(target, bytes); },
|
|
},
|
|
parseSnapshot: parseKstuffRouteSelectionSnapshot,
|
|
managementSnapshot: async () => ({ engineExact: true, managementReady: true, processCoverageComplete: true, foregroundClean: true, payloadIdentityCurrentBootExact }),
|
|
wait: async () => {}, now: (() => { let value = 1000; return () => value += 11000; })(), temporaryRoot: root, expected,
|
|
});
|
|
assert.equal(result.status, 'blocked');
|
|
assert.equal(result.activeRuntimeExact, false);
|
|
assert.equal(result.activeTransitionProven, false);
|
|
assert.equal(result.runtime.identityStatus, 'unproven');
|
|
assert.equal(result.runtime.traceEligible, false);
|
|
assert.equal(result.runtime.identitySource, 'expected-build-inputs');
|
|
assert.equal(result.evidenceContract.status, 'unavailable');
|
|
assert.equal(result.evidenceContract.reason, 'kstuff_current_boot_execution_receipt_unavailable');
|
|
assert.equal(result.autoload.loaderSha256, sha(loader));
|
|
assert.equal(result.autoload.readerSha256, sha(reader));
|
|
assert.equal(result.autoload.manifestSha256, sha(manifest));
|
|
assert.equal(result.premetrics.continuous, true);
|
|
assert.equal(result.launchEligible, false);
|
|
assert.equal(result.launchRequests, 0);
|
|
assert.equal(result.payloadLoadPerformed, false);
|
|
assert.equal(result.consoleMutationPerformed, false);
|
|
});
|
|
}
|
|
|
|
test('A7 active preflight fails closed on stale semantic samples', async t => {
|
|
const mod = await import('../../scripts/autonomous/p15-a7-active-preflight.mjs');
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-a7-stale-'));
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
const manifest = Buffer.from(`\n\npldmgr_v0.4.2.elf\n${mod.EXPECTED.loaderName}\n!30000\n${mod.EXPECTED.readerName}\n!5000\netaHEN-2.6B.bin\nftpsrv.elf\nnanodns.elf\n`);
|
|
const loader = Buffer.alloc(mod.EXPECTED.loaderSize); const reader = Buffer.alloc(mod.EXPECTED.readerSize);
|
|
const expected = { ...mod.EXPECTED, loaderSha256: sha(loader), readerSha256: sha(reader) };
|
|
await assert.rejects(mod.qualifyActiveRuntime({
|
|
ftp: {
|
|
list: async () => ['autoload.txt', mod.EXPECTED.loaderName, mod.EXPECTED.readerName, mod.EXPECTED.currentLoaderName, mod.EXPECTED.currentReaderName].map(name => ({ name })),
|
|
download: async (source, target) => fs.writeFileSync(target, source.endsWith('autoload.txt') ? manifest : (source === mod.METRICS_PATH ? Buffer.from(lines(8)) : source.endsWith(mod.EXPECTED.loaderName) ? loader : reader)),
|
|
}, parseSnapshot: parseKstuffRouteSelectionSnapshot, managementSnapshot: async () => ({}), wait: async () => {}, temporaryRoot: root, expected,
|
|
}), { code: 'P15_A7_ACTIVE_CONTINUITY' });
|
|
});
|