Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m9s
Added ProviderResourceBinding model, migrations, policies, and supporting framework for canonical resource identity mapping as defined in Spec 381.
152 lines
6.4 KiB
PHP
152 lines
6.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Support\EnvironmentReviewCompletenessState;
|
|
use App\Support\ReviewPacks\ReviewPackOutputReadiness;
|
|
use App\Support\ReviewPacks\ReviewPackOutputResolutionGuidance;
|
|
|
|
it('maps publication blockers into one primary guidance state and groups the remaining limitations', function (): void {
|
|
$readiness = spec349Readiness(
|
|
evidenceState: EnvironmentReviewCompletenessState::Partial->value,
|
|
hasReadyExport: false,
|
|
includePii: true,
|
|
publishBlockers: ['Operator approval note is still missing.'],
|
|
requiredSectionStates: [
|
|
EnvironmentReviewCompletenessState::Complete->value => 3,
|
|
EnvironmentReviewCompletenessState::Missing->value => 2,
|
|
],
|
|
);
|
|
|
|
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
|
|
'download' => '/review-packs/1/download',
|
|
'review' => '/environment-reviews/1',
|
|
'evidence' => '/evidence/1',
|
|
'operation' => '/operations/1',
|
|
]);
|
|
|
|
expect($guidance['state'])->toBe('publication_blocked')
|
|
->and($guidance['label'])->toBe('Output not customer-ready')
|
|
->and($guidance['primary_action']['label'])->toBe('Inspect review blockers')
|
|
->and($guidance['action_help'])->toContain('opens the review detail with blockers, evidence status, and next steps')
|
|
->and($guidance['limitations'])->toHaveCount(5)
|
|
->and($guidance['limitations'][0]['key'])->toBe('publish_blockers_present')
|
|
->and(collect($guidance['secondary_actions'])->pluck('label')->all())->not->toContain('Open review')
|
|
->and(collect($guidance['limitations'])->pluck('key')->all())->toEqual([
|
|
'publish_blockers_present',
|
|
'export_not_ready',
|
|
'evidence_basis_incomplete',
|
|
'required_sections_incomplete',
|
|
'contains_pii',
|
|
]);
|
|
});
|
|
|
|
it('maps incomplete evidence to a published-with-limitations guidance item', function (): void {
|
|
$readiness = spec349Readiness(
|
|
evidenceState: EnvironmentReviewCompletenessState::Missing->value,
|
|
hasReadyExport: true,
|
|
);
|
|
|
|
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
|
|
'review' => '/environment-reviews/1',
|
|
'evidence' => '/evidence/1',
|
|
]);
|
|
|
|
expect($guidance['state'])->toBe('published_with_limitations')
|
|
->and($guidance['primary_reason'])->toBe('Evidence basis is incomplete.')
|
|
->and($guidance['primary_action']['label'])->toBe('Open evidence basis')
|
|
->and($guidance['limitations'])->toHaveCount(1)
|
|
->and($guidance['limitations'][0]['label'])->toBe('Evidence basis incomplete');
|
|
});
|
|
|
|
it('renders required section limitation reasons through pluralization instead of raw translation ranges', function (): void {
|
|
$readiness = spec349Readiness(
|
|
hasReadyExport: true,
|
|
requiredSectionStates: [
|
|
EnvironmentReviewCompletenessState::Complete->value => 1,
|
|
EnvironmentReviewCompletenessState::Partial->value => 4,
|
|
EnvironmentReviewCompletenessState::Missing->value => 2,
|
|
],
|
|
);
|
|
|
|
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
|
|
'review' => '/environment-reviews/1',
|
|
]);
|
|
|
|
expect($guidance['limitations'])->toHaveCount(1)
|
|
->and($guidance['limitations'][0]['key'])->toBe('required_sections_incomplete')
|
|
->and($guidance['limitations'][0]['reason'])->toBe('6 required sections are partial, missing, or stale.')
|
|
->and($guidance['limitations'][0]['reason'])->not->toContain('{1}')
|
|
->and($guidance['limitations'][0]['reason'])->not->toContain('[2,*]');
|
|
});
|
|
|
|
it('marks pii-bearing ready exports as internal-only and qualifies the download action', function (): void {
|
|
$readiness = spec349Readiness(
|
|
includePii: true,
|
|
hasReadyExport: true,
|
|
);
|
|
|
|
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
|
|
'download' => '/review-packs/1/download',
|
|
'review' => '/environment-reviews/1',
|
|
]);
|
|
|
|
expect($guidance['state'])->toBe('internal_only')
|
|
->and($guidance['label'])->toBe('Internal review package available')
|
|
->and($guidance['primary_action']['label'])->toBe('Review PII/redaction state')
|
|
->and(collect($guidance['secondary_actions'])->pluck('label')->all())->toContain('Download internal review pack');
|
|
});
|
|
|
|
it('marks complete non-pii exports as customer-safe ready', function (): void {
|
|
$readiness = spec349Readiness(
|
|
hasReadyExport: true,
|
|
);
|
|
|
|
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
|
|
'download' => '/review-packs/1/download',
|
|
'review' => '/environment-reviews/1',
|
|
]);
|
|
|
|
expect($guidance['state'])->toBe('customer_safe_ready')
|
|
->and($guidance['label'])->toBe('Customer-safe review pack ready')
|
|
->and($guidance['primary_action']['label'])->toBe('Download customer-safe review pack')
|
|
->and($guidance)->not->toHaveKey('provider_resource_bindings')
|
|
->and($guidance['limitations'])->toBeEmpty();
|
|
});
|
|
|
|
it('keeps review pack output guidance independent from provider resource bindings', function (): void {
|
|
$guidanceFile = (new ReflectionClass(ReviewPackOutputResolutionGuidance::class))->getFileName();
|
|
|
|
expect($guidanceFile)->toBeString()
|
|
->and(file_get_contents((string) $guidanceFile))->not->toContain('ProviderResourceBinding');
|
|
});
|
|
|
|
/**
|
|
* @param array<string, int> $requiredSectionStates
|
|
* @param list<string> $publishBlockers
|
|
* @return array<string, mixed>
|
|
*/
|
|
function spec349Readiness(
|
|
string $evidenceState = EnvironmentReviewCompletenessState::Complete->value,
|
|
bool $hasReadyExport = true,
|
|
bool $includePii = false,
|
|
array $publishBlockers = [],
|
|
array $requiredSectionStates = [
|
|
EnvironmentReviewCompletenessState::Complete->value => 5,
|
|
],
|
|
): array {
|
|
return ReviewPackOutputReadiness::derive(
|
|
reviewStatus: 'published',
|
|
reviewCompletenessState: EnvironmentReviewCompletenessState::Complete->value,
|
|
evidenceCompletenessState: $evidenceState,
|
|
sectionStateCounts: $requiredSectionStates,
|
|
requiredSectionCount: array_sum($requiredSectionStates),
|
|
requiredSectionStateCounts: $requiredSectionStates,
|
|
publishBlockers: $publishBlockers,
|
|
hasReadyExport: $hasReadyExport,
|
|
includePii: $includePii,
|
|
protectedValuesHidden: true,
|
|
disclosurePresent: true,
|
|
);
|
|
}
|