64 lines
3.2 KiB
TypeScript
64 lines
3.2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import type { StoredGpoBackupInstance } from '../../src/domain/gpo-analysis-persistence';
|
|
import type { GpoBackupInstance } from '../../src/domain/gpo-ingestion';
|
|
import type { ImportArtifact, ImportProcessingRun } from '../../src/domain/ingestion-persistence';
|
|
import { LocalAssessorRepository } from '../../src/persistence/local-assessor-repository';
|
|
import { RepositoryConflictError } from '../../src/persistence/repository-errors';
|
|
|
|
const timestamp = '2026-07-21T10:00:00.000Z';
|
|
const project = { id: 'gpo-persistence-project', name: 'Synthetic', createdAt: timestamp, updatedAt: timestamp, attributes: {} };
|
|
const artifact: ImportArtifact = {
|
|
version: 1, id: 'gpo-artifact', projectId: project.id, kind: 'source-file', relativePath: 'gpo-backups/backup.zip',
|
|
sha256: 'a'.repeat(64), sizeBytes: 10, sensitivity: 'secret', parseStatus: 'pending',
|
|
storage: { kind: 'backend-controlled', storageKey: '11111111-1111-4111-8111-111111111111' }, createdAt: timestamp
|
|
};
|
|
const run: ImportProcessingRun = {
|
|
version: 1, id: 'gpo-processing', projectId: project.id, artifactId: artifact.id, status: 'partial',
|
|
processors: [{ kind: 'artifact-parser', id: 'gpo-backup-ingestion', version: '1.0.0' }], diagnosticCodes: [],
|
|
startedAt: timestamp, completedAt: timestamp
|
|
};
|
|
const instance: GpoBackupInstance = {
|
|
version: 1, id: 'gpo-instance', projectId: project.id, sourceArtifactId: artifact.id,
|
|
identity: { status: 'resolved', gpoId: '11111111-1111-4111-8111-111111111111', backupId: '22222222-2222-4222-8222-222222222222', evidence: 'backup-metadata' },
|
|
domain: { status: 'resolved', key: 'dns:synthetic.example', evidence: 'backup-metadata' },
|
|
collection: { status: 'observed', collectedAt: timestamp, evidence: 'backend-receipt' },
|
|
backupSet: { scope: 'unknown', evidence: 'unknown' }, metadataStatus: 'complete',
|
|
sections: { computer: 'unknown', user: 'unknown' },
|
|
inventory: {
|
|
version: 1,
|
|
status: 'complete',
|
|
entries: [{
|
|
version: 1,
|
|
artifactId: 'metadata-artifact',
|
|
relativePath: 'synthetic/Backup.xml',
|
|
role: 'backup-metadata',
|
|
scope: 'shared',
|
|
disposition: 'supported',
|
|
secretIndicatorStatus: 'not-detected'
|
|
}],
|
|
diagnosticCodes: []
|
|
},
|
|
discoveredAt: timestamp
|
|
};
|
|
const record: StoredGpoBackupInstance = {
|
|
version: 1, id: 'stored-instance', projectId: project.id, artifactId: artifact.id,
|
|
processingRunId: run.id, instance, createdAt: timestamp
|
|
};
|
|
|
|
describe('immutable GPO analysis persistence', () => {
|
|
it('commits run and instances atomically, permits exact retry and rejects divergent history', async () => {
|
|
const repository = new LocalAssessorRepository();
|
|
await repository.saveProject(project);
|
|
await repository.saveImportArtifact(artifact);
|
|
await repository.saveGpoBackupAnalysis(run, [record]);
|
|
const revision = repository.revision;
|
|
|
|
await expect(repository.saveGpoBackupAnalysis(run, [record])).resolves.toBeUndefined();
|
|
expect(repository.revision).toBe(revision);
|
|
await expect(repository.saveGpoBackupAnalysis(run, [{ ...record, createdAt: '2026-07-21T10:00:01.000Z' }]))
|
|
.rejects.toBeInstanceOf(RepositoryConflictError);
|
|
await expect(repository.listGpoBackupInstances(project.id)).resolves.toEqual([record]);
|
|
});
|
|
});
|
|
|