'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, PINNED_PS5_BUILDER, createPs5NativePkgBuilderProvider, } = require('../../src/services/ps5-native-pkg-builder-provider'); const CLEAN_CAPABILITIES = Object.freeze({ backupToDebugFpkg: true, dataDlcToDebugFpkg: true, updateToDebugFpkg: false, backupInspection: true, packageInspection: true, packageValidation: true, launchReadiness: true, licenseFreeBuild: false, distinctTitleControlBuild: true, finalizedFihOutput: true, }); function fixture() { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-clean-fpkg-builder-')); const toolRoot = path.join(root, 'tool'); const sourceRoot = path.join(root, 'source'); const workRoot = path.join(root, 'work'); fs.mkdirSync(toolRoot, { recursive: true }); fs.mkdirSync(path.join(sourceRoot, 'sce_sys'), { recursive: true }); fs.mkdirSync(workRoot, { recursive: true }); fs.writeFileSync(path.join(sourceRoot, 'sce_sys', 'param.json'), '{}'); fs.writeFileSync(path.join(sourceRoot, 'eboot.bin'), Buffer.from([0x7f, 0x45, 0x4c, 0x46])); const executable = path.join(toolRoot, PINNED_PS5_BUILDER.executable); fs.writeFileSync(executable, 'fixture'); return { root, toolRoot, sourceRoot, workRoot }; } function cleanProbe(overrides = {}) { return { product: 'LibProsperoPkg', version: '2.6.0', revision: '9084c0e88cd8d7cd9c0b353b8b6b89f7d1cc4275', abi: 'chimera-prospero-bridge-v4', patched: true, patch: 'chimera-stream-large-package-assembly-u2c24-v2', capabilities: CLEAN_CAPABILITIES, ...overrides, }; } test('production builder pin is the exact streaming semantic bridge-v4 baseline', () => { assert.equal(PINNED_PS5_BUILDER.abi, 'chimera-prospero-bridge-v4'); assert.equal(PINNED_PS5_BUILDER.version, '2.6.0'); assert.equal(PINNED_PS5_BUILDER.patched, true); assert.equal(PINNED_PS5_BUILDER.patch, 'chimera-stream-large-package-assembly-u2c24-v2'); assert.equal(PINNED_PS5_BUILDER.patchSha256, '65e04ca3462ef4e619d296d3656c3658a6083283102a38bfb69d095f369db135'); assert.equal('patchSet' in PINNED_PS5_BUILDER, false); }); test('probe recognizes the exact clean revision but blocks its unproven license-free converter', async t => { const f = fixture(); t.after(() => fs.rmSync(f.root, { recursive: true, force: true })); let report = cleanProbe(); const provider = createPs5NativePkgBuilderProvider({ toolRoot: f.toolRoot, allowedWorkRoots: [f.workRoot], allowedSourceRoots: [f.sourceRoot], runner: async () => ({ code: 0, output: JSON.stringify(report) }), }); let status = await provider.probe(); assert.equal(status.pinned, true); assert.equal(status.clean, true); assert.equal(status.available, false); assert.equal(status.controlAvailable, true); assert.equal(status.reason, 'capability-mismatch'); report = cleanProbe({ patch: 'unexpected-patch' }); assert.equal((await provider.probe()).available, false); report = cleanProbe({ revision: '0'.repeat(40) }); assert.equal((await provider.probe()).available, false); report = cleanProbe({ capabilities: { ...CLEAN_CAPABILITIES, licenseFreeBuild: true } }); status = await provider.probe(); assert.equal(status.available, true); }); test('distinct control build uses one fixed non-colliding identity and exact upstream assets', async t => { const f = fixture(); t.after(() => fs.rmSync(f.root, { recursive: true, force: true })); fs.writeFileSync(path.join(f.sourceRoot, 'eboot.bin'), Buffer.from('fixture-eboot')); fs.writeFileSync(path.join(f.sourceRoot, 'sce_sys', 'icon0.png'), Buffer.from('fixture-icon')); const descriptor = { ...A8_DISTINCT_CONTROL, assets: { ebootSha256: require('node:crypto').createHash('sha256').update('fixture-eboot').digest('hex'), iconSha256: require('node:crypto').createHash('sha256').update('fixture-icon').digest('hex'), }, }; const outputPath = path.join(f.workRoot, 'control.pkg'); const workPath = path.join(f.workRoot, 'control-work'); let request; const runner = async ({ args }) => { if (args[0] === 'probe') return { code: 0, output: JSON.stringify(cleanProbe()) }; assert.deepEqual(args.slice(0, 2), ['build-control', '--request']); request = JSON.parse(fs.readFileSync(args[2], 'utf8')); fs.writeFileSync(outputPath, Buffer.concat([Buffer.from([0x7f, 0x46, 0x49, 0x48]), Buffer.alloc(64)])); fs.writeFileSync(args[4], JSON.stringify({ ok: true, outputPath, licenseFree: true, fixedIdentity: true })); return { code: 0, output: '' }; }; const provider = createPs5NativePkgBuilderProvider({ toolRoot: f.toolRoot, allowedWorkRoots: [f.workRoot], allowedSourceRoots: [f.sourceRoot], runner, distinctControl: descriptor, }); const result = await provider.buildDistinctControl({ sourcePath: f.sourceRoot, outputPath, workPath }); assert.equal(request.abi, 'chimera-prospero-bridge-v4'); assert.equal(request.operation, 'build-control'); assert.equal(request.titleId, A8_DISTINCT_CONTROL.titleId); assert.equal(request.contentId, A8_DISTINCT_CONTROL.contentId); assert.equal(request.componentType, 'base'); assert.equal(request.sourceAssets.ebootSha256, descriptor.assets.ebootSha256); assert.equal(request.sourceAssets.iconSha256, descriptor.assets.iconSha256); assert.equal(result.report.licenseFree, true); }); test('distinct control build rejects source drift and caller-selected identity before the bridge', async t => { const f = fixture(); t.after(() => fs.rmSync(f.root, { recursive: true, force: true })); const provider = createPs5NativePkgBuilderProvider({ toolRoot: f.toolRoot, allowedWorkRoots: [f.workRoot], allowedSourceRoots: [f.sourceRoot], runner: async () => ({ code: 0, output: JSON.stringify(cleanProbe()) }), }); await assert.rejects( () => provider.buildDistinctControl({ sourcePath: f.sourceRoot, outputPath: path.join(f.workRoot, 'control.pkg'), workPath: path.join(f.workRoot, 'work'), titleId: 'PPSA12345' }), error => error.code === 'PS5_A8_CONTROL_IDENTITY_FIXED', ); await assert.rejects( () => provider.buildDistinctControl({ sourcePath: f.sourceRoot, outputPath: path.join(f.workRoot, 'control.pkg'), workPath: path.join(f.workRoot, 'work') }), error => error.code === 'PS5_A8_CONTROL_SOURCE_DRIFT', ); }); test('build invokes only build-backup with an immutable semantic v4 request when all clean capabilities are proven', async t => { const f = fixture(); t.after(() => fs.rmSync(f.root, { recursive: true, force: true })); const outputPath = path.join(f.workRoot, 'artifact.pkg'); const buildWork = path.join(f.workRoot, 'job'); let request; let reportOverride = {}; const runner = async ({ args }) => { if (args[0] === 'probe') return { code: 0, output: JSON.stringify(cleanProbe({ capabilities: { ...CLEAN_CAPABILITIES, licenseFreeBuild: true, backupBuildApi: 'ProsperoPackageBuilder' } })) }; assert.deepEqual(args.slice(0, 2), ['build-backup', '--request']); request = JSON.parse(fs.readFileSync(args[2], 'utf8')); fs.writeFileSync(outputPath, Buffer.concat([Buffer.from([0x7f, 0x46, 0x49, 0x48]), Buffer.alloc(64)])); fs.writeFileSync(args[4], JSON.stringify({ ok: true, outputPath, buildApi: 'ProsperoPackageBuilder', licenseFree: true, validation: { accepted: true }, unresolvedModules: [], launchReadiness: { isLaunchReady: true }, ...reportOverride })); return { code: 0, output: '' }; }; const provider = createPs5NativePkgBuilderProvider({ toolRoot: f.toolRoot, allowedWorkRoots: [f.workRoot], allowedSourceRoots: [f.sourceRoot], runner }); await provider.build({ componentType: 'base', sourcePath: f.sourceRoot, sourceSize: 6, outputPath, workPath: buildWork, titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERAFPKG00001', version: '01.00', title: 'Fixture', }); assert.equal(request.abi, 'chimera-prospero-bridge-v4'); assert.equal(request.operation, 'build-backup'); assert.equal(request.componentType, 'base'); assert.equal('licenseFree' in request, false); assert.equal('fakeSignSelfModules' in request, false); assert.equal('tuning' in request, false); for (const invalid of [{ licenseFree: false }, { buildApi: 'ProsperoBackupConverter' }, { outputPath: path.join(f.workRoot, 'other.pkg') }, { validation: { accepted: false } }, { unresolvedModules: ['eboot.bin'] }]) { reportOverride = invalid; await assert.rejects(provider.build({ componentType: 'base', sourcePath: f.sourceRoot, sourceSize: 6, outputPath, workPath: buildWork, titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERAFPKG00001' }), { code: 'PS5_BUILDER_OUTPUT' }); } }); test('Docker production stage applies only the pinned streaming patch, never the historical V16 series', () => { const docker = fs.readFileSync('Dockerfile', 'utf8'); assert.match(docker, /ARG LIBPROSPEROPKG_COMMIT=9084c0e88cd8d7cd9c0b353b8b6b89f7d1cc4275/); assert.match(docker, /patches\/0001-stream-large-package-assembly\.patch/); assert.match(docker, /git -C \/src\/LibProsperoPkg apply/); const streamingPatch = fs.readFileSync('tools/chimera-prospero-bridge/patches/0001-stream-large-package-assembly.patch', 'utf8'); assert.match(streamingPatch, /BuildFromFsTreeToFile/); assert.match(streamingPatch, /BuildForPackageFile/); assert.match(streamingPatch, /ProsperoOuterPfsAddressingPlan/); assert.match(streamingPatch, /WriteU2cBase24\(entry\.AsSpan\(4, 3\), nextBase\)/); assert.match(streamingPatch, /value is < 0 or > 0xFFFFFF/); assert.doesNotMatch(streamingPatch, /MountImageKey|RsaPkcs1EncryptKey|PfsGenEncKey|PfsGenSignKey/); assert.doesNotMatch(docker, /CHIMERA_PATCH_SET|chimera-license-free-base-v16/); assert.match(docker, /LibProsperoPkg-9084c0e-streaming/); }); test('historical patches remain documented outside the production path', () => { const legacyRoot = 'tools/chimera-prospero-bridge/legacy/v16-patches'; assert.equal(fs.existsSync(path.join(legacyRoot, '0001-parallel-fast-store.patch')), true); const notice = fs.readFileSync(path.join(legacyRoot, 'README.md'), 'utf8'); assert.match(notice, /historical research only/i); assert.match(notice, /not used by the production builder/i); });