'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 { createImportClassifierService } = require('../../src/services/import-classifier-service'); function store(root, relativePaths) { let saved = null; for (const relativePath of relativePaths) { const target = path.join(root, ...relativePath.split('/')); fs.mkdirSync(path.dirname(target), { recursive: true }); fs.writeFileSync(target, relativePath); } return { openForInspection: () => ({ id: 'job', state: 'quarantined', payloadPath: root, components: [] }), saveClassification: (_id, _owner, value) => { saved = structuredClone(value); return structuredClone(saved); }, getClassification: () => structuredClone(saved), }; } const evidence = (value, source = 'pkg-param-sfo', confidence = 'high') => ({ value, source, confidence }); test('known packages receive provenance and validated base-update-DLC order', async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-classifier-known-')); try { const staging = store(root, ['base.pkg', 'update.pkg', 'dlc.pkg', 'install-notes.txt']); const metadata = { 'base.pkg': { titleId: evidence('CUSA12345'), contentId: evidence('UP0001-CUSA12345_00-BASEPACKAGE000001'), version: evidence('1.00'), category: 'base', source: 'pkg-param-sfo', confidence: 'high' }, 'update.pkg': { titleId: evidence('CUSA12345'), contentId: evidence('UP0001-CUSA12345_00-UPDATEPACKAGE001'), version: evidence('1.02'), category: 'update', source: 'pkg-param-sfo', confidence: 'high' }, 'dlc.pkg': { titleId: evidence('CUSA12345'), contentId: evidence('UP0001-CUSA12345_00-DLCPACKAGE000001'), version: evidence('1.00'), category: 'dlc', source: 'pkg-param-sfo', confidence: 'high' }, }; const classifier = createImportClassifierService({ stagingStore: staging, packageInspector: (_file, relative) => metadata[relative], now: () => 1000 }); const result = await classifier.classify('job', 'alice'); assert.equal(result.status, 'classified'); assert.equal(result.title.id.value, 'CUSA12345'); assert.deepEqual(result.recipeProposal.installOrder.map(item => item.componentType), ['base', 'update', 'dlc']); assert.equal(result.components.every(component => component.provenance.length > 0), true); assert.equal(result.notes[0].execution, 'never'); assert.equal(result.recipeProposal.notesExecutable, false); assert.deepEqual(result.recipeProposal.arbitraryCommands, []); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); test('ambiguous filename-only evidence remains review-required', async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-classifier-ambiguous-')); try { const staging = store(root, ['CUSA11111-or-CUSA22222-update-v1.02.pkg']); const classifier = createImportClassifierService({ stagingStore: staging }); const result = await classifier.classify('job', 'alice'); assert.equal(result.status, 'review-required'); assert.equal(result.title.id.value, null); assert.equal(result.recipeProposal.installOrder.length, 0); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); test('ambiguous package versions remain review-required despite a strong title ID', async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-classifier-version-')); try { const staging = store(root, ['base.pkg']); const classifier = createImportClassifierService({ stagingStore: staging, packageInspector: () => ({ titleId: evidence('CUSA11111'), contentId: evidence('UP0001-CUSA11111_00-BASEPACKAGE000001'), version: evidence(null), category: 'base', candidates: { versions: ['1.00', '1.01'] }, }) }); const result = await classifier.classify('job', 'alice'); assert.equal(result.status, 'review-required'); assert.equal(result.issues.some(issue => issue.code === 'ambiguous-version'), true); assert.equal(result.components[0].validated, false); assert.deepEqual(result.recipeProposal.installOrder, []); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); test('mismatched component and content IDs block validation and ordering', async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-classifier-mismatch-')); try { const staging = store(root, ['base.pkg', 'update.pkg']); const classifier = createImportClassifierService({ stagingStore: staging, packageInspector: (_file, relative) => relative === 'base.pkg' ? { titleId: evidence('PPSA11111'), contentId: evidence('UP0001-PPSA11111_00-BASEPACKAGE000001'), version: evidence('1.00'), category: 'base' } : { titleId: evidence('PPSA22222'), contentId: evidence('UP0001-PPSA33333_00-UPDATEPACKAGE001'), version: evidence('1.01'), category: 'update' } }); const result = await classifier.classify('job', 'alice'); assert.equal(result.status, 'review-required'); assert.equal(result.issues.some(issue => issue.code === 'multiple-title-ids'), true); assert.equal(result.issues.some(issue => issue.code === 'content-title-mismatch'), true); assert.equal(result.components.find(component => component.relativePath === 'update.pkg').validated, false); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); test('packages discovered inside an extracted archive folder are classified', async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-classifier-archive-')); try { const relative = '.inspection/archive-id/game/base.pkg'; const staging = store(root, [relative]); const classifier = createImportClassifierService({ stagingStore: staging, packageInspector: () => ({ titleId: evidence('CUSA54321'), contentId: evidence('EP0001-CUSA54321_00-BASEPACKAGE000001'), version: evidence('1.00'), category: 'base' }) }); const result = await classifier.classify('job', 'alice'); assert.equal(result.components[0].relativePath, relative); assert.equal(result.components[0].validated, true); assert.equal(result.status, 'classified'); } finally { fs.rmSync(root, { recursive: true, force: true }); } });