browser()->timeout(60_000); it('Spec327 smokes non-empty governance inbox decision workbench entry', function (): void { [$user, $environmentA, $environmentB] = spec327GovernanceInboxFixture(); spec327AuthenticateGovernanceInboxBrowser($this, $user, $environmentA); visit(GovernanceInbox::getUrl(panel: 'admin')) ->resize(1440, 1100) ->waitForText('Governance Inbox') ->assertSee('Daily operator queue for governance follow-up, accepted risk, evidence gaps, and review handoff.') ->assertDontSee(__('localization.shell.no_environment_selected')) ->assertDontSee('Environment filter:') ->assertSee('Open governance work') ->assertSee('Primary inbox lanes') ->assertSee('Needs triage') ->assertSee('Requires decision') ->assertSee('Evidence required') ->assertSee('Risk / exception review') ->assertSee('Blocked') ->assertSee('Reason') ->assertSee('Impact') ->assertSee('Environment') ->assertSee('Next recommended action') ->assertSee('More context') ->assertSee('Source detail') ->assertSee($environmentA->name) ->assertSee($environmentB->name) ->assertDontSee('No governance items need attention.') ->assertDontSee('tenant filter') ->assertDontSee('current tenant') ->assertDontSee('entitled tenant') ->assertDontSee('all tenants') ->assertDontSee('raw payload should stay hidden') ->assertDontSee('stack trace should stay hidden') ->assertDontSee('provider secret should stay hidden') ->assertDontSee('debug metadata should stay hidden') ->assertScript('document.querySelector("[data-testid=\"governance-inbox-diagnostics\"]")?.open === false', true) ->assertScript('(() => { const summary = document.querySelector("[data-testid=\"governance-inbox-operator-summary\"]"); const lanes = document.querySelector("[data-testid=\"governance-inbox-lanes\"]"); const sourceDetail = document.querySelector("[data-testid=\"governance-inbox-source-detail\"]"); if (! summary || ! lanes || ! sourceDetail) { return false; } return summary.getBoundingClientRect().top < lanes.getBoundingClientRect().top && lanes.getBoundingClientRect().top < sourceDetail.getBoundingClientRect().top; })()', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec327GovernanceInboxScreenshot('governance-inbox--clean')); spec327CopyBrowserScreenshot('governance-inbox--clean'); spec327CopyBrowserScreenshot('governance-inbox--clean', 'governance-inbox-decision-workbench.png'); }); it('Spec327 smokes filtered governance inbox clear and reload behavior', function (): void { [$user, $environmentA, $environmentB] = spec327GovernanceInboxFixture(); $cleanPath = json_encode((string) parse_url(GovernanceInbox::getUrl(panel: 'admin'), PHP_URL_PATH), JSON_THROW_ON_ERROR); spec327AuthenticateGovernanceInboxBrowser($this, $user, $environmentA); $page = visit(GovernanceInbox::getUrl(panel: 'admin', parameters: [ 'environment_id' => (int) $environmentA->getKey(), ])) ->waitForText('Environment filter:') ->assertSee('Environment filter: '.$environmentA->name) ->assertSee('Open governance work') ->assertSee($environmentA->name) ->assertDontSee($environmentB->name) ->assertScript('document.querySelector("[data-testid=\"governance-inbox-diagnostics\"]")?.open === false', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec327GovernanceInboxScreenshot('governance-inbox--filtered')); spec327CopyBrowserScreenshot('governance-inbox--filtered'); $page ->click('[data-testid="workspace-hub-environment-filter-clear"]') ->waitForText($environmentB->name) ->assertDontSee('Environment filter:') ->assertSee($environmentB->name) ->assertScript("window.location.pathname === {$cleanPath}", true) ->assertScript('! window.location.search.includes("environment_id=")', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec327GovernanceInboxScreenshot('governance-inbox--after-clear')); spec327CopyBrowserScreenshot('governance-inbox--after-clear'); $page->script('window.location.reload();'); $page ->waitForText($environmentB->name) ->assertDontSee('Environment filter:') ->assertSee($environmentB->name) ->assertScript("window.location.pathname === {$cleanPath}", true) ->assertScript('! window.location.search.includes("environment_id=")', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec327GovernanceInboxScreenshot('governance-inbox--after-reload')); spec327CopyBrowserScreenshot('governance-inbox--after-reload'); }); it('Spec327 smokes governance inbox secondary disclosures', function (): void { [$user, $environmentA] = spec327GovernanceInboxFixture(); spec327AuthenticateGovernanceInboxBrowser($this, $user, $environmentA); visit(GovernanceInbox::getUrl(panel: 'admin')) ->waitForText('Source detail') ->assertSee('Source detail') ->assertScript('document.querySelector("[data-testid=\"governance-inbox-diagnostics\"]")?.open === false', true) ->click('[data-testid="governance-inbox-diagnostics"] summary') ->assertScript('document.querySelector("[data-testid=\"governance-inbox-diagnostics\"]")?.open === true', true) ->assertSee('Raw diagnostics, payloads, and support detail stay on authorized source surfaces') ->click('[data-testid="governance-inbox-source-detail"] summary') ->assertScript('document.querySelector("[data-testid=\"governance-inbox-source-detail\"]")?.open === true', true) ->assertSee('Source-family context') ->assertDontSee('raw payload should stay hidden') ->assertDontSee('internal exception should stay hidden') ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec327GovernanceInboxScreenshot('governance-inbox--diagnostics')); spec327CopyBrowserScreenshot('governance-inbox--diagnostics'); }); /** * @return array{0: User, 1: ManagedEnvironment, 2: ManagedEnvironment} */ function spec327GovernanceInboxFixture(): array { $environmentA = ManagedEnvironment::factory()->active()->create([ 'name' => 'Spec327 Browser Environment A', 'external_id' => 'spec327-browser-environment-a', ]); [$user, $environmentA] = createUserWithTenant( tenant: $environmentA, role: 'owner', workspaceRole: 'owner', ); $environmentB = ManagedEnvironment::factory()->active()->create([ 'workspace_id' => (int) $environmentA->workspace_id, 'name' => 'Spec327 Browser Environment B', 'external_id' => 'spec327-browser-environment-b', ]); createUserWithTenant( tenant: $environmentB, user: $user, role: 'owner', workspaceRole: 'owner', ); Finding::factory() ->for($environmentA) ->assignedTo((int) $user->getKey()) ->ownedBy((int) $user->getKey()) ->overdueByHours() ->create([ 'workspace_id' => (int) $environmentA->workspace_id, 'subject_external_id' => 'spec327-browser-priority-a', 'severity' => Finding::SEVERITY_HIGH, 'evidence_jsonb' => [ 'summary' => [ 'kind' => 'policy_snapshot', 'raw_payload' => 'raw payload should stay hidden', 'stack_trace' => 'stack trace should stay hidden', 'provider_secret' => 'provider secret should stay hidden', 'debug_metadata' => 'debug metadata should stay hidden', 'internal_exception' => 'internal exception should stay hidden', ], ], ]); Finding::factory() ->for($environmentB) ->reopened() ->create([ 'workspace_id' => (int) $environmentB->workspace_id, 'subject_external_id' => 'spec327-browser-secondary-b', 'severity' => Finding::SEVERITY_MEDIUM, 'owner_user_id' => null, 'assignee_user_id' => null, 'due_at' => now()->addDays(14), 'evidence_jsonb' => [], ]); return [$user, $environmentA, $environmentB]; } function spec327AuthenticateGovernanceInboxBrowser( mixed $test, User $user, ManagedEnvironment $rememberedEnvironment, ): void { $workspaceId = (int) $rememberedEnvironment->workspace_id; $session = [ WorkspaceContext::SESSION_KEY => $workspaceId, WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [ (string) $workspaceId => (int) $rememberedEnvironment->getKey(), ], ]; $test->actingAs($user)->withSession($session); foreach ($session as $key => $value) { session()->put($key, $value); } setAdminPanelContext($rememberedEnvironment); } function spec327GovernanceInboxScreenshot(string $name): string { return 'spec327-'.$name; } function spec327CopyBrowserScreenshot(string $name, ?string $targetFilename = null): void { $filename = spec327GovernanceInboxScreenshot($name).'.png'; $source = \Pest\Browser\Support\Screenshot::path($filename); $targetDirectory = repo_path('specs/327-governance-inbox-decision-first-workbench-productization/artifacts/screenshots'); $targetFilename ??= $filename; if (! is_dir($targetDirectory)) { @mkdir($targetDirectory, 0755, true); } if (! is_dir($targetDirectory) || ! is_writable($targetDirectory)) { return; } if (is_file($source)) { @copy($source, $targetDirectory.DIRECTORY_SEPARATOR.$targetFilename); } }