'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 database = require('../../src/database'); const { createPs5NativePackageService, inspectPs5ContainerFile, } = require('../../src/services/ps5-native-package-service'); const { PINNED_PS5_BUILDER, createPs5NativePkgBuilderProvider, runProcess, } = require('../../src/services/ps5-native-pkg-builder-provider'); const { registerPs5NativePackageManifest } = require('../../src/services/ps5-native-package-registration-service'); function semanticCapabilities(overrides = {}) { return { backupToDebugFpkg: true, dataDlcToDebugFpkg: true, updateToDebugFpkg: false, backupInspection: true, packageInspection: true, packageValidation: true, launchReadiness: true, licenseFreeBuild: true, finalizedFihOutput: true, ...overrides }; } function semanticProbe(overrides = {}) { return { available: true, ...PINNED_PS5_BUILDER, capabilities: semanticCapabilities(), ...overrides }; } function acceptedValidation() { return { accepted: true, validator: 'ProsperoPkgValidator', launchReady: true, unresolvedModules: [] }; } function writeBackup(root, name = 'source', overrides = {}) { const folder = path.join(root, name); fs.mkdirSync(path.join(folder, 'sce_sys'), { recursive: true }); fs.writeFileSync(path.join(folder, 'eboot.bin'), Buffer.concat([Buffer.from([0x7f, 0x45, 0x4c, 0x46]), Buffer.alloc(128)])); fs.writeFileSync(path.join(folder, 'sce_sys', 'param.json'), JSON.stringify({ titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001', contentVersion: '01.00', localizedParameters: { enUS: { titleName: 'Chimera PS5 Test' }, defaultLanguage: 'en-US' }, applicationDrmType: 'standard', ...overrides, })); return folder; } function writeDlcBackup(root, name = 'dlc-source', overrides = {}) { const folder = path.join(root, name); fs.mkdirSync(path.join(folder, 'sce_sys'), { recursive: true }); fs.mkdirSync(path.join(folder, 'data'), { recursive: true }); fs.writeFileSync(path.join(folder, 'data', 'owned-content.bin'), 'owned dlc fixture'); fs.writeFileSync(path.join(folder, 'sce_sys', 'param.json'), JSON.stringify({ titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERADLC000001', contentVersion: '01.01', localizedParameters: { enUS: { titleName: 'Chimera PS5 Test DLC' }, defaultLanguage: 'en-US' }, applicationDrmType: 'free', ...overrides, })); return folder; } function writeFih(filename, contentId = 'UP0001-PPSA12345_00-CHIMERATEST00001') { const fih = Buffer.alloc(0x10000); const pfs = Buffer.alloc(0x10000); const cnt = Buffer.alloc(0x2900); Buffer.from([0x7f, 0x46, 0x49, 0x48]).copy(fih); fih[4] = 1; fih.writeUInt16LE(3, 6); fih.writeUInt32LE(1, 8); fih.writeBigUInt64LE(0x10000n, 0x10); fih.writeBigUInt64LE(0x10000n, 0x18); fih.writeBigUInt64LE(0x20000n, 0x58); fih.writeUInt32LE(1, 0xfc); const gameDigest = crypto.createHash('sha3-256').update(pfs).digest(); for (const offset of [0x30, 0x70, 0xd0]) gameDigest.copy(fih, offset); Buffer.from([0x7f, 0x43, 0x4e, 0x54]).copy(cnt); cnt.writeUInt32BE(1, 0x10); cnt.writeUInt16BE(1, 0x14); cnt.writeUInt16BE(1, 0x16); cnt.writeUInt32BE(0x2000, 0x18); cnt.writeBigUInt64BE(0x2000n, 0x20); cnt.writeBigUInt64BE(0x900n, 0x28); Buffer.from(contentId, 'ascii').copy(cnt, 0x40, 0, 0x30); cnt.writeUInt32BE(0x20, 0x2000); cnt.writeUInt32BE(0x2100, 0x2010); cnt.writeUInt32BE(0x800, 0x2014); for (const [record, offset] of [0x000, 0x180, 0x300, 0x480, 0x600].entries()) crypto.createHash('sha256').update(`${contentId}:${record}`).digest().copy(cnt, 0x2100 + offset); crypto.createHash('sha3-256').update(cnt.subarray(0, 0xfe0)).digest().copy(cnt, 0xfe0); fs.writeFileSync(filename, Buffer.concat([fih, pfs, cnt])); } function fixture(t, overrides = {}) { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-pkg-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const libraryRoot = path.join(root, 'library'); const outputRoot = path.join(root, 'vault'); fs.mkdirSync(libraryRoot, { recursive: true }); const registrations = []; const builds = []; const provider = overrides.provider || { probe: async () => semanticProbe(), build: async input => { builds.push(input); fs.mkdirSync(path.dirname(input.outputPath), { recursive: true }); writeFih(input.outputPath, input.contentId); return { provider: PINNED_PS5_BUILDER }; }, validatePackage: async () => acceptedValidation(), }; const service = createPs5NativePackageService({ allowedRoots: () => [libraryRoot, outputRoot], outputRoot, stateFile: path.join(root, 'state', 'jobs.json'), provider, registrar: async manifest => { registrations.push(manifest); return { packageSetId: 91 }; }, idFactory: overrides.idFactory || (() => 'ps5-job-1'), now: overrides.now || (() => 1_800_000_000_000), }); return { root, libraryRoot, outputRoot, registrations, builds, service }; } test('validates a decrypted PS5 backup from param.json and executable evidence', async t => { const f = fixture(t); const source = writeBackup(f.libraryRoot); const result = await f.service.inspectBackup({ sourcePath: source, expectedTitleId: 'PPSA12345' }); assert.equal(result.ready, true); assert.equal(result.titleId, 'PPSA12345'); assert.equal(result.executable.format, 'raw-elf'); assert.equal(result.contentId, 'UP0001-PPSA12345_00-CHIMERATEST00001'); }); test('blocks opaque executables and identity mismatch while rejecting unsafe paths', async t => { const f = fixture(t); const opaque = writeBackup(f.libraryRoot, 'opaque'); fs.writeFileSync(path.join(opaque, 'eboot.bin'), 'not decrypted'); const opaqueResult = await f.service.inspectBackup({ sourcePath: opaque }); assert.equal(opaqueResult.state, 'blocked'); assert.ok(opaqueResult.issues.some(item => item.code === 'PS5_FPKG_MODULE_UNRESOLVED')); const wrong = writeBackup(f.libraryRoot, 'wrong'); const mismatch = await f.service.inspectBackup({ sourcePath: wrong, expectedTitleId: 'PPSA99999' }); assert.equal(mismatch.state, 'blocked'); assert.ok(mismatch.issues.some(item => item.code === 'PS5_FPKG_TITLE_MISMATCH')); const linked = writeBackup(f.libraryRoot, 'linked'); const outside = path.join(f.root, 'outside'); fs.mkdirSync(outside); fs.writeFileSync(path.join(outside, 'x'), 'x'); fs.symlinkSync(outside, path.join(linked, 'escape'), process.platform === 'win32' ? 'junction' : 'dir'); await assert.rejects(() => f.service.inspectBackup({ sourcePath: linked }), error => error.code === 'PS5_FPKG_SOURCE_UNSAFE'); await assert.rejects(() => f.service.inspectBackup({ sourcePath: outside }), error => error.code === 'PS5_BACKUP_CONTAINMENT'); }); test('accepts signed modules only when a matching decrypted raw-ELF substitute exists', async t => { const f = fixture(t); const source = writeBackup(f.libraryRoot, 'signed-with-decrypted'); fs.writeFileSync(path.join(source, 'eboot.bin'), Buffer.concat([Buffer.from([0x54, 0x14, 0xf5, 0xee]), Buffer.alloc(128)])); fs.mkdirSync(path.join(source, 'decrypted'), { recursive: true }); fs.writeFileSync(path.join(source, 'decrypted', 'eboot.bin'), Buffer.concat([Buffer.from([0x7f, 0x45, 0x4c, 0x46]), Buffer.alloc(128)])); const result = await f.service.inspectBackup({ sourcePath: source }); assert.equal(result.executable.format, 'self-with-decrypted-substitutes'); assert.equal(result.executable.substitutedModuleCount, 1); }); test('accepts data DLC without eboot but refuses update and entitlement-only package routes', async t => { const f = fixture(t); const dlc = writeDlcBackup(f.libraryRoot); const inspected = await f.service.inspectBackup({ sourcePath: dlc, expectedTitleId: 'PPSA12345', componentType: 'dlc' }); assert.equal(inspected.componentType, 'dlc'); assert.equal(inspected.executable.moduleCount, 0); const update = await f.service.inspectBackup({ sourcePath: dlc, componentType: 'update' }); assert.equal(update.state, 'unsupported'); assert.equal(update.ready, false); await assert.rejects(() => f.service.inspectBackup({ sourcePath: dlc, componentType: 'dlc-entitlement' }), error => error.code === 'PS5_FPKG_SOURCE_NOT_READY'); }); test('distinguishes genuine PS5 FIH/CNT containers from FFPKG mount images and renamed files', t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-format-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const fih = path.join(root, 'game.pkg'); writeFih(fih); const cnt = path.join(root, 'metadata.pkg'); fs.writeFileSync(cnt, Buffer.concat([Buffer.from([0x7f, 0x43, 0x4e, 0x54]), Buffer.alloc(64)])); const image = path.join(root, 'game.ffpkg'); fs.writeFileSync(image, Buffer.alloc(128)); const renamed = path.join(root, 'renamed.pkg'); fs.writeFileSync(renamed, Buffer.alloc(128)); const inspectedFih = inspectPs5ContainerFile(fih); assert.deepEqual(inspectedFih.format, 'ps5-fih-debug-package'); assert.equal(inspectedFih.validation.installTrust.status, 'unproven'); assert.equal(inspectedFih.validation.installTrust.basis, 'structural-only'); assert.ok(inspectedFih.validation.warnings.some(item => item.code === 'APPINST_TRUST_UNPROVEN')); assert.deepEqual(inspectPs5ContainerFile(cnt).format, 'ps5-cnt-container'); assert.equal(inspectPs5ContainerFile(image).format, 'ufs-mount-image'); assert.equal(inspectPs5ContainerFile(image).nativeInstallable, false); assert.equal(inspectPs5ContainerFile(renamed).format, 'unknown-pkg'); assert.equal(inspectPs5ContainerFile(renamed).nativeInstallable, false); }); test('accepts the upstream stock FIH image-count and opaque image-key profile without claiming launch compatibility', t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-stock-profile-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const stock = path.join(root, 'stock.pkg'); writeFih(stock, 'IV9999-FAKE00000_00-HOMEBREWLOADER01'); const bytes = fs.readFileSync(stock); bytes.writeUInt32LE(0, 0xfc); for (let index = 0; index < 0x800; index++) bytes[0x22100 + index] = ((index * 73 + 19) % 255) + 1; crypto.createHash('sha3-256').update(bytes.subarray(0x20000, 0x20fe0)).digest().copy(bytes, 0x20fe0); fs.writeFileSync(stock, bytes); const inspected = inspectPs5ContainerFile(stock); assert.equal(inspected.structurallyValid, true); assert.equal(inspected.validation.validationLevel, 'fih-cnt-structural-v3'); assert.equal(inspected.validation.imageCount, 0); assert.equal(inspected.validation.imageKey.profile, 'opaque-filled-0x800'); assert.equal(inspected.validation.routeCompatibility.status, 'unproven'); assert.ok(inspected.validation.warnings.some(item => item.code === 'FIH_IMAGE_COUNT_STOCK_PROFILE')); assert.ok(inspected.validation.warnings.some(item => item.code === 'CNT_IMAGE_KEY_OPAQUE_PROFILE')); }); test('fails closed when FIH geometry, CNT sealing or image-key records are corrupted', t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-structural-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const geometry = path.join(root, 'geometry.pkg'); writeFih(geometry); const geometryFd = fs.openSync(geometry, 'r+'); fs.writeSync(geometryFd, Buffer.from([0x01]), 0, 1, 0x58); fs.closeSync(geometryFd); let inspected = inspectPs5ContainerFile(geometry); assert.equal(inspected.nativeInstallable, false); assert.ok(inspected.validation.errors.some(item => item.code === 'FIH_CNT_GEOMETRY')); const seal = path.join(root, 'seal.pkg'); writeFih(seal); const sealFd = fs.openSync(seal, 'r+'); fs.writeSync(sealFd, Buffer.from([0xff]), 0, 1, 0x20000 + 0x100); fs.closeSync(sealFd); inspected = inspectPs5ContainerFile(seal); assert.ok(inspected.validation.errors.some(item => item.code === 'CNT_HEADER_SEAL')); const key = path.join(root, 'key.pkg'); writeFih(key); const keyFd = fs.openSync(key, 'r+'); fs.writeSync(keyFd, Buffer.alloc(0x800), 0, 0x800, 0x22100); fs.closeSync(keyFd); inspected = inspectPs5ContainerFile(key); assert.ok(inspected.validation.errors.some(item => item.code === 'CNT_IMAGE_KEY_PROFILE')); const sparseKey = path.join(root, 'sparse-key.pkg'); writeFih(sparseKey); const sparseKeyBytes = fs.readFileSync(sparseKey); sparseKeyBytes.fill(0, 0x22100, 0x22900); sparseKeyBytes[0x22100] = 1; crypto.createHash('sha3-256').update(sparseKeyBytes.subarray(0x20000, 0x20fe0)).digest().copy(sparseKeyBytes, 0x20fe0); fs.writeFileSync(sparseKey, sparseKeyBytes); inspected = inspectPs5ContainerFile(sparseKey); assert.ok(inspected.validation.errors.some(item => item.code === 'CNT_IMAGE_KEY_PROFILE')); }); test('builds, validates and hashes a real FIH package before registration', async t => { const f = fixture(t); const source = writeBackup(f.libraryRoot); const created = await f.service.create({ sourcePath: source, expectedTitleId: 'PPSA12345' }); assert.equal(created.status, 'package_ready'); const complete = await f.service.run(created.id); assert.equal(complete.status, 'artifact_registered'); assert.equal(complete.container.format, 'ps5-fih-debug-package'); assert.match(complete.sha256, /^[a-f0-9]{64}$/); assert.equal(f.registrations.length, 1); assert.equal(f.registrations[0].components[0].adapterHint, 'ps5-fpkg-finalized-fih'); assert.equal(f.registrations[0].components[0].sha256, crypto.createHash('sha256').update(fs.readFileSync(complete.outputPath)).digest('hex')); }); test('builds one ordered native package set from base plus data DLC components', async t => { const f = fixture(t); const base = writeBackup(f.libraryRoot, 'base'); const dlc = writeDlcBackup(f.libraryRoot, 'dlc'); const created = await f.service.create({ expectedTitleId: 'PPSA12345', sources: [{ sourcePath: base, componentType: 'base' }, { sourcePath: dlc, componentType: 'dlc' }] }); const complete = await f.service.run(created.id); assert.equal(complete.status, 'artifact_registered'); assert.deepEqual(f.builds.map(item => item.componentType), ['base', 'dlc']); assert.deepEqual(f.registrations[0].components.map(item => item.type), ['base', 'dlc']); assert.deepEqual(f.registrations[0].recipe.installOrder.map(item => item.order), [1, 3]); assert.deepEqual(f.registrations[0].dependencies, [{ componentId: f.registrations[0].components[1].id, requires: 'base' }]); assert.equal(f.registrations[0].components.every(item => item.container?.format === 'ps5-fih-debug-package'), true); }); test('a component identity change between planning and build fails closed', async t => { const f = fixture(t); const base = writeBackup(f.libraryRoot, 'base'); const dlc = writeDlcBackup(f.libraryRoot, 'dlc'); const created = await f.service.create({ sources: [{ sourcePath: base, componentType: 'base' }, { sourcePath: dlc, componentType: 'dlc' }] }); const paramPath = path.join(dlc, 'sce_sys', 'param.json'); const param = JSON.parse(fs.readFileSync(paramPath, 'utf8')); param.contentId = 'UP0001-PPSA12345_00-CHIMERADLC000002'; fs.writeFileSync(paramPath, JSON.stringify(param)); await assert.rejects(() => f.service.run(created.id), error => error.code === 'PS5_FPKG_SOURCE_CHANGED'); assert.equal(f.registrations.length, 0); }); test('a same-size payload mutation between planning and build fails closed', async t => { const f = fixture(t); const base = writeBackup(f.libraryRoot, 'base'); const dlc = writeDlcBackup(f.libraryRoot, 'dlc'); const created = await f.service.create({ sources: [{ sourcePath: base, componentType: 'base' }, { sourcePath: dlc, componentType: 'dlc' }] }); const payloadPath = path.join(dlc, 'data', 'owned-content.bin'); const original = fs.readFileSync(payloadPath); fs.writeFileSync(payloadPath, Buffer.alloc(original.length, 0x78)); await assert.rejects(() => f.service.run(created.id), error => error.code === 'PS5_FPKG_SOURCE_CHANGED'); assert.equal(f.builds.length, 0); assert.equal(f.registrations.length, 0); }); test('exposes only hash-bound native FIH packages through a short-lived HTTPS handoff', async t => { const f = fixture(t); const pkg = path.join(f.outputRoot, 'verified.pkg'); writeFih(pkg); const bytes = fs.readFileSync(pkg); const sha256 = crypto.createHash('sha256').update(bytes).digest('hex'); const exposed = await f.service.expose({ filePath: pkg, sha256, size: bytes.length, origin: 'https://chimera.example.test' }); assert.match(exposed.url, /^https:\/\/chimera\.example\.test\/ps5-native-package\/[A-Za-z0-9_-]{43}\/verified\.pkg$/); assert.equal(f.service.resolvePackageHandoff(new URL(exposed.url).pathname).filePath, fs.realpathSync(pkg)); await assert.rejects(() => f.service.expose({ filePath: pkg, sha256: '0'.repeat(64), size: bytes.length, origin: 'https://chimera.example.test' }), error => error.code === 'PS5_PACKAGE_HANDOFF_HASH'); await assert.rejects(() => f.service.expose({ filePath: pkg, sha256, size: bytes.length, origin: 'http://chimera.example.test' }), error => error.code === 'PS5_PACKAGE_ORIGIN'); }); test('active jobs become interrupted and require an explicit resume', async t => { const f = fixture(t); const source = writeBackup(f.libraryRoot); const created = await f.service.create({ sourcePath: source }); const stateFile = path.join(f.root, 'state', 'jobs.json'); const stored = JSON.parse(fs.readFileSync(stateFile, 'utf8')); stored.jobs[0].status = 'building'; fs.writeFileSync(stateFile, JSON.stringify(stored)); const restarted = createPs5NativePackageService({ allowedRoots: () => [f.libraryRoot, f.outputRoot], outputRoot: f.outputRoot, stateFile, provider: f.service.__provider || { probe: async () => ({ available: true }), build: async () => ({}) }, registrar: async () => ({ packageSetId: 91 }) }); assert.equal(restarted.get(created.id).status, 'interrupted'); assert.equal(restarted.resume(created.id).status, 'package_ready'); }); test('requires a real registrar and never marks an unregistered artifact completed', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-registrar-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const libraryRoot = path.join(root, 'library'); const outputRoot = path.join(root, 'vault'); fs.mkdirSync(libraryRoot); const provider = { probe: async () => semanticProbe(), build: async input => writeFih(input.outputPath, input.contentId), validatePackage: async () => acceptedValidation() }; assert.throws(() => createPs5NativePackageService({ allowedRoots: () => [libraryRoot, outputRoot], outputRoot, stateFile: path.join(root, 'missing.json'), provider }), /registrar/i); let registration = {}; let builds = 0; provider.build = async input => { builds++; fs.mkdirSync(path.dirname(input.outputPath), { recursive: true }); writeFih(input.outputPath, input.contentId); }; const service = createPs5NativePackageService({ allowedRoots: () => [libraryRoot, outputRoot], outputRoot, stateFile: path.join(root, 'jobs.json'), provider, registrar: async () => registration, idFactory: () => 'registration-job' }); const source = writeBackup(libraryRoot); const created = await service.create({ sourcePath: source }); await assert.rejects(() => service.run(created.id), error => error.code === 'PS5_PACKAGE_REGISTRATION_INCOMPLETE'); assert.equal(service.get(created.id).status, 'registration_pending'); registration = { packageSetId: 123 }; service.resume(created.id); const completed = await service.run(created.id); assert.equal(completed.status, 'artifact_registered'); assert.equal(completed.registration.packageSetId, 123); assert.equal(builds, 1); }); test('rejects stale concurrent writers instead of clobbering job state', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-cas-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const libraryRoot = path.join(root, 'library'); const outputRoot = path.join(root, 'vault'); const stateFile = path.join(root, 'jobs.json'); fs.mkdirSync(libraryRoot); const provider = { probe: async () => ({ available: true }), build: async () => ({}) }; const options = { allowedRoots: () => [libraryRoot, outputRoot], outputRoot, stateFile, provider, registrar: async () => ({ packageSetId: 1 }) }; const first = createPs5NativePackageService({ ...options, idFactory: () => 'first' }); const second = createPs5NativePackageService({ ...options, idFactory: () => 'second' }); const source = writeBackup(libraryRoot); await first.create({ sourcePath: source }); await assert.rejects(() => second.create({ sourcePath: source }), error => error.code === 'PS5_PACKAGE_STATE_CONFLICT'); assert.deepEqual(JSON.parse(fs.readFileSync(stateFile, 'utf8')).jobs.map(job => job.id), ['first']); }); test('fails closed without overwriting corrupted durable job state', t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-corrupt-state-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const outputRoot = path.join(root, 'vault'); const stateFile = path.join(root, 'jobs.json'); const original = '{broken-json'; fs.writeFileSync(stateFile, original); const provider = { probe: async () => ({ available: true }), build: async () => ({}) }; assert.throws(() => createPs5NativePackageService({ allowedRoots: () => [root], outputRoot, stateFile, provider, registrar: async () => ({ packageSetId: 1 }) }), error => error.code === 'PS5_PACKAGE_STATE_CORRUPT'); assert.equal(fs.readFileSync(stateFile, 'utf8'), original); }); test('resume reuses a hash-verified component checkpoint instead of rebuilding it', async t => { const calls = []; let failDlc = true; const provider = { probe: async () => semanticProbe(), build: async input => { calls.push(input.componentType); if (input.componentType === 'dlc' && failDlc) throw new Error('simulated DLC failure'); fs.mkdirSync(path.dirname(input.outputPath), { recursive: true }); writeFih(input.outputPath, input.contentId); }, validatePackage: async () => acceptedValidation(), }; const f = fixture(t, { provider }); const base = writeBackup(f.libraryRoot, 'base'); const dlc = writeDlcBackup(f.libraryRoot, 'dlc'); const created = await f.service.create({ sources: [{ sourcePath: base, componentType: 'base' }, { sourcePath: dlc, componentType: 'dlc' }] }); await assert.rejects(() => f.service.run(created.id), /simulated DLC failure/); failDlc = false; f.service.resume(created.id); const complete = await f.service.run(created.id); assert.equal(complete.status, 'artifact_registered'); assert.deepEqual(calls, ['base', 'dlc', 'dlc']); }); test('start acknowledges immediately and runs the durable build asynchronously', async t => { let releaseBuild; const gate = new Promise(resolve => { releaseBuild = resolve; }); const provider = { probe: async () => semanticProbe(), build: async input => { await gate; fs.mkdirSync(path.dirname(input.outputPath), { recursive: true }); writeFih(input.outputPath, input.contentId); }, validatePackage: async () => acceptedValidation(), }; const f = fixture(t, { provider }); const created = await f.service.create({ sourcePath: writeBackup(f.libraryRoot) }); const accepted = f.service.start(created.id); assert.equal(accepted.accepted, true); assert.equal(accepted.status, 'package_ready'); assert.equal(f.service.start(created.id).alreadyRunning, true); releaseBuild(); for (let attempt = 0; attempt < 100 && f.service.get(created.id).status !== 'artifact_registered'; attempt++) await new Promise(resolve => setTimeout(resolve, 10)); assert.equal(f.service.get(created.id).status, 'artifact_registered'); }); test('service enforces the builder-advertised source ceiling before build', async t => { let builds = 0; const provider = { probe: async () => semanticProbe({ capabilities: semanticCapabilities({ maxSourceBytes: 1 }) }), build: async () => { builds++; }, validatePackage: async () => acceptedValidation(), }; const f = fixture(t, { provider }); const created = await f.service.create({ sourcePath: writeBackup(f.libraryRoot) }); await assert.rejects(() => f.service.run(created.id), error => error.code === 'PS5_BUILDER_SOURCE_LIMIT' && error.details.maxSourceBytes === 1); assert.equal(builds, 0); }); test('pinned bridge uses a fixed no-shell JSON request protocol and rejects hostile paths', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-builder-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const toolRoot = path.join(root, 'tool'); const workRoot = path.join(root, 'work'); const sourceRoot = path.join(root, 'source'); fs.mkdirSync(toolRoot); fs.mkdirSync(workRoot); fs.mkdirSync(sourceRoot); const executable = path.join(toolRoot, PINNED_PS5_BUILDER.executable); fs.writeFileSync(executable, 'bridge'); const outputPath = path.join(workRoot, 'out.pkg'); const calls = []; const runner = async input => { calls.push(input); if (input.args[0] === 'probe') return { output: JSON.stringify(semanticProbe()) }; writeFih(outputPath); fs.writeFileSync(input.args[4], JSON.stringify({ ok: true, outputPath })); return { output: 'ok' }; }; const provider = createPs5NativePkgBuilderProvider({ toolRoot, allowedWorkRoots: [workRoot], allowedSourceRoots: [sourceRoot], runner }); assert.equal((await provider.probe()).available, true); await provider.build({ sourcePath: sourceRoot, sourceSize: 0, outputPath, workPath: path.join(workRoot, 'job'), titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001' }); assert.equal(calls.at(-1).command, fs.realpathSync(executable)); assert.equal(calls.at(-1).shell, false); assert.equal(calls.at(-1).args[0], 'build-backup'); assert.equal(calls.at(-1).args[1], '--request'); assert.equal(calls.at(-1).args[3], '--result'); assert.equal(JSON.parse(fs.readFileSync(calls.at(-1).args[2], 'utf8')).componentType, 'base'); await assert.rejects(() => provider.build({ sourcePath: sourceRoot, sourceSize: 0, outputPath, workPath: path.join(workRoot, 'update'), titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001', componentType: 'update' }), error => error.code === 'PS5_BUILDER_COMPONENT'); await assert.rejects(() => provider.build({ sourcePath: fspOutside(root), sourceSize: 0, outputPath, workPath: path.join(workRoot, 'evil'), titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001' }), error => error.code === 'PS5_BUILDER_PATH'); }); test('pinned bridge rejects a runtime that does not prove license-free base conversion', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-builder-license-free-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const toolRoot = path.join(root, 'tool'); fs.mkdirSync(toolRoot); fs.writeFileSync(path.join(toolRoot, PINNED_PS5_BUILDER.executable), 'bridge'); const runner = async () => ({ output: JSON.stringify({ ...PINNED_PS5_BUILDER, capabilities: { ...semanticCapabilities({ licenseFreeBuild: false }), }, }) }); const provider = createPs5NativePkgBuilderProvider({ toolRoot, runner }); const probe = await provider.probe(); assert.equal(probe.available, false); assert.equal(probe.reason, 'capability-mismatch'); }); test('pinned bridge persists bounded diagnostics when the native process fails', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-builder-failure-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const toolRoot = path.join(root, 'tool'); const workRoot = path.join(root, 'work'); const sourceRoot = path.join(root, 'source'); fs.mkdirSync(toolRoot); fs.mkdirSync(workRoot); fs.mkdirSync(sourceRoot); fs.writeFileSync(path.join(toolRoot, PINNED_PS5_BUILDER.executable), 'bridge'); const runner = async input => { if (input.args[0] === 'probe') return { output: JSON.stringify(semanticProbe()) }; throw Object.assign(new Error('PS5 packagebridge stopte met code 1.'), { code: 'PS5_BUILDER_FAILED', details: { code: 1, output: 'System.InvalidOperationException: exact native failure' } }); }; const provider = createPs5NativePkgBuilderProvider({ toolRoot, allowedWorkRoots: [workRoot], allowedSourceRoots: [sourceRoot], runner }); const workPath = path.join(workRoot, 'job'); await assert.rejects(() => provider.build({ sourcePath: sourceRoot, sourceSize: 0, outputPath: path.join(workRoot, 'out.pkg'), workPath, titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001' }), error => { assert.equal(error.code, 'PS5_BUILDER_FAILED'); assert.match(error.details.output, /exact native failure/); assert.equal(error.details.exitCode, 1); return true; }); const diagnostic = JSON.parse(fs.readFileSync(path.join(workPath, 'build-failure.json'), 'utf8')); assert.equal(diagnostic.code, 'PS5_BUILDER_FAILED'); assert.equal(diagnostic.exitCode, 1); assert.match(diagnostic.output, /exact native failure/); }); test('native bridge process logging is capped while retaining a bounded output tail', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-builder-log-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const logPath = path.join(root, 'build.log'); const result = await runProcess({ command: process.execPath, args: ['-e', `process.stdout.write('x'.repeat(${9 * 1024 * 1024}))`], cwd: root, logPath }); assert.equal(result.code, 0); assert.equal(result.output.length, 64_000); assert.ok(fs.statSync(logPath).size <= 8 * 1024 * 1024); }); test('failed package jobs retain structured provider diagnostics', async t => { const provider = { probe: async () => semanticProbe(), build: async () => { throw Object.assign(new Error('bridge failed'), { code: 'PS5_BUILDER_FAILED', details: { exitCode: 1, output: 'precise failure', diagnosticPath: '/safe/work/build-failure.json' } }); }, validatePackage: async () => acceptedValidation(), }; const f = fixture(t, { provider }); const source = writeBackup(f.libraryRoot); const created = await f.service.create({ sourcePath: source }); await assert.rejects(() => f.service.run(created.id), /bridge failed/); const failed = f.service.get(created.id); assert.equal(failed.status, 'failed'); assert.deepEqual(failed.errorDetails, { code: 'PS5_BUILDER_FAILED', exitCode: 1, output: 'precise failure', diagnosticPath: '/safe/work/build-failure.json' }); }); test('bridge binds data DLC explicitly and exposes no update or entitlement-only build mode', () => { const source = fs.readFileSync(path.join(__dirname, '../../tools/chimera-prospero-bridge/Program.cs'), 'utf8'); assert.match(source, /chimera-prospero-bridge-v4/); assert.match(source, /ProsperoBackupConverter/); assert.match(source, /ProsperoPkgValidator\.Validate/); assert.match(source, /build-backup/); assert.match(source, /build-data-dlc/); assert.match(source, /inspect-backup/); assert.match(source, /inspect-package/); assert.match(source, /validate-package/); assert.match(source, /licenseFreeBuild = true/); assert.match(source, /backupBuildApi = "ProsperoPackageBuilder"/); assert.match(source, /LicenseFree = true, FakeSignSelfModules = false/); assert.match(source, /ProsperoFself\.MakeFself/); assert.doesNotMatch(source, /patchSet/); assert.doesNotMatch(source, /wideNapsU2cBase|stockImageKeyRsa3072|chimera-license-free-base-v16/); assert.match(source, /ProsperoPackageMode\.AdditionalContentData/); assert.doesNotMatch(source, /ProsperoPackageMode\.AdditionalContentNoData/); assert.doesNotMatch(source, /ProsperoPackageMode\.(Update|Patch)/); }); test('builder v4 request contains semantic inputs without legacy implementation tuning', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-builder-tuning-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const toolRoot = path.join(root, 'tool'); const workRoot = path.join(root, 'work'); const sourceRoot = path.join(root, 'source'); fs.mkdirSync(toolRoot); fs.mkdirSync(workRoot); fs.mkdirSync(sourceRoot); fs.writeFileSync(path.join(toolRoot, PINNED_PS5_BUILDER.executable), 'bridge'); const outputPath = path.join(workRoot, 'out.pkg'); const calls = []; const runner = async input => { calls.push(input); if (input.args[0] === 'probe') return { output: JSON.stringify(semanticProbe()) }; writeFih(outputPath); fs.writeFileSync(input.args[4], JSON.stringify({ ok: true, outputPath })); return { output: 'ok' }; }; const provider = createPs5NativePkgBuilderProvider({ toolRoot, allowedWorkRoots: [workRoot], allowedSourceRoots: [sourceRoot], runner, }); await provider.build({ sourcePath: sourceRoot, sourceSize: 0, outputPath, workPath: path.join(workRoot, 'job'), titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001' }); const buildCall = calls.at(-1); const request = JSON.parse(fs.readFileSync(buildCall.args[2], 'utf8')); assert.equal(request.operation, 'build-backup'); assert.equal(request.abi, 'chimera-prospero-bridge-v4'); assert.equal(request.tuning, undefined); assert.equal(buildCall.env.CHIMERA_PROSPERO_COMPRESSION_WORKERS, undefined); assert.match(buildCall.env.CHIMERA_PROSPERO_ALLOWED_SOURCE_ROOTS, /source/); }); test('Docker builds the exact upstream revision with only the pinned streaming patch', () => { const root = path.resolve(__dirname, '../..'); const dockerfile = fs.readFileSync(path.join(root, 'Dockerfile'), 'utf8'); assert.match(dockerfile, /9084c0e88cd8d7cd9c0b353b8b6b89f7d1cc4275/); assert.match(dockerfile, /git .* status --porcelain/); assert.match(dockerfile, /CHIMERA_UPSTREAM_PROVENANCE\.json/); assert.match(dockerfile, /0001-stream-large-package-assembly\.patch/); assert.doesNotMatch(dockerfile, /v16-patches|chimera-license-free-base-v16/); assert.equal(fs.existsSync(path.join(root, 'tools/chimera-prospero-bridge/legacy/v16-patches/0001-parallel-fast-store.patch')), true); }); test('builder rejects insufficient workspace before starting the bridge', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-builder-capacity-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const toolRoot = path.join(root, 'tool'); const workRoot = path.join(root, 'work'); const sourceRoot = path.join(root, 'source'); fs.mkdirSync(toolRoot); fs.mkdirSync(workRoot); fs.mkdirSync(sourceRoot); fs.writeFileSync(path.join(toolRoot, PINNED_PS5_BUILDER.executable), 'bridge'); let buildRuns = 0; const runner = async input => { if (input.args[0] === 'probe') return { output: JSON.stringify(semanticProbe()) }; buildRuns++; return { output: '' }; }; const provider = createPs5NativePkgBuilderProvider({ toolRoot, allowedWorkRoots: [workRoot], allowedSourceRoots: [sourceRoot], runner }); await assert.rejects(() => provider.build({ sourcePath: sourceRoot, sourceSize: 10_000_000_000_000, outputPath: path.join(workRoot, 'out.pkg'), workPath: path.join(workRoot, 'job'), titleId: 'PPSA12345', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001' }), error => error.code === 'PS5_BUILDER_DISK'); assert.equal(buildRuns, 0); }); function fspOutside(root) { const outside = path.join(root, 'not-allowed'); fs.mkdirSync(outside, { recursive: true }); return outside; } test('registers a verified native package as a local package set without console-install evidence', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-registration-')); database.configure({ dataDir: path.join(root, 'db'), logger: { info() {}, warn() {}, error() {} } }); await database.initialize(); t.after(() => { database.close(); fs.rmSync(root, { recursive: true, force: true }); }); const outputRoot = path.join(root, 'vault'); const folder = path.join(outputRoot, 'PPSA12345', 'job'); fs.mkdirSync(folder, { recursive: true }); const pkg = path.join(folder, 'PPSA12345-base.pkg'); writeFih(pkg); const bytes = fs.readFileSync(pkg); const manifest = { schemaVersion: 1, kind: 'chimera.ps5-native-package.v1', createdAt: 100, title: { platform: 'ps5', titleId: 'PPSA12345', name: 'PS5 Test' }, packageFormat: { container: 'FIH', debug: true, retail: false }, components: [{ id: 'base', type: 'base', version: '01.00', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001', size: bytes.length, sha256: crypto.createHash('sha256').update(bytes).digest('hex'), absolutePath: pkg, required: true, order: 1, adapterHint: 'ps5-native-debug-package', provenance: [] }], dependencies: [], recipe: { installOrder: [{ componentId: 'base', order: 1 }] } }; const result = registerPs5NativePackageManifest({ db: database, outputRoot, manifest }); assert.ok(result.packageSetId); assert.equal(database.runQuery('SELECT COUNT(*) AS count FROM local_copies')[0].count, 1); assert.equal(database.runQuery('SELECT COUNT(*) AS count FROM console_installs')[0].count, 0); }); test('rolls back title and package registration atomically when a component is invalid', async t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-ps5-registration-rollback-')); database.configure({ dataDir: path.join(root, 'db'), logger: { info() {}, warn() {}, error() {} } }); await database.initialize(); t.after(() => { database.close(); fs.rmSync(root, { recursive: true, force: true }); }); const outputRoot = path.join(root, 'vault'); const folder = path.join(outputRoot, 'PPSA12345', 'job'); fs.mkdirSync(folder, { recursive: true }); const pkg = path.join(folder, 'invalid.pkg'); writeFih(pkg); const size = fs.statSync(pkg).size; const beforeGames = database.runQuery('SELECT COUNT(*) AS count FROM games')[0].count; const beforeTitles = database.runQuery('SELECT COUNT(*) AS count FROM titles')[0].count; const manifest = { schemaVersion: 1, kind: 'chimera.ps5-native-package.v1', createdAt: 100, title: { platform: 'ps5', titleId: 'PPSA12345', name: 'Rollback Test' }, packageFormat: { container: 'FIH', debug: true, retail: false }, components: [{ id: 'base', type: 'base', version: '01.00', contentId: 'UP0001-PPSA12345_00-CHIMERATEST00001', size, sha256: 'not-a-hash', absolutePath: pkg, required: true, order: 1 }], dependencies: [], recipe: { installOrder: [{ componentId: 'base', order: 1 }] } }; assert.throws(() => registerPs5NativePackageManifest({ db: database, outputRoot, manifest }), error => error.code === 'PS5_PACKAGE_MANIFEST'); assert.equal(database.runQuery('SELECT COUNT(*) AS count FROM games')[0].count, beforeGames); assert.equal(database.runQuery('SELECT COUNT(*) AS count FROM titles')[0].count, beforeTitles); assert.equal(database.runQuery('SELECT COUNT(*) AS count FROM package_sets')[0].count, 0); });