TenantAtlas/tests/Support/AssertsDriftEvidenceContract.php
Ahmed Darrazi 39fd8ca1ea feat(spec-119): baseline compare drift cutover
- Enrich drift findings evidence_jsonb for diff UX (summary.kind, refs, fidelity, provenance)

- Add baseline policy version resolver and contract asserts

- Remove legacy drift generator + DriftLanding surfaces

- Add one-time cleanup migration for legacy drift findings

- Scope baseline capture/landing warnings to latest inventory sync

- Canonicalize compliance scheduledActionsForRule drift signal
2026-03-06 15:22:42 +01:00

115 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Support;
use PHPUnit\Framework\Assert;
final class AssertsDriftEvidenceContract
{
/**
* @var list<string>
*/
private const array AllowedSummaryKinds = [
'policy_snapshot',
'policy_assignments',
'policy_scope_tags',
];
/**
* @var list<string>
*/
private const array AllowedChangeTypes = [
'missing_policy',
'unexpected_policy',
'different_version',
];
/**
* @var list<string>
*/
private const array AllowedFidelity = [
'content',
'meta',
'mixed',
];
/**
* @param array<string, mixed> $evidence
*/
public static function assertValid(array $evidence): void
{
foreach (['change_type', 'policy_type', 'subject_key', 'summary', 'baseline', 'current', 'fidelity', 'provenance'] as $key) {
Assert::assertArrayHasKey($key, $evidence);
}
$changeType = is_string($evidence['change_type'] ?? null) ? (string) $evidence['change_type'] : '';
Assert::assertContains($changeType, self::AllowedChangeTypes);
$summary = is_array($evidence['summary'] ?? null) ? $evidence['summary'] : [];
Assert::assertArrayHasKey('kind', $summary);
$kind = is_string($summary['kind'] ?? null) ? (string) $summary['kind'] : '';
Assert::assertContains($kind, self::AllowedSummaryKinds);
$baseline = is_array($evidence['baseline'] ?? null) ? $evidence['baseline'] : [];
$current = is_array($evidence['current'] ?? null) ? $evidence['current'] : [];
Assert::assertArrayHasKey('policy_version_id', $baseline);
Assert::assertArrayHasKey('policy_version_id', $current);
$baselineId = is_numeric($baseline['policy_version_id'] ?? null) ? (int) $baseline['policy_version_id'] : null;
$currentId = is_numeric($current['policy_version_id'] ?? null) ? (int) $current['policy_version_id'] : null;
$expectedFidelity = self::expectedFidelity($baselineId, $currentId);
$fidelity = is_string($evidence['fidelity'] ?? null) ? (string) $evidence['fidelity'] : '';
Assert::assertContains($fidelity, self::AllowedFidelity);
Assert::assertSame($expectedFidelity, $fidelity);
$provenance = is_array($evidence['provenance'] ?? null) ? $evidence['provenance'] : [];
foreach (['baseline_profile_id', 'baseline_snapshot_id', 'compare_operation_run_id', 'inventory_sync_run_id'] as $key) {
Assert::assertArrayHasKey($key, $provenance);
}
Assert::assertIsInt($provenance['baseline_profile_id']);
Assert::assertIsInt($provenance['baseline_snapshot_id']);
Assert::assertIsInt($provenance['compare_operation_run_id']);
$inventorySyncRunId = $provenance['inventory_sync_run_id'] ?? null;
Assert::assertTrue($inventorySyncRunId === null || is_numeric($inventorySyncRunId));
}
public static function isDiffRenderable(array $evidence): bool
{
$changeType = is_string($evidence['change_type'] ?? null) ? (string) $evidence['change_type'] : '';
$baseline = is_array($evidence['baseline'] ?? null) ? $evidence['baseline'] : [];
$current = is_array($evidence['current'] ?? null) ? $evidence['current'] : [];
$baselineId = is_numeric($baseline['policy_version_id'] ?? null) ? (int) $baseline['policy_version_id'] : null;
$currentId = is_numeric($current['policy_version_id'] ?? null) ? (int) $current['policy_version_id'] : null;
return match ($changeType) {
'missing_policy' => $baselineId !== null,
'unexpected_policy' => $currentId !== null,
default => $baselineId !== null && $currentId !== null,
};
}
private static function expectedFidelity(?int $baselinePolicyVersionId, ?int $currentPolicyVersionId): string
{
if ($baselinePolicyVersionId !== null && $currentPolicyVersionId !== null) {
return 'content';
}
if ($baselinePolicyVersionId !== null || $currentPolicyVersionId !== null) {
return 'mixed';
}
return 'meta';
}
}