forBackupItem(new BackupItem([ 'payload' => [], 'assignments' => [], 'metadata' => [ 'source' => 'metadata_only', 'assignments_fetch_failed' => true, 'has_orphaned_assignments' => true, 'integrity_warning' => 'Protected values are intentionally hidden.', 'assignment_capture_reason' => 'separate_role_assignments', ], ])); expect($summary->snapshotMode)->toBe('metadata_only') ->and($summary->hasAssignmentIssues)->toBeTrue() ->and($summary->hasOrphanedAssignments)->toBeTrue() ->and($summary->hasIntegrityWarning())->toBeTrue() ->and($summary->degradationFamilies)->toBe([ 'metadata_only', 'assignment_capture_issue', 'orphaned_assignments', 'integrity_warning', ]) ->and($summary->qualityHighlights)->toContain( 'Metadata only', 'Assignment fetch failed', 'Orphaned assignments', 'Integrity warning', ); }); it('uses unknown quality only when backup item metadata cannot justify a stronger claim', function (): void { $resolver = app(BackupQualityResolver::class); $unknownSummary = $resolver->forBackupItem(new BackupItem([ 'payload' => [], 'assignments' => [], 'metadata' => [], ])); $assignmentIssueSummary = $resolver->forBackupItem(new BackupItem([ 'payload' => [], 'assignments' => [], 'metadata' => [ 'assignments_fetch_failed' => true, ], ])); expect($unknownSummary->degradationFamilies)->toBe(['unknown_quality']) ->and($unknownSummary->compactSummary)->toBe('Unknown quality') ->and($assignmentIssueSummary->degradationFamilies)->toBe(['assignment_capture_issue']) ->and($assignmentIssueSummary->qualityHighlights)->not->toContain('Unknown quality'); }); it('derives policy version integrity warnings from existing redaction context', function (): void { $summary = app(BackupQualityResolver::class)->forPolicyVersion(new PolicyVersion([ 'snapshot' => [ 'id' => 'policy-1', 'displayName' => 'Policy One', ], 'metadata' => [ 'assignments_fetch_failed' => true, ], 'secret_fingerprints' => [ 'snapshot' => ['/clientSecret' => 'abc123'], 'assignments' => [], 'scope_tags' => [], ], ])); expect($summary->snapshotMode)->toBe('full') ->and($summary->hasAssignmentIssues)->toBeTrue() ->and($summary->integrityWarning)->toBe(RedactionIntegrity::protectedValueNote()) ->and($summary->degradationFamilies)->toBe([ 'assignment_capture_issue', 'integrity_warning', ]); });