40 lines
2.5 KiB
TypeScript
40 lines
2.5 KiB
TypeScript
import { readFile } from 'node:fs/promises';
|
|
import { resolve } from 'node:path';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { databaseMigrations } from '../../server/postgres/migration-catalog';
|
|
|
|
const migrationPath = resolve(import.meta.dirname, '..', '..', 'server', 'postgres', 'migrations', '015_policy_evaluations.sql');
|
|
const baselineDrivenMigrationPath = resolve(import.meta.dirname, '..', '..', 'server', 'postgres', 'migrations', '020_baseline_driven_policy_evaluation.sql');
|
|
|
|
describe('PostgreSQL policy evaluation migration', () => {
|
|
it('persists runs, results, explicit baseline sources, and multi-source evidence', async () => {
|
|
const sql = await readFile(migrationPath, 'utf8');
|
|
expect(databaseMigrations.find(migration => migration.version === '015')).toMatchObject({ version: '015', name: 'policy-evaluations' });
|
|
expect(sql).toContain('CREATE TABLE assessor_policy_evaluation_runs');
|
|
expect(sql).toContain('CREATE TABLE assessor_policy_evaluation_baseline_sources');
|
|
expect(sql).toContain('CREATE TABLE assessor_policy_evaluation_results');
|
|
expect(sql).toContain('CREATE TABLE assessor_policy_evaluation_evidence');
|
|
expect(sql).toContain('aggregation_run_id text NOT NULL REFERENCES assessor_policy_snapshot_aggregation_runs(id) ON DELETE CASCADE');
|
|
expect(sql).toContain('aggregation_state_id text NOT NULL REFERENCES assessor_policy_snapshot_states(id) ON DELETE CASCADE');
|
|
});
|
|
|
|
it('keeps projection and effectiveness closed at the relational boundary', async () => {
|
|
const sql = await readFile(migrationPath, 'utf8');
|
|
expect(sql).toContain('CHECK (projected_finding_count = 0)');
|
|
expect(sql).toContain("CHECK (effective_state = 'unknown')");
|
|
expect(sql).toContain("CHECK (NOT finding_eligible OR classification = 'confirmed_configured_deviation')");
|
|
expect(sql).not.toMatch(/severity|finding_definition|finding_occurrence/i);
|
|
});
|
|
|
|
it('supports baseline-only comparison rows without inventing aggregation states', async () => {
|
|
const sql = await readFile(baselineDrivenMigrationPath, 'utf8');
|
|
expect(databaseMigrations.find(migration => migration.version === '020')).toMatchObject({
|
|
version: '020', name: 'baseline-driven-policy-evaluation'
|
|
});
|
|
expect(sql).toContain('ALTER COLUMN aggregation_state_id DROP NOT NULL');
|
|
expect(sql).toContain('ADD COLUMN baseline_analysis_id text');
|
|
expect(sql).toContain("customer_state IN ('configured', 'missing', 'conflicted', 'indeterminate')");
|
|
expect(sql).toContain('assessor_policy_evaluation_results_baseline_identity_uq');
|
|
});
|
|
});
|