TenantAtlas/apps/platform/tests/Feature/Navigation/Spec346GovernanceInboxScopeContractTest.php
ahmido 8cffdbdb2c feat: governance inbox final operator workflow (spec 346) (#418)
Implemented the final operator workflow for the Governance Inbox. This includes refactoring the inbox page, updating finding resources, adding UI enforcement policies, updating related blade views, and adding comprehensive tests for operator workflow and scope contracts.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #418
2026-06-02 14:58:39 +00:00

164 lines
6.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\Governance\DecisionRegister;
use App\Filament\Pages\Governance\GovernanceInbox;
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentTriageReview;
use App\Models\User;
use App\Support\BackupHealth\TenantBackupHealthResolver;
use App\Support\PortfolioTriage\ManagedEnvironmentTriageReviewFingerprint;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\Workspaces\WorkspaceContext;
it('renders the canonical environment filter and scope-correct workspace-hub links on the governance inbox', function (): void {
[$user, $environmentA, $environmentB, $records] = spec346GovernanceInboxScopeFixture();
$response = $this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $environmentA->workspace_id])
->get(GovernanceInbox::getUrl(panel: 'admin', parameters: [
'environment_id' => (int) $environmentA->getKey(),
]));
$response
->assertOk()
->assertSee('Environment filter:')
->assertSee($environmentA->name)
->assertSee('Clear filter')
->assertSee(GovernanceInbox::getUrl(panel: 'admin'), false)
->assertSee((string) parse_url(FindingExceptionsQueue::getUrl(panel: 'admin'), PHP_URL_PATH), false)
->assertSee('environment_id='.(int) $environmentA->getKey(), false)
->assertSee('exception='.(int) $records['exception']->getKey(), false)
->assertSee(CustomerReviewWorkspace::environmentFilterUrl($environmentA), false)
->assertSee(DecisionRegister::getUrl(panel: 'admin', parameters: [
'environment_id' => (int) $environmentA->getKey(),
]), false)
->assertSee(route('admin.evidence.overview', [
'environment_id' => (int) $environmentA->getKey(),
]), false)
->assertDontSee('environment_id='.(int) $environmentB->getKey(), false)
->assertDontSee('tenant=', false)
->assertDontSee('tenant_id=', false)
->assertDontSee('managed_environment_id=', false)
->assertDontSee('tenant_scope=', false)
->assertDontSee('tableFilters', false);
});
it('keeps clean governance inbox entry unfiltered and ignores retired environment query aliases', function (): void {
[$user, $environmentA, $environmentB] = spec346GovernanceInboxScopeFixture();
$this->actingAs($user)
->withSession([
WorkspaceContext::SESSION_KEY => (int) $environmentA->workspace_id,
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $environmentA->workspace_id => (int) $environmentA->getKey(),
],
])
->get(GovernanceInbox::getUrl(panel: 'admin'))
->assertOk()
->assertDontSee('Environment filter:')
->assertSee($environmentB->name);
$legacyQueries = [
['tenant' => (string) $environmentA->getKey()],
['tenant_id' => (int) $environmentA->getKey()],
['managed_environment_id' => (int) $environmentA->getKey()],
['environment' => (string) $environmentA->getKey()],
['tenant_scope' => 'environment'],
['tableFilters' => ['managed_environment_id' => ['value' => (string) $environmentA->getKey()]]],
];
foreach ($legacyQueries as $query) {
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $environmentA->workspace_id])
->get(GovernanceInbox::getUrl(panel: 'admin', parameters: $query))
->assertOk()
->assertDontSee('Environment filter:')
->assertSee($environmentB->name);
}
});
/**
* @return array{0: User, 1: ManagedEnvironment, 2: ManagedEnvironment, 3: array{exception: FindingException}}
*/
function spec346GovernanceInboxScopeFixture(): array
{
$environmentA = ManagedEnvironment::factory()->active()->create([
'name' => 'Spec346 Scope Environment Alpha',
'external_id' => 'spec346-scope-environment-alpha',
]);
[$user, $environmentA] = createUserWithTenant($environmentA, role: 'owner', workspaceRole: 'owner');
$environmentB = ManagedEnvironment::factory()->active()->create([
'workspace_id' => (int) $environmentA->workspace_id,
'name' => 'Spec346 Scope Environment Beta',
'external_id' => 'spec346-scope-environment-beta',
]);
createUserWithTenant($environmentB, user: $user, role: 'owner', workspaceRole: 'owner');
Finding::factory()
->for($environmentB)
->create([
'workspace_id' => (int) $environmentB->workspace_id,
'status' => Finding::STATUS_NEW,
'owner_user_id' => null,
'assignee_user_id' => null,
'evidence_jsonb' => [],
]);
Finding::factory()
->for($environmentA)
->assignedTo((int) $user->getKey())
->ownedBy((int) $user->getKey())
->create([
'workspace_id' => (int) $environmentA->workspace_id,
'status' => Finding::STATUS_IN_PROGRESS,
'evidence_jsonb' => [],
]);
$exceptionFinding = Finding::factory()
->for($environmentA)
->riskAccepted()
->create([
'workspace_id' => (int) $environmentA->workspace_id,
]);
$exception = FindingException::query()->create([
'workspace_id' => (int) $environmentA->workspace_id,
'managed_environment_id' => (int) $environmentA->getKey(),
'finding_id' => (int) $exceptionFinding->getKey(),
'requested_by_user_id' => (int) $user->getKey(),
'owner_user_id' => (int) $user->getKey(),
'status' => FindingException::STATUS_PENDING,
'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT,
'request_reason' => 'Spec346 scope contract exception',
'requested_at' => now()->subDay(),
'review_due_at' => now()->addDays(2),
'evidence_summary' => ['reference_count' => 0],
]);
$backupHealthResolver = app(TenantBackupHealthResolver::class);
$fingerprints = app(ManagedEnvironmentTriageReviewFingerprint::class);
$fingerprint = $fingerprints->forBackupHealth($backupHealthResolver->assess($environmentA));
ManagedEnvironmentTriageReview::factory()
->for($environmentA)
->followUpNeeded()
->create([
'workspace_id' => (int) $environmentA->workspace_id,
'reviewed_by_user_id' => (int) $user->getKey(),
'concern_family' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
'review_fingerprint' => $fingerprint['fingerprint'],
'review_snapshot' => $fingerprint['snapshot'],
]);
return [$user, $environmentA, $environmentB, [
'exception' => $exception,
]];
}