actingAs($user); Filament::setCurrentPanel('admin'); Filament::setTenant(null, true); Filament::bootCurrentPanel(); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id); return [$user, $tenant]; } function spec354QueueException( ManagedEnvironment $tenant, \App\Models\User $user, array $findingAttributes = [], array $exceptionAttributes = [], ): FindingException { $decisionType = (string) ($exceptionAttributes['decision_type'] ?? \App\Models\FindingExceptionDecision::TYPE_APPROVED); $decisionMetadata = is_array($exceptionAttributes['decision_metadata'] ?? null) ? $exceptionAttributes['decision_metadata'] : []; unset($exceptionAttributes['decision_type']); unset($exceptionAttributes['decision_metadata']); $finding = Finding::factory() ->for($tenant) ->riskAccepted() ->create(array_merge([ 'workspace_id' => (int) $tenant->workspace_id, ], $findingAttributes)); $exception = FindingException::query()->create(array_merge([ 'workspace_id' => (int) $tenant->workspace_id, 'managed_environment_id' => (int) $tenant->getKey(), 'finding_id' => (int) $finding->getKey(), 'requested_by_user_id' => (int) $user->getKey(), 'owner_user_id' => (int) $user->getKey(), 'approved_by_user_id' => (int) $user->getKey(), 'status' => FindingException::STATUS_ACTIVE, 'current_validity_state' => FindingException::VALIDITY_VALID, 'request_reason' => 'Spec354 queue guidance request', 'approval_reason' => 'Spec354 queue approval', 'requested_at' => now()->subDays(5), 'approved_at' => now()->subDays(4), 'effective_from' => now()->subDays(4), 'review_due_at' => now()->addDay(), 'expires_at' => now()->addDays(2), 'evidence_summary' => ['reference_count' => 0], ], $exceptionAttributes)); $decision = $exception->decisions()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'managed_environment_id' => (int) $tenant->getKey(), 'actor_user_id' => (int) $user->getKey(), 'decision_type' => $decisionType, 'reason' => 'Spec354 queue guidance decision', 'metadata' => $decisionMetadata, 'decided_at' => now()->subDays(4), ]); $exception->forceFill(['current_decision_id' => (int) $decision->getKey()])->save(); return $exception->fresh(['finding', 'tenant', 'owner', 'requester', 'currentDecision', 'decisions.actor', 'evidenceReferences']); } it('shows one dominant expiring guidance case with repo-backed secondary actions only', function (): void { [$user, $tenant] = spec354QueueEnvironment(); $expiring = spec354QueueException($tenant, $user); Livewire::withQueryParams([ 'exception' => (int) $expiring->getKey(), ]) ->test(FindingExceptionsQueue::class) ->assertSet('selectedFindingExceptionId', (int) $expiring->getKey()) ->assertSee('data-testid="accepted-risk-guidance-card"', false) ->assertSee(__('localization.accepted_risk_guidance.title_expiring')) ->assertSee(__('localization.accepted_risk_guidance.impact_expiring')) ->assertSee(__('localization.accepted_risk_guidance.action_open_exception')) ->assertSee(__('localization.accepted_risk_guidance.action_open_finding')) ->assertSee(__('localization.accepted_risk_guidance.detail_owner_label')) ->assertDontSee('Fix provider') ->assertDontSee('Grant permissions automatically'); }); it('preserves governance inbox continuity on queue guidance links', function (): void { [$user, $tenant] = spec354QueueEnvironment(); $exception = spec354QueueException($tenant, $user); $context = CanonicalNavigationContext::forGovernanceInbox( canonicalRouteName: GovernanceInbox::getRouteName(Filament::getPanel('admin')), tenantId: (int) $tenant->getKey(), familyKey: 'finding_exceptions', backLinkUrl: GovernanceInbox::getUrl(panel: 'admin', parameters: [ 'environment_id' => (string) $tenant->getKey(), 'family' => 'finding_exceptions', ]), ); $component = Livewire::withQueryParams(array_replace($context->toQuery(), [ 'environment_id' => (int) $tenant->getKey(), 'exception' => (int) $exception->getKey(), ])) ->test(FindingExceptionsQueue::class) ->assertSee(__('localization.accepted_risk_guidance.action_open_exception')) ->assertSee(__('localization.accepted_risk_guidance.action_open_finding')); $guidance = $component->instance()->selectedExceptionGuidance(); $secondaryActions = collect(is_array($guidance['secondary_actions'] ?? null) ? $guidance['secondary_actions'] : []); $openExceptionAction = $secondaryActions->firstWhere('key', 'accepted_risk.expiring.open_exception'); expect($openExceptionAction)->toBeArray() ->and((string) $openExceptionAction['url']) ->toContain('nav%5Bsource_surface%5D=governance.inbox') ->toContain('nav%5Bfamily_key%5D=finding_exceptions'); }); it('keeps queue access workspace scoped and preserves explicit environment filter semantics', function (): void { [$user, $tenant] = spec354QueueEnvironment(); $otherWorkspaceTenant = ManagedEnvironment::factory()->create(); spec354QueueException($tenant, $user); $this->actingAs($user) ->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ]) ->get(FindingExceptionsQueue::getUrl(panel: 'admin', parameters: [ 'environment_id' => (int) $otherWorkspaceTenant->getKey(), ])) ->assertNotFound(); }); it('keeps approve and reject safety intact while rendering guidance without outbound http', function (): void { bindFailHardGraphClient(); [$user, $tenant] = spec354QueueEnvironment(); $pending = spec354QueueException($tenant, $user, exceptionAttributes: [ 'status' => FindingException::STATUS_PENDING, 'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT, 'approved_by_user_id' => null, 'approved_at' => null, 'effective_from' => null, 'approval_reason' => null, 'decision_type' => \App\Models\FindingExceptionDecision::TYPE_REQUESTED, ]); assertNoOutboundHttp(function () use ($pending): void { Livewire::withQueryParams([ 'exception' => (int) $pending->getKey(), ]) ->test(FindingExceptionsQueue::class) ->assertSee(__('localization.accepted_risk_guidance.title_pending')) ->assertActionVisible('approve_selected_exception') ->assertActionVisible('reject_selected_exception') ->mountAction('approve_selected_exception') ->callMountedAction() ->assertHasActionErrors(['approval_reason']); Livewire::withQueryParams([ 'exception' => (int) $pending->getKey(), ]) ->test(FindingExceptionsQueue::class) ->mountAction('reject_selected_exception') ->callMountedAction() ->assertHasActionErrors(['rejection_reason']); }); }); it('keeps expired and expiring carried-over governance dominant over pending renewal on the queue', function (): void { [$user, $tenant] = spec354QueueEnvironment(); $expiredRenewal = spec354QueueException($tenant, $user, exceptionAttributes: [ 'status' => FindingException::STATUS_PENDING, 'current_validity_state' => FindingException::VALIDITY_VALID, 'decision_type' => \App\Models\FindingExceptionDecision::TYPE_RENEWAL_REQUESTED, 'decision_metadata' => [ 'previous_review_due_at' => now()->subDays(2)->toIso8601String(), 'previous_expires_at' => now()->subDay()->toIso8601String(), ], ]); $expiringRenewal = spec354QueueException($tenant, $user, exceptionAttributes: [ 'status' => FindingException::STATUS_PENDING, 'current_validity_state' => FindingException::VALIDITY_VALID, 'decision_type' => \App\Models\FindingExceptionDecision::TYPE_RENEWAL_REQUESTED, 'decision_metadata' => [ 'previous_review_due_at' => now()->addDay()->toIso8601String(), 'previous_expires_at' => now()->addDays(2)->toIso8601String(), ], ]); Livewire::withQueryParams([ 'exception' => (int) $expiredRenewal->getKey(), ]) ->test(FindingExceptionsQueue::class) ->assertSee(__('localization.accepted_risk_guidance.title_expired')); Livewire::withQueryParams([ 'exception' => (int) $expiringRenewal->getKey(), ]) ->test(FindingExceptionsQueue::class) ->assertSee(__('localization.accepted_risk_guidance.title_expiring')) ->assertDontSee(__('localization.accepted_risk_guidance.title_pending_renewal')); }); it('renders localized dominant queue guidance copy for german locale', function (): void { $originalLocale = app()->getLocale(); [$user, $tenant] = spec354QueueEnvironment(); $expiring = spec354QueueException($tenant, $user); app()->setLocale('de'); Livewire::withQueryParams([ 'exception' => (int) $expiring->getKey(), ]) ->test(FindingExceptionsQueue::class) ->assertSee(__('localization.accepted_risk_guidance.reason_expiring')) ->assertSee(__('localization.accepted_risk_guidance.impact_expiring')) ->assertDontSee('The current accepted-risk governance window is still active, but it is nearing expiry and needs review.'); app()->setLocale($originalLocale); });