Files
chimera-Public/test/server/ch-1401-p15-a8-distinct-control-package.test.js

262 lines
16 KiB
JavaScript

'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const test = require('node:test');
const { A8_DISTINCT_CONTROL } = require('../../src/services/ps5-native-pkg-builder-provider');
const { createPs5FpkgDistinctControlPackageService } = require('../../src/services/ps5-fpkg-distinct-control-package-service');
const { assessPs5FpkgControlMetadata } = require('../../src/services/ps5-fpkg-control-metadata-assessment');
const { validatePs5NativePackageManifest } = require('../../src/services/ps5-native-package-registration-service');
test('repository distribution contains the exact frozen canonical artifact and Docker copies it', () => {
const artifact = path.join('assets', 'ps5-controls', 'a9', A8_DISTINCT_CONTROL.selectedArtifact.filename);
assert.equal(fs.statSync(artifact).size, A8_DISTINCT_CONTROL.selectedArtifact.size);
const sha256 = require('node:crypto').createHash('sha256').update(fs.readFileSync(artifact)).digest('hex');
assert.equal(sha256, A8_DISTINCT_CONTROL.selectedArtifact.sha256);
const docker = fs.readFileSync('Dockerfile', 'utf8');
assert.match(docker, /COPY --chown=chimera:chimera assets \.\/assets/);
assert.match(docker, new RegExp(A8_DISTINCT_CONTROL.selectedArtifact.sha256));
assert.match(docker, /chmod 0444 .*\/app\/assets\/ps5-controls\/a9/);
});
function fixture({ registrar, assessMetadata } = {}) {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-a8-distinct-control-'));
const registrations = [];
let builds = 0;
let validations = 0;
const builder = {
async buildDistinctControl({ outputPath }) {
builds += 1;
fs.writeFileSync(outputPath, Buffer.from(`fixed-identity-randomized-artifact-${builds}`), { flag: 'wx' });
return { provider: { product: 'LibProsperoPkg', version: '2.6.0', revision: A8_DISTINCT_CONTROL.upstreamRevision, abi: 'chimera-prospero-bridge-v4', patched: false }, report: { fixedIdentity: true, licenseFree: true } };
},
async validatePackage() { validations += 1; return { accepted: true, checks: [{ name: 'Finalized image', status: 0 }] }; },
async inspectPackage() { return { type: 'FullDebug', contentId: A8_DISTINCT_CONTROL.contentId }; },
};
const service = createPs5FpkgDistinctControlPackageService({
outputRoot: path.join(root, 'vault'), stateFile: path.join(root, 'state.json'), builder,
assessMetadata: assessMetadata || (() => ({ qualified: true, status: 'metadata_qualified', issues: [] })),
registrar: registrar || (async manifest => { registrations.push(manifest); return { packageSetId: 71, titleId: 72 }; }),
});
return { root, registrations, service, builds: () => builds, validations: () => validations };
}
test('builds, validates, freezes and registers one exact distinct-title control artifact', async t => {
const f = fixture(); t.after(() => fs.rmSync(f.root, { recursive: true, force: true }));
const ready = await f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') });
assert.equal(ready.status, 'ready');
assert.equal(ready.titleId, A8_DISTINCT_CONTROL.titleId);
assert.equal(ready.contentId, A8_DISTINCT_CONTROL.contentId);
assert.equal(ready.artifactVerified, true);
assert.equal(ready.installAuthorized, false);
assert.equal(ready.installed, false);
assert.equal(ready.launchVerified, false);
assert.equal(ready.productionRestorable, false);
assert.equal(f.builds(), 1);
assert.equal(f.registrations[0].controlProfile, A8_DISTINCT_CONTROL.controlProfile);
assert.equal(f.registrations[0].packageFormat.licenseFree, true);
assert.equal(f.registrations[0].components[0].structuralValidation.status, 'accepted');
assert.equal(f.registrations[0].components[0].structuralValidation.upstream.accepted, true);
assert.equal(f.registrations[0].components[0].metadataQualification.status, 'accepted');
assert.deepEqual(f.registrations[0].components[0].structuralValidation.upstream.checks, [{ name: 'Finalized image', status: 0 }]);
assert.equal(f.registrations[0].evidence.immutableArtifact.sha256, ready.sha256);
assert.equal(f.registrations[0].evidence.immutableArtifact.rebuildSubstitutionAllowed, false);
assert.equal((await f.service.buildAndRegister({ sourcePath: 'ignored-after-ready' })).sha256, ready.sha256);
assert.equal(f.builds(), 1);
assert.equal(f.validations(), 1);
});
test('retains built_verified state when registration fails and retries without rebuilding', async t => {
let attempts = 0;
const f = fixture({ registrar: async () => {
attempts += 1;
if (attempts === 1) throw Object.assign(new Error('database unavailable'), { code: 'TEST_REGISTRATION' });
return { packageSetId: 81, titleId: 82 };
} });
t.after(() => fs.rmSync(f.root, { recursive: true, force: true }));
await assert.rejects(f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') }), /database unavailable/);
assert.equal(f.service.status().status, 'built_verified');
const ready = await f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') });
assert.equal(ready.status, 'ready');
assert.equal(f.builds(), 1);
assert.equal(attempts, 2);
assert.equal(f.validations(), 2);
});
test('fails closed when the selected artifact drifts or an unmanaged target already exists', async t => {
const f = fixture(); t.after(() => fs.rmSync(f.root, { recursive: true, force: true }));
await f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') });
fs.appendFileSync(f.service.targetPath(), 'drift');
assert.equal(f.service.status().status, 'artifact_drift');
await assert.rejects(f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') }), error => error.code === 'PS5_A8_CONTROL_ARTIFACT_DRIFT');
const other = fixture(); t.after(() => fs.rmSync(other.root, { recursive: true, force: true }));
fs.mkdirSync(path.dirname(other.service.targetPath()), { recursive: true });
fs.writeFileSync(other.service.targetPath(), 'unmanaged');
await assert.rejects(other.service.buildAndRegister({ sourcePath: path.join(other.root, 'source') }), error => error.code === 'PS5_A8_CONTROL_UNOWNED_ARTIFACT');
});
test('keeps an exact artifact distinct from a metadata assessment failure', async t => {
let parserFails = false;
const f = fixture({
assessMetadata: () => {
if (parserFails) throw Object.assign(new Error('host parser details'), { code: 'PS5_FPKG_METADATA_CONTAINER_INVALID' });
return { qualified: true, status: 'metadata_qualified', issues: [] };
},
});
t.after(() => fs.rmSync(f.root, { recursive: true, force: true }));
await f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') });
parserFails = true;
const state = f.service.status();
assert.equal(state.status, 'metadata_rejected');
assert.equal(state.artifactVerified, true);
assert.equal(state.metadataQualified, false);
await assert.rejects(
f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') }),
error => error.code === 'PS5_A8_CONTROL_METADATA_UNQUALIFIED'
&& error.details.status === 'metadata_rejected'
&& error.details.issues[0].actual === 'PS5_FPKG_METADATA_CONTAINER_INVALID'
&& !JSON.stringify(error.details).includes('host parser details'),
);
});
test('fails closed on corrupt durable state without replacing its evidence', async t => {
const f = fixture(); t.after(() => fs.rmSync(f.root, { recursive: true, force: true }));
const statePath = path.join(f.root, 'state.json');
fs.writeFileSync(statePath, '{invalid-json', 'utf8');
assert.throws(() => f.service.status(), error => error.code === 'PS5_A8_CONTROL_STATE_CORRUPT');
await assert.rejects(f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') }), error => error.code === 'PS5_A8_CONTROL_STATE_CORRUPT');
assert.equal(fs.readFileSync(statePath, 'utf8'), '{invalid-json');
assert.equal(f.builds(), 0);
});
test('rejects a concurrent materialization before a second build can start', async t => {
let releaseRegistration;
let registrationStarted;
const started = new Promise(resolve => { registrationStarted = resolve; });
const f = fixture({ registrar: async () => {
registrationStarted();
await new Promise(resolve => { releaseRegistration = resolve; });
return { packageSetId: 83, titleId: 84 };
} });
t.after(() => fs.rmSync(f.root, { recursive: true, force: true }));
const first = f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') });
await started;
await assert.rejects(f.service.buildAndRegister({ sourcePath: path.join(f.root, 'source') }), error => error.code === 'PS5_A8_CONTROL_BUSY');
assert.equal(f.builds(), 1);
releaseRegistration();
assert.equal((await first).status, 'ready');
});
test('production preparation copies and registers only the exact frozen distribution bytes', async t => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-a8-selected-control-'));
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
const selectedPath = path.join(root, 'selected.pkg');
const bytes = Buffer.from('frozen-distribution-control');
fs.writeFileSync(selectedPath, bytes);
const sha256 = require('node:crypto').createHash('sha256').update(bytes).digest('hex');
let builds = 0;
const service = createPs5FpkgDistinctControlPackageService({
outputRoot: path.join(root, 'vault'), stateFile: path.join(root, 'state.json'), selectedArtifactPath: selectedPath,
descriptor: { ...A8_DISTINCT_CONTROL, selectedArtifact: { filename: 'selected.pkg', size: bytes.length, sha256 } },
builder: {
async buildDistinctControl() { builds += 1; throw new Error('must not rebuild selected artifact'); },
async probe() { return { product: 'LibProsperoPkg', version: '2.6.0', revision: A8_DISTINCT_CONTROL.upstreamRevision, abi: 'chimera-prospero-bridge-v4', patched: false, pinned: true, clean: true, controlAvailable: true }; },
async validatePackage() { return { accepted: true }; },
async inspectPackage() { return { type: 'FullDebug', contentId: A8_DISTINCT_CONTROL.contentId }; },
},
assessMetadata: () => ({ qualified: true, status: 'metadata_qualified', issues: [] }),
registrar: async manifest => {
assert.equal(manifest.components[0].sha256, sha256);
return { packageSetId: 91, titleId: 92 };
},
});
const ready = await service.prepareSelectedAndRegister();
assert.equal(ready.status, 'ready');
assert.equal(ready.artifactSelection, 'frozen-distribution-artifact');
assert.equal(ready.sha256, sha256);
assert.deepEqual(fs.readFileSync(service.targetPath()), bytes);
assert.equal(builds, 0);
});
test('frozen canonical control carries structural and metadata qualification into registration', async t => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-a8-registration-boundary-'));
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
const outputRoot = path.join(root, 'vault');
const selectedArtifactPath = path.resolve('assets', 'ps5-controls', 'a9', A8_DISTINCT_CONTROL.selectedArtifact.filename);
let registeredManifest = null;
const service = createPs5FpkgDistinctControlPackageService({
outputRoot,
stateFile: path.join(root, 'state.json'),
selectedArtifactPath,
builder: {
async buildDistinctControl() { throw new Error('production must not rebuild the frozen artifact'); },
async probe() { return { product: 'LibProsperoPkg', version: '2.6.0', revision: A8_DISTINCT_CONTROL.upstreamRevision, abi: 'chimera-prospero-bridge-v4', patched: false, pinned: true, clean: true, controlAvailable: true }; },
async validatePackage() { return { accepted: true, checks: [{ name: 'Finalized image', status: 0 }] }; },
async inspectPackage() { return { type: 'FullDebug', contentId: A8_DISTINCT_CONTROL.contentId }; },
},
assessMetadata: sourcePath => assessPs5FpkgControlMetadata({
sourcePath,
expected: { titleId: A8_DISTINCT_CONTROL.titleId, contentId: A8_DISTINCT_CONTROL.contentId },
}),
registrar: async manifest => {
validatePs5NativePackageManifest(manifest, { outputRoot, verifyArtifacts: true });
registeredManifest = manifest;
return { packageSetId: 93, titleId: 94 };
},
});
const ready = await service.prepareSelectedAndRegister();
assert.equal(ready.status, 'ready');
assert.equal(ready.metadataQualified, true);
assert.equal(registeredManifest.controlProfile, A8_DISTINCT_CONTROL.controlProfile);
assert.equal(registeredManifest.components[0].structuralValidation.upstream.accepted, true);
assert.equal(registeredManifest.components[0].metadataQualification.assessment.status, 'metadata_qualified');
assert.equal(registeredManifest.components[0].metadataQualification.assessment.metadata.contentVersion, '01.000.000');
});
test('production registry keeps preparation separate from the single-use exact-confirmed control install gate', () => {
const registry = fs.readFileSync('src/server/create-registry.js', 'utf8');
assert.match(registry, /ps5-native-packages:a8-distinct-control-status[\s\S]*classification: 'read-only'/);
assert.match(registry, /ps5-native-packages:a8-distinct-control-prepare[\s\S]*classification: 'mutating'/);
assert.match(registry, /prepareSelectedAndRegister\(\)/);
assert.doesNotMatch(registry, /a8-distinct-control-build/);
assert.match(registry, /a8-distinct-control-install-plan[\s\S]*classification: 'mutating'/);
assert.match(registry, /CONFIRMATION: A8_CONTROL_INSTALL_CONFIRMATION/);
assert.match(registry, /a8-distinct-control-install[\s\S]*classification: 'destructive'[\s\S]*confirmation: A8_CONTROL_INSTALL_CONFIRMATION/);
assert.match(registry, /performConsoleScan\(A8_CONTROL_INSTALL_ROOTS\)/);
assert.match(registry, /ps5FpkgDistinctControlInstallGate\.plan\(context\.session\?\.id\)/);
assert.match(registry, /ps5FpkgDistinctControlInstallGate\.start\(input, context\.session\?\.id\)/);
assert.match(registry, /PS5_A8_CONTROL_INSTALL_GATE_REQUIRED/g);
});
test('server and desktop UI expose preflight, exact install, independent scan and launch qualification', () => {
const preload = fs.readFileSync('preload.js', 'utf8');
const web = fs.readFileSync('renderer/pork-web-shim.js', 'utf8');
const main = fs.readFileSync('main.js', 'utf8');
const modal = fs.readFileSync('renderer/modules/modal.js', 'utf8');
const surface = `${fs.readFileSync('renderer/index.html', 'utf8')}\n${modal}`;
for (const source of [preload, web]) assert.match(source, /ps5A8DistinctControl/);
assert.match(main, /PS5_A8_CONTROL_SERVER_REQUIRED/);
assert.match(surface, /ps5-a8-control-prepare/);
assert.match(modal, /ps5A8DistinctControl\('prepare'\)/);
assert.match(surface, /ps5-a8-control-preflight/);
assert.match(modal, /ps5A8DistinctControl\('install-plan'\)/);
assert.match(modal, /ps5A8DistinctControl\('install'/);
assert.match(modal, /ps5A8Control\('trust'\)\.removeAttribute\('data-i18n'\)/);
assert.match(modal, /ps5A8Control\('status'\)\.removeAttribute\('data-i18n'\)/);
assert.match(modal, /ps5NativePackageRestoreVerify\(\{ titleId: 'CHIM00002'/);
assert.match(modal, /ps5NativePackageRestoreLaunchPlan\(ps5A8ControlOperationId\)/);
assert.match(modal, /Number\(item\.packageSetId\) === Number\(a8Control\.packageSetId\)/);
assert.match(modal, /item\.components\[0\]\?\.sha256 === a8Control\.sha256/);
for (const locale of ['en', 'nl']) {
const catalog = JSON.parse(fs.readFileSync(`build/lang/${locale}.json`, 'utf8'));
assert.equal(typeof catalog.strings?.['ps5NativePackages.a8Control.ready'], 'string');
for (const key of ['preflight', 'install', 'verify', 'launch', 'confirm', 'boundary']) {
assert.equal(typeof catalog.strings?.[`ps5NativePackages.a8Control.${key}`], 'string');
}
}
});