import { mkdtemp, rm, writeFile } from 'node:fs/promises'; import type { Server } from 'node:http'; import type { AddressInfo } from 'node:net'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { afterEach, beforeEach, expect, it } from 'vitest'; import { createAssessorHttpServer } from '../../server/assessor-http-server'; import { LocalComplianceStore } from '../../src/compliance/local-compliance-store'; import type { RegulatoryMappingBatchRun } from '../../src/compliance/regulatory-mapping'; import { LocalAssessorRepository } from '../../src/persistence/local-assessor-repository'; // The project export keeps the engine's data: the Core export and the Compliance Engine's own // project data are combined at the HTTP route, not inside the Core repository. const stamp = '2026-10-05T08:00:00.000Z'; let directory: string; let server: Server | undefined; beforeEach(async () => { directory = await mkdtemp(join(tmpdir(), 'assessor-compliance-export-')); await writeFile(join(directory, 'index.html'), '
synthetic app
'); }); afterEach(async () => { await new Promise(resolve => server ? server.close(resolve) : resolve(undefined)); server = undefined; await rm(directory, { recursive: true, force: true }); }); async function exportVia(complianceExport?: LocalComplianceStore) { const repository = new LocalAssessorRepository(); await repository.saveProject({ id: 'dummy-project', name: 'Dummy Customer', createdAt: stamp, updatedAt: stamp, attributes: {} }); server = createAssessorHttpServer({ repository, staticRoot: directory, ...(complianceExport ? { complianceExport } : {}) }); await new Promise(resolve => server!.listen(0, '127.0.0.1', resolve)); const { port } = server.address() as AddressInfo; return (await fetch(`http://127.0.0.1:${port}/api/v1/projects/dummy-project/export`)).json(); } it('adds the Compliance Engine project data to the Core project export', async () => { const store = new LocalComplianceStore(); const batch = await store.createRegulatoryMappingBatchRun({ version: 1, id: 'dummy-batch', projectId: 'dummy-project', scopeKey: 'scope', filterHash: 'a'.repeat(64), idempotencyKey: 'dummy-batch-1', assessmentIds: ['dummy-assessment'], scanRunIds: [], filters: {}, status: 'queued', counts: { filteredResultCount: 0, excludedNonScannerCount: 0, eligibleFindingCount: 0, unsupportedFindingCount: 0, distinctRuleCount: 0, reusedSucceededRuleCount: 0, reusedActiveRuleCount: 0, scheduledRuleCount: 0, succeededRuleCount: 0, failedRuleCount: 0 }, createdAt: stamp, updatedAt: stamp } satisfies RegulatoryMappingBatchRun); const exported = await exportVia(store); expect(exported).toMatchObject({ project: { id: 'dummy-project' }, regulatoryMappingBatchRuns: [batch], regulatoryMappingRuns: [], regulatoryMappingDecisions: [] }); }); it('keeps the Core project export complete without the Compliance Engine', async () => { const exported = await exportVia(); expect(exported).toMatchObject({ project: { id: 'dummy-project' } }); expect(exported).not.toHaveProperty('regulatoryMappingBatchRuns'); });