'use strict'; const assert = require('node:assert/strict'); const fs = require('fs'); const os = require('os'); const path = require('path'); const test = require('node:test'); const database = require('../../src/database'); const { createV3Repositories } = require('../../src/services/v3-repositories'); const { createInstallRecipeRepository } = require('../../src/services/install-recipe-repository'); const contract = require('../../renderer/modules/navigation-routes'); const { inferredPermission } = require('../../src/core/command-registry'); function withDatabase(run) { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-package-library-')); database.configure({ dataDir: root, logger: { info() {}, warn() {}, error() {} } }); return database.initialize().then(run).finally(() => { database.close(); fs.rmSync(root, { recursive: true, force: true }); }); } test('package catalog preserves title, sets, component versions/hashes and recipes', () => withDatabase(() => { database.runMutatingSqlWithParams("INSERT INTO titles (id,platform,title_id,name,sort_name) VALUES (1,'ps4','CUSA12345','Package Library','Package Library')"); const packageSet = { id: 0, titleId: 1, setKey: 'retail-us', label: 'Retail US', variantKey: 'retail', platform: 'ps4', region: 'US', source: 'managed-import', observedAt: 1, confidence: 'high', components: [ { componentId: 'base', type: 'base', required: true, originalRelativePath: 'base.pkg', normalizedRelativePath: 'base/base.pkg', size: 4, sha256: '1'.repeat(64), version: '1.00', contentId: 'UP0001-CUSA12345_00-BASEPACKAGE000001', region: 'US', order: 1, metadata: { platform: 'ps4', titleId: { value: 'CUSA12345' } }, provenance: [{ source: 'test' }] }, { componentId: 'update', type: 'update', required: true, originalRelativePath: 'update.pkg', normalizedRelativePath: 'updates/1.02/update.pkg', size: 5, sha256: '2'.repeat(64), version: '1.02', contentId: 'UP0001-CUSA12345_00-UPDATEPACKAGE001', region: 'US', order: 2, metadata: { platform: 'ps4', titleId: { value: 'CUSA12345' } }, provenance: [{ source: 'test' }] }, ], dependencies: [{ componentId: 'update', dependsOnComponentId: 'base', kind: 'requires' }] }; createV3Repositories(database).packageSets.savePackageSet(packageSet); const saved = createV3Repositories(database).packageSets.listByTitle(1)[0]; createInstallRecipeRepository({ db: database, now: () => 10 }).saveVersion({ packageSet: saved, recipeKey: 'safe', label: 'Safe install', notes: 'Read only notes', expectedVersion: 0, steps: [ { id: 'base-step', componentId: 'base', action: 'install-package', required: true, dependsOn: [], destinationCapabilities: ['canInstall'] }, { id: 'update-step', componentId: 'update', action: 'install-package', required: true, dependsOn: ['base-step'], destinationCapabilities: ['canInstall'] }, ] }); const sets = createV3Repositories(database).packageSets.listCatalog(); const recipes = createInstallRecipeRepository({ db: database }).listByTitle(1); assert.equal(sets[0].title.externalTitleId, 'CUSA12345'); assert.deepEqual(sets[0].components.map(item => [item.type, item.version, item.sha256]), [['base', '1.00', '1'.repeat(64)], ['update', '1.02', '2'.repeat(64)]]); assert.equal(recipes[0].label, 'Safe install'); assert.match(recipes[0].recipeSha256, /^[a-f0-9]{64}$/); })); test('Library Packages is normal while raw Package Services remains Expert-only', () => { const library = contract.routes.find(route => route.id === 'library/packages'); const services = contract.routes.find(route => route.id === 'tools/package-services'); assert.equal(library.page, 'packages'); assert.equal(library.expert, undefined); assert.equal(services.page, 'operations'); assert.equal(services.panel, 'packages'); assert.equal(services.expert, true); assert.equal(inferredPermission('package-catalog:list'), 'authenticated'); assert.equal(inferredPermission('packages:status'), 'expert'); }); test('normal package module is inventory-only and contains no raw service or handoff calls', () => { const source = fs.readFileSync(path.join(__dirname, '../../renderer/modules/packages.js'), 'utf8'); assert.match(source, /packageCatalog\(\)/); assert.match(source, /component\.sha256/); assert.match(source, /set\.recipes/); assert.doesNotMatch(source, /packagesStatus|packagesInstallUrl|DPI|Void|install-url/i); });