feat: migrate dashboard inbox table contracts to productized flow #470
@ -132,11 +132,11 @@ public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->query(fn (): Builder => $this->queueViewQuery())
|
||||
->paginated(TablePaginationProfiles::customPage())
|
||||
->paginated(TablePaginationProfiles::productSurface())
|
||||
->persistFiltersInSession()
|
||||
->columns([
|
||||
TextColumn::make('tenant.name')
|
||||
->label('ManagedEnvironment'),
|
||||
->label('Managed environment'),
|
||||
TextColumn::make('subject_display_name')
|
||||
->label('Finding')
|
||||
->state(fn (Finding $record): string => $record->resolvedSubjectDisplayName() ?? 'Finding #'.$record->getKey())
|
||||
@ -168,7 +168,7 @@ public function table(Table $table): Table
|
||||
])
|
||||
->filters([
|
||||
SelectFilter::make('managed_environment_id')
|
||||
->label('ManagedEnvironment')
|
||||
->label('Managed environment')
|
||||
->options(fn (): array => $this->tenantFilterOptions())
|
||||
->searchable(),
|
||||
])
|
||||
|
||||
@ -124,7 +124,7 @@ public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->query(fn (): Builder => $this->queueBaseQuery())
|
||||
->paginated(TablePaginationProfiles::customPage())
|
||||
->paginated(TablePaginationProfiles::productSurface())
|
||||
->persistFiltersInSession()
|
||||
->columns([
|
||||
TextColumn::make('tenant.name')
|
||||
|
||||
@ -329,7 +329,7 @@ public function landingHierarchySummary(): array
|
||||
'scope_reset_body' => $activeEnvironment instanceof ManagedEnvironment
|
||||
? 'Reset Operations Hub back to workspace-wide execution records when environment-specific context is no longer needed.'
|
||||
: null,
|
||||
'inspect_body' => 'Open a run from the table to enter the canonical monitoring detail viewer.',
|
||||
'inspect_body' => 'Open an operation from the table to enter the canonical monitoring detail viewer.',
|
||||
];
|
||||
}
|
||||
|
||||
@ -465,7 +465,6 @@ private function workbenchOperationPayload(OperationRun $run, bool $hasAttention
|
||||
return [
|
||||
'id' => (int) $run->getKey(),
|
||||
'title' => OperationCatalog::label((string) $run->type),
|
||||
'identifier' => OperationRunLinks::identifier($run),
|
||||
'status_label' => $this->humanizeState((string) $run->status),
|
||||
'outcome_label' => $this->humanizeState((string) $run->outcome),
|
||||
'attention_label' => $hasAttention && $run->requiresOperatorReview()
|
||||
@ -475,8 +474,8 @@ private function workbenchOperationPayload(OperationRun $run, bool $hasAttention
|
||||
'impact' => $this->operationImpact($run),
|
||||
'environment' => $tenant instanceof ManagedEnvironment ? (string) $tenant->name : 'Workspace-level operation',
|
||||
'timing' => $this->operationTiming($run),
|
||||
'proof_label' => 'Operation detail available',
|
||||
'proof_body' => (string) ($actionDecision['attention_reason'] ?? 'Open operation for stored proof, related links, and authorized diagnostics.'),
|
||||
'proof_label' => 'Technical detail available',
|
||||
'proof_body' => (string) ($actionDecision['attention_reason'] ?? 'Open details for stored technical context, related links, and authorized diagnostics.'),
|
||||
'primary_action_label' => is_string($primaryAction['label'] ?? null)
|
||||
? (string) $primaryAction['label']
|
||||
: OperationRunLinks::openLabel(),
|
||||
@ -511,12 +510,12 @@ private function operationReason(OperationRun $run, array $decisionTruth): strin
|
||||
}
|
||||
|
||||
return match ((string) $run->outcome) {
|
||||
OperationRunOutcome::Blocked->value => 'The operation is blocked by an execution prerequisite recorded on the run.',
|
||||
OperationRunOutcome::Blocked->value => 'The operation is blocked by an execution prerequisite recorded on the operation.',
|
||||
OperationRunOutcome::Failed->value => 'The operation finished with a failed outcome and needs review before retrying or relying on the result.',
|
||||
OperationRunOutcome::PartiallySucceeded->value => 'The operation finished partially and needs follow-up on affected items.',
|
||||
OperationRunOutcome::Succeeded->value => 'The operation completed successfully. This is execution truth only, not an environment health claim.',
|
||||
default => $run->isCurrentlyActive()
|
||||
? 'The operation is still active. Progress is shown only from trusted run counts.'
|
||||
? 'The operation is still active. Progress is shown only from trusted progress counts.'
|
||||
: 'Reason unavailable from stored operation truth.',
|
||||
};
|
||||
}
|
||||
@ -531,9 +530,9 @@ private function operationImpact(OperationRun $run): string
|
||||
OperationRunOutcome::Blocked->value => 'Execution did not proceed; inspect the blocked prerequisite before retrying from the source surface.',
|
||||
OperationRunOutcome::Failed->value => 'The expected result may be incomplete or unavailable until the failure is reviewed.',
|
||||
OperationRunOutcome::PartiallySucceeded->value => 'Some work completed, but affected items may still require review or a targeted rerun.',
|
||||
OperationRunOutcome::Succeeded->value => 'Execution completed; use operation detail for proof rather than treating this as governance health.',
|
||||
OperationRunOutcome::Succeeded->value => 'Execution completed; use operation detail for technical context rather than treating this as governance health.',
|
||||
default => $run->isCurrentlyActive()
|
||||
? 'Work is in progress; avoid duplicate starts until this run settles or becomes stale.'
|
||||
? 'Work is in progress; avoid duplicate starts until this operation settles or needs attention.'
|
||||
: 'Impact unavailable from stored operation truth.',
|
||||
};
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
|
||||
return ActionSurfaceDeclaration::forResource(ActionSurfaceProfile::CrudListAndView)
|
||||
->satisfy(ActionSurfaceSlot::ListHeader, 'Header actions support filtered findings operations (legacy acknowledge-all-matching remains until bulk workflow migration).')
|
||||
->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
|
||||
->satisfy(ActionSurfaceSlot::ListRowMoreMenu, 'Secondary workflow actions are grouped under "More"; the only inline row action is the related-record drill-down.')
|
||||
->satisfy(ActionSurfaceSlot::ListRowMoreMenu, 'Related-record and workflow actions are grouped under "More"; the clickable row remains the primary inspect affordance.')
|
||||
->satisfy(ActionSurfaceSlot::ListBulkMoreGroup, 'Bulk actions are grouped under "More".')
|
||||
->exempt(ActionSurfaceSlot::ListEmptyState, 'Findings are generated by drift detection and intentionally have no create CTA.')
|
||||
->satisfy(ActionSurfaceSlot::DetailHeader, 'View page exposes capability-gated workflow actions for finding lifecycle management.');
|
||||
@ -781,7 +781,7 @@ public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->defaultSort('created_at', 'desc')
|
||||
->paginated(TablePaginationProfiles::resource())
|
||||
->paginated(TablePaginationProfiles::productSurface())
|
||||
->persistFiltersInSession()
|
||||
->persistSearchInSession()
|
||||
->persistSortInSession()
|
||||
@ -1011,8 +1011,8 @@ public static function table(Table $table): Table
|
||||
])
|
||||
->recordUrl(static fn (Finding $record): string => static::getUrl('view', ['record' => $record]))
|
||||
->actions([
|
||||
static::primaryRelatedAction(),
|
||||
Actions\ActionGroup::make([
|
||||
static::primaryRelatedAction(),
|
||||
...static::workflowActions(),
|
||||
])
|
||||
->label('More')
|
||||
|
||||
@ -136,7 +136,7 @@ public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->defaultSort('created_at', 'desc')
|
||||
->paginated(TablePaginationProfiles::resource())
|
||||
->paginated(TablePaginationProfiles::productSurface())
|
||||
->persistFiltersInSession()
|
||||
->persistSearchInSession()
|
||||
->persistSortInSession()
|
||||
|
||||
@ -4,12 +4,12 @@
|
||||
|
||||
namespace App\Filament\Widgets\Dashboard;
|
||||
|
||||
use App\Models\OperationRun;
|
||||
use App\Models\ManagedEnvironment;
|
||||
use App\Models\OperationRun;
|
||||
use App\Support\Badges\BadgeDomain;
|
||||
use App\Support\Badges\BadgeRenderer;
|
||||
use App\Support\Filament\TablePaginationProfiles;
|
||||
use App\Support\OperationCatalog;
|
||||
use App\Support\OperationRunLinks;
|
||||
use App\Support\OpsUx\ActiveRuns;
|
||||
use App\Support\OpsUx\OperationUxPresenter;
|
||||
use Filament\Facades\Filament;
|
||||
@ -31,13 +31,8 @@ public function table(Table $table): Table
|
||||
->query($this->getQuery())
|
||||
->poll(fn (): ?string => ActiveRuns::pollingIntervalForTenant($tenant instanceof ManagedEnvironment ? $tenant : null))
|
||||
->defaultSort('created_at', 'desc')
|
||||
->paginated(\App\Support\Filament\TablePaginationProfiles::widget())
|
||||
->paginated(TablePaginationProfiles::productSurface())
|
||||
->columns([
|
||||
TextColumn::make('short_id')
|
||||
->label(OperationRunLinks::identifierLabel())
|
||||
->state(fn (OperationRun $record): string => OperationRunLinks::identifier($record))
|
||||
->copyable()
|
||||
->copyableState(fn (OperationRun $record): string => (string) $record->getKey()),
|
||||
TextColumn::make('type')
|
||||
->label('Operation')
|
||||
->sortable()
|
||||
@ -95,9 +90,7 @@ public function table(Table $table): Table
|
||||
->sortable()
|
||||
->since(),
|
||||
])
|
||||
->recordUrl(fn (OperationRun $record): ?string => $tenant instanceof ManagedEnvironment
|
||||
? OperationRunLinks::view($record, $tenant)
|
||||
: null)
|
||||
->recordUrl(null)
|
||||
->emptyStateHeading('No operations yet')
|
||||
->emptyStateDescription('Once you run inventory sync, drift generation, or restores, they\'ll show up here.');
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ protected function getStats(): array
|
||||
key: 'needs-attention',
|
||||
label: 'Needs attention',
|
||||
value: $needsAttention,
|
||||
description: 'Failed, blocked, partial, or stale OperationRuns in scope.',
|
||||
description: 'Failed, blocked, partial, or stale operations in scope.',
|
||||
color: $needsAttention > 0 ? 'warning' : 'gray',
|
||||
descriptionIcon: 'heroicon-m-exclamation-triangle',
|
||||
),
|
||||
|
||||
@ -45,4 +45,12 @@ public static function customPage(): array
|
||||
{
|
||||
return [25, 50, 'all'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int>
|
||||
*/
|
||||
public static function productSurface(): array
|
||||
{
|
||||
return [8, 25, 50];
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
<p class="text-xs font-medium uppercase text-gray-500 dark:text-gray-400">Operations Hub</p>
|
||||
<h2 class="text-2xl font-semibold text-gray-950 dark:text-white">Execution follow-up</h2>
|
||||
<p class="text-sm leading-6 text-gray-600 dark:text-gray-300">
|
||||
Scan active, stale, failed, and partial OperationRuns. Open proof or the one safe next action without exposing diagnostics by default.
|
||||
Scan active, stale, failed, and partial operations. Open the one safe next action without exposing diagnostics by default.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
<div class="mt-5 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-800 dark:bg-gray-950/40" data-testid="operations-hub-no-attention-state">
|
||||
<h3 class="text-base font-semibold text-gray-950 dark:text-white">No operations need follow-up</h3>
|
||||
<p class="mt-1 text-sm leading-6 text-gray-600 dark:text-gray-300">
|
||||
No failed, blocked, partial, or stale OperationRuns are visible in this scope.
|
||||
No failed, blocked, partial, or stale operations are visible in this scope.
|
||||
</p>
|
||||
</div>
|
||||
@endif
|
||||
@ -81,16 +81,13 @@
|
||||
<div class="mt-5 rounded-lg border border-dashed border-gray-300 bg-gray-50 p-5 dark:border-gray-700 dark:bg-gray-950/40" data-testid="operations-hub-empty-record-state">
|
||||
<h3 class="text-base font-semibold text-gray-950 dark:text-white">No operation records are visible</h3>
|
||||
<p class="mt-1 text-sm leading-6 text-gray-600 dark:text-gray-300">
|
||||
Queued, running, and completed OperationRuns will appear here when work is triggered in this workspace scope.
|
||||
Queued, running, and completed operations will appear here when work is triggered in this workspace scope.
|
||||
</p>
|
||||
</div>
|
||||
@else
|
||||
<div class="mt-5 space-y-5">
|
||||
<div class="space-y-2">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<x-filament::badge color="gray" size="sm">
|
||||
{{ $selectedOperation['identifier'] }}
|
||||
</x-filament::badge>
|
||||
<x-filament::badge color="gray" size="sm">
|
||||
Environment: {{ $selectedOperation['environment'] }}
|
||||
</x-filament::badge>
|
||||
@ -179,7 +176,7 @@
|
||||
<p class="mt-1 text-gray-800 dark:text-gray-100">{{ $selectedOperation['environment'] }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Proof</p>
|
||||
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Detail path</p>
|
||||
<p class="mt-1 text-gray-800 dark:text-gray-100">{{ $selectedOperation['proof_label'] }}</p>
|
||||
<p class="mt-1 text-gray-600 dark:text-gray-300">{{ $selectedOperation['proof_body'] }}</p>
|
||||
</div>
|
||||
@ -207,8 +204,8 @@ class="mt-2 w-full"
|
||||
<p class="mt-1 text-gray-800 dark:text-gray-100">Unavailable</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Proof</p>
|
||||
<p class="mt-1 text-gray-800 dark:text-gray-100">Proof unavailable</p>
|
||||
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Detail path</p>
|
||||
<p class="mt-1 text-gray-800 dark:text-gray-100">Detail unavailable</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Primary next action</p>
|
||||
@ -231,9 +228,9 @@ class="mt-2 w-full"
|
||||
|
||||
<section class="space-y-4" data-testid="operations-hub-secondary-history">
|
||||
<div class="space-y-1">
|
||||
<h2 class="text-lg font-semibold text-gray-950 dark:text-white">Recent runs</h2>
|
||||
<h2 class="text-lg font-semibold text-gray-950 dark:text-white">Recent operations</h2>
|
||||
<p class="text-sm leading-6 text-gray-600 dark:text-gray-300">
|
||||
Chronological operation record. Use tabs for attention states; open a row for proof and authorized diagnostics.
|
||||
Chronological operation record. Use tabs for attention states; open a row only when technical details are needed.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -260,7 +257,7 @@ class="mt-2 w-full"
|
||||
tag="a"
|
||||
:spa-mode="true"
|
||||
>
|
||||
Likely stale
|
||||
Needs attention
|
||||
</x-filament::tabs.item>
|
||||
<x-filament::tabs.item
|
||||
:active="$this->activeTab === $terminalFollowUpTab"
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
<x-filament::section heading="Recent operations">
|
||||
<p class="mb-4 text-xs leading-5 text-gray-500 dark:text-gray-400">
|
||||
Diagnostic recency across your visible workspace slice. This does not define governance health on its own.
|
||||
</p>
|
||||
<x-filament::section heading="Operations detail">
|
||||
<details data-testid="workspace-recent-operations-disclosure">
|
||||
<summary class="cursor-pointer text-sm font-medium text-gray-700 dark:text-gray-200">
|
||||
Review recent workspace activity
|
||||
</summary>
|
||||
|
||||
@if ($operations === [])
|
||||
<div class="flex h-full flex-col justify-between gap-4">
|
||||
<p class="mt-3 text-xs leading-5 text-gray-500 dark:text-gray-400">
|
||||
Diagnostic recency across your visible workspace slice. This does not define governance health on its own.
|
||||
</p>
|
||||
|
||||
@if ($operations === [])
|
||||
<div class="mt-4 flex h-full flex-col justify-between gap-4">
|
||||
<div class="space-y-2">
|
||||
<p class="text-sm font-medium text-gray-950 dark:text-white">
|
||||
{{ $emptyState['title'] ?? 'No recent operations yet' }}
|
||||
@ -23,8 +28,8 @@
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div class="space-y-3">
|
||||
@else
|
||||
<div class="mt-4 space-y-3">
|
||||
@foreach ($operations as $operation)
|
||||
@php
|
||||
$destination = $operation['destination'] ?? null;
|
||||
@ -84,5 +89,6 @@
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</details>
|
||||
</x-filament::section>
|
||||
|
||||
@ -38,11 +38,11 @@
|
||||
->assertSee('Reason')
|
||||
->assertSee('Impact')
|
||||
->assertSee($environmentA->name)
|
||||
->assertSee('Proof')
|
||||
->assertSee('Operation detail available')
|
||||
->assertSee('Detail path')
|
||||
->assertSee('Technical detail available')
|
||||
->assertSee('Primary next action')
|
||||
->assertSee('Next action')
|
||||
->assertSee('Recent runs')
|
||||
->assertSee('Recent operations')
|
||||
->assertSee('Policy sync')
|
||||
->assertSee('View affected families')
|
||||
->assertDontSee('tenant filter')
|
||||
@ -224,8 +224,8 @@
|
||||
visit(OperationRunLinks::index(workspace: $environment->workspace))
|
||||
->waitForText('Operations Hub')
|
||||
->assertSee('No operations need follow-up')
|
||||
->assertSee('No failed, blocked, partial, or stale OperationRuns are visible in this scope.')
|
||||
->assertSee('Operation detail available')
|
||||
->assertSee('No failed, blocked, partial, or stale operations are visible in this scope.')
|
||||
->assertSee('Technical detail available')
|
||||
->assertDontSee('environment is healthy')
|
||||
->assertDontSee('governance health is complete')
|
||||
->assertNoJavaScriptErrors()
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
->assertSee('Environment filter: '.$environment->name)
|
||||
->assertSee('Which operation needs attention now?')
|
||||
->assertSee('Inventory sync')
|
||||
->assertSee('Recent runs')
|
||||
->assertSee('Recent operations')
|
||||
->assertDontSee('Spec391 browser hidden sibling operator')
|
||||
->assertDontSee('Maximum execution time')
|
||||
->assertDontSee('HasAttributes.php')
|
||||
|
||||
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Filament\Pages\Findings\FindingsIntakeQueue;
|
||||
use App\Filament\Pages\Findings\MyFindingsInbox;
|
||||
use App\Filament\Pages\Governance\GovernanceInbox;
|
||||
use App\Filament\Resources\FindingResource;
|
||||
use App\Http\Middleware\SuppressDebugbarForSmokeRequests;
|
||||
use App\Models\Finding;
|
||||
use App\Models\ManagedEnvironment;
|
||||
use App\Models\OperationRun;
|
||||
use App\Models\User;
|
||||
use App\Support\ManagedEnvironmentLinks;
|
||||
use App\Support\OperationRunLinks;
|
||||
use App\Support\OperationRunOutcome;
|
||||
use App\Support\OperationRunStatus;
|
||||
use App\Support\Workspaces\WorkspaceContext;
|
||||
|
||||
pest()->browser()->timeout(120_000);
|
||||
|
||||
it('Spec399 smokes dashboard, inbox, findings, and operations product-surface defaults', function (): void {
|
||||
[$user, $environment] = spec399BrowserFixture();
|
||||
|
||||
spec399AuthenticateBrowser($this, $user, $environment);
|
||||
|
||||
visit(route('admin.workspace.home', ['workspace' => $environment->workspace]))
|
||||
->resize(1440, 1100)
|
||||
->waitForText('Needs attention')
|
||||
->assertSee('Review recent workspace activity')
|
||||
->assertScript('document.querySelector("[data-testid=\"workspace-recent-operations-disclosure\"]")?.hasAttribute("open") === false', true)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
visit(ManagedEnvironmentLinks::viewUrl($environment))
|
||||
->resize(1440, 1100)
|
||||
->waitForText($environment->name)
|
||||
->assertDontSee('spec399 browser raw payload should stay hidden')
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
visit(GovernanceInbox::getUrl(panel: 'admin'))
|
||||
->resize(1440, 1100)
|
||||
->waitForText('Governance Inbox')
|
||||
->assertSee('Primary inbox lanes')
|
||||
->assertSee('Needs triage')
|
||||
->assertScript('document.querySelector("[data-testid=\"governance-inbox-lane-needs_triage\"]") !== null', true)
|
||||
->assertScript(<<<'JS'
|
||||
(() => {
|
||||
const lane = document.querySelector('[data-testid="governance-inbox-lane-needs_triage"]');
|
||||
const item = lane?.querySelector('[data-testid^="governance-inbox-item-needs_triage"]');
|
||||
const details = item?.querySelector('details');
|
||||
|
||||
return Boolean(item)
|
||||
&& Boolean(item.querySelector('a[href]'))
|
||||
&& details instanceof HTMLDetailsElement
|
||||
&& details.open === false;
|
||||
})()
|
||||
JS, true)
|
||||
->assertDontSee('spec399 browser raw payload should stay hidden')
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
visit(MyFindingsInbox::getUrl(panel: 'admin'))
|
||||
->resize(1440, 1100)
|
||||
->waitForText('My findings')
|
||||
->waitForText('Spec399 Browser Assigned Finding 10')
|
||||
->assertSee('Managed environment')
|
||||
->assertDontSee('spec399-browser-source-key')
|
||||
->assertScript('(() => { const rows = document.querySelectorAll("table tbody tr"); return rows.length > 0 && rows.length <= 8; })()', true)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
visit(FindingsIntakeQueue::getUrl(panel: 'admin'))
|
||||
->resize(1440, 1100)
|
||||
->waitForText('Findings intake')
|
||||
->waitForText('Spec399 Browser Intake Finding 10')
|
||||
->assertSee('Managed environment')
|
||||
->assertDontSee('spec399-browser-intake-key')
|
||||
->assertScript('(() => { const rows = document.querySelectorAll("table tbody tr"); return rows.length > 0 && rows.length <= 8; })()', true)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
visit(FindingResource::getUrl('index', tenant: $environment, panel: 'admin'))
|
||||
->resize(1440, 1100)
|
||||
->waitForText('Findings')
|
||||
->assertDontSee('spec399-browser-source-key')
|
||||
->assertDontSee('spec399-browser-intake-key')
|
||||
->assertScript('(() => { const rows = document.querySelectorAll("table tbody tr"); return rows.length > 0 && rows.length <= 8; })()', true)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
$operationsPage = visit(OperationRunLinks::index($environment))
|
||||
->resize(1440, 1100)
|
||||
->waitForText('Operations Hub')
|
||||
->assertSee('Which operation needs attention now?')
|
||||
->assertSee('Recent operations')
|
||||
->assertSee('Detail path')
|
||||
->assertSee('Technical detail available')
|
||||
->assertDontSee('Operation #')
|
||||
->assertDontSee('OperationRuns')
|
||||
->assertDontSee('Operation detail available')
|
||||
->assertDontSee('Proof unavailable')
|
||||
->assertDontSee('spec399 browser raw payload should stay hidden')
|
||||
->assertScript('document.querySelector("[data-testid=\"operations-hub-diagnostics\"]")?.hasAttribute("open") === false', true)
|
||||
->assertScript('typeof window.Livewire !== "undefined"', true)
|
||||
->assertScript('typeof window.Alpine !== "undefined"', true)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
$operationsPage->script('document.querySelector("[data-testid=\"operations-hub-diagnostics\"] summary")?.click();');
|
||||
$operationsPage
|
||||
->assertScript('document.querySelector("[data-testid=\"operations-hub-diagnostics\"]")?.hasAttribute("open") === true', true)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
$operationsPage->script("document.documentElement.classList.add('dark');");
|
||||
$operationsPage
|
||||
->assertScript('document.documentElement.classList.contains("dark")', true)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
$operationsPage->script("window.location.replace('about:blank');");
|
||||
});
|
||||
|
||||
/**
|
||||
* @return array{0: User, 1: ManagedEnvironment}
|
||||
*/
|
||||
function spec399BrowserFixture(): array
|
||||
{
|
||||
bindFailHardGraphClient();
|
||||
|
||||
$environment = ManagedEnvironment::factory()->active()->create([
|
||||
'name' => 'Spec399 Browser Environment',
|
||||
'external_id' => 'spec399-browser-environment',
|
||||
]);
|
||||
|
||||
[$user, $environment] = createUserWithTenant(
|
||||
tenant: $environment,
|
||||
role: 'owner',
|
||||
workspaceRole: 'owner',
|
||||
);
|
||||
|
||||
OperationRun::factory()->forTenant($environment)->create([
|
||||
'type' => 'inventory_sync',
|
||||
'status' => OperationRunStatus::Completed->value,
|
||||
'outcome' => OperationRunOutcome::Blocked->value,
|
||||
'initiator_name' => 'Spec399 browser operator',
|
||||
'context' => [
|
||||
'reason_code' => 'write_gate_blocked',
|
||||
'raw_payload' => 'spec399 browser raw payload should stay hidden',
|
||||
'target_scope' => [
|
||||
'scope_display_name' => 'Spec399 Browser Environment',
|
||||
],
|
||||
],
|
||||
'completed_at' => now(),
|
||||
]);
|
||||
|
||||
foreach (range(1, 10) as $index) {
|
||||
Finding::factory()->for($environment)->create([
|
||||
'workspace_id' => (int) $environment->workspace_id,
|
||||
'status' => Finding::STATUS_NEW,
|
||||
'severity' => Finding::SEVERITY_HIGH,
|
||||
'owner_user_id' => (int) $user->getKey(),
|
||||
'assignee_user_id' => (int) $user->getKey(),
|
||||
'subject_external_id' => $index === 1
|
||||
? 'spec399-browser-source-key'
|
||||
: sprintf('spec399-browser-assigned-key-%02d', $index),
|
||||
'evidence_jsonb' => [
|
||||
'display_name' => sprintf('Spec399 Browser Assigned Finding %02d', $index),
|
||||
],
|
||||
'created_at' => now()->subMinutes($index),
|
||||
]);
|
||||
}
|
||||
|
||||
foreach (range(1, 10) as $index) {
|
||||
Finding::factory()->for($environment)->create([
|
||||
'workspace_id' => (int) $environment->workspace_id,
|
||||
'status' => $index % 2 === 0 ? Finding::STATUS_NEW : Finding::STATUS_REOPENED,
|
||||
'severity' => Finding::SEVERITY_MEDIUM,
|
||||
'owner_user_id' => null,
|
||||
'assignee_user_id' => null,
|
||||
'subject_external_id' => $index === 1
|
||||
? 'spec399-browser-intake-key'
|
||||
: sprintf('spec399-browser-intake-key-%02d', $index),
|
||||
'evidence_jsonb' => [
|
||||
'display_name' => sprintf('Spec399 Browser Intake Finding %02d', $index),
|
||||
],
|
||||
'created_at' => now()->subMinutes($index + 20),
|
||||
]);
|
||||
}
|
||||
|
||||
return [$user, $environment];
|
||||
}
|
||||
|
||||
function spec399AuthenticateBrowser(
|
||||
mixed $test,
|
||||
User $user,
|
||||
ManagedEnvironment $environment,
|
||||
): void {
|
||||
$workspaceId = (int) $environment->workspace_id;
|
||||
|
||||
$session = [
|
||||
WorkspaceContext::SESSION_KEY => $workspaceId,
|
||||
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
|
||||
(string) $workspaceId => (int) $environment->getKey(),
|
||||
],
|
||||
SuppressDebugbarForSmokeRequests::SESSION_KEY => SuppressDebugbarForSmokeRequests::COOKIE_VALUE,
|
||||
];
|
||||
|
||||
$test->actingAs($user)->withSession($session);
|
||||
|
||||
foreach ($session as $key => $value) {
|
||||
session()->put($key, $value);
|
||||
}
|
||||
|
||||
setAdminPanelContext($environment);
|
||||
}
|
||||
@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Filament\Pages\Findings\FindingsIntakeQueue;
|
||||
use App\Filament\Pages\Findings\MyFindingsInbox;
|
||||
use App\Filament\Pages\Governance\GovernanceInbox;
|
||||
use App\Filament\Resources\FindingResource;
|
||||
use App\Filament\Resources\FindingResource\Pages\ListFindings;
|
||||
use App\Filament\Widgets\Dashboard\RecentOperations;
|
||||
use App\Models\Finding;
|
||||
use App\Models\OperationRun;
|
||||
use App\Support\Filament\TablePaginationProfiles;
|
||||
use App\Support\ManagedEnvironmentLinks;
|
||||
use App\Support\OperationRunLinks;
|
||||
use App\Support\OperationRunOutcome;
|
||||
use App\Support\OperationRunStatus;
|
||||
use App\Support\OperationRunType;
|
||||
use App\Support\Workspaces\WorkspaceContext;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\ActionGroup;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Features\SupportTesting\Testable;
|
||||
use Livewire\Livewire;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
function spec399ActingTenantContext(): array
|
||||
{
|
||||
[$user, $tenant] = createUserWithTenant(role: 'owner', workspaceRole: 'owner');
|
||||
|
||||
test()->actingAs($user);
|
||||
setAdminPanelContext($tenant);
|
||||
session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
|
||||
|
||||
return [$user, $tenant];
|
||||
}
|
||||
|
||||
function spec399Table(Testable $component): \Filament\Tables\Table
|
||||
{
|
||||
return $component->instance()->getTable();
|
||||
}
|
||||
|
||||
it('caps the recent operations dashboard table and removes default operation detail links', function (): void {
|
||||
[$user, $tenant] = spec399ActingTenantContext();
|
||||
|
||||
$operation = OperationRun::factory()->create([
|
||||
'managed_environment_id' => (int) $tenant->getKey(),
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
'type' => OperationRunType::InventorySync->value,
|
||||
'status' => OperationRunStatus::Queued->value,
|
||||
'outcome' => OperationRunOutcome::Pending->value,
|
||||
]);
|
||||
|
||||
$table = spec399Table(Livewire::actingAs($user)->test(RecentOperations::class));
|
||||
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
|
||||
->and($table->getRecordUrl($operation))->toBeNull()
|
||||
->and(array_keys($table->getVisibleColumns()))->toBe(['type', 'outcome', 'created_at']);
|
||||
});
|
||||
|
||||
it('renders dashboard, governance, and operations defaults without raw operation proof language', function (): void {
|
||||
[$user, $tenant] = spec399ActingTenantContext();
|
||||
|
||||
OperationRun::factory()->forTenant($tenant)->create([
|
||||
'type' => OperationRunType::InventorySync->value,
|
||||
'status' => OperationRunStatus::Completed->value,
|
||||
'outcome' => OperationRunOutcome::Blocked->value,
|
||||
'context' => [
|
||||
'raw_payload' => 'spec399 feature raw payload should stay hidden',
|
||||
],
|
||||
'completed_at' => now(),
|
||||
]);
|
||||
|
||||
Finding::factory()->for($tenant)->create([
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
'status' => Finding::STATUS_NEW,
|
||||
'severity' => Finding::SEVERITY_HIGH,
|
||||
'owner_user_id' => null,
|
||||
'assignee_user_id' => null,
|
||||
'subject_external_id' => 'spec399-feature-source-key',
|
||||
'evidence_jsonb' => [
|
||||
'display_name' => 'Spec399 Feature Governance Finding',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->actingAs($user)
|
||||
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
|
||||
->get(route('admin.workspace.home', ['workspace' => $tenant->workspace]))
|
||||
->assertOk()
|
||||
->assertSee('Review recent workspace activity')
|
||||
->assertSee('data-testid="workspace-recent-operations-disclosure"', false)
|
||||
->assertDontSee('spec399 feature raw payload should stay hidden');
|
||||
|
||||
$this->actingAs($user)
|
||||
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
|
||||
->get(ManagedEnvironmentLinks::viewUrl($tenant))
|
||||
->assertOk()
|
||||
->assertDontSee('spec399 feature raw payload should stay hidden');
|
||||
|
||||
$this->actingAs($user)
|
||||
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
|
||||
->get(GovernanceInbox::getUrl(panel: 'admin'))
|
||||
->assertOk()
|
||||
->assertSee('Governance Inbox')
|
||||
->assertSee('Primary inbox lanes')
|
||||
->assertSee('Needs triage')
|
||||
->assertDontSee('spec399-feature-source-key')
|
||||
->assertDontSee('spec399 feature raw payload should stay hidden');
|
||||
|
||||
$this->actingAs($user)
|
||||
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
|
||||
->get(OperationRunLinks::index($tenant))
|
||||
->assertOk()
|
||||
->assertSee('Detail path')
|
||||
->assertSee('Technical detail available')
|
||||
->assertSee('Recent operations')
|
||||
->assertDontSee('Operation #')
|
||||
->assertDontSee('OperationRuns')
|
||||
->assertDontSee('Operation detail available')
|
||||
->assertDontSee('spec399 feature raw payload should stay hidden');
|
||||
});
|
||||
|
||||
it('proves touched findings tables cap product rows before secondary pages', function (): void {
|
||||
[$user, $tenant] = spec399ActingTenantContext();
|
||||
|
||||
$assignedFindings = collect(range(1, 10))
|
||||
->map(fn (int $index): Finding => Finding::factory()->for($tenant)->create([
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
'status' => Finding::STATUS_NEW,
|
||||
'owner_user_id' => (int) $user->getKey(),
|
||||
'assignee_user_id' => (int) $user->getKey(),
|
||||
'subject_external_id' => sprintf('spec399-assigned-source-%02d', $index),
|
||||
'created_at' => now()->subMinutes($index),
|
||||
]));
|
||||
|
||||
$intakeFindings = collect(range(1, 10))
|
||||
->map(fn (int $index): Finding => Finding::factory()->for($tenant)->create([
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
'status' => Finding::STATUS_REOPENED,
|
||||
'owner_user_id' => null,
|
||||
'assignee_user_id' => null,
|
||||
'subject_external_id' => sprintf('spec399-intake-source-%02d', $index),
|
||||
'created_at' => now()->subMinutes($index + 20),
|
||||
]));
|
||||
|
||||
$environmentList = Livewire::actingAs($user)->test(ListFindings::class);
|
||||
$environmentList
|
||||
->assertCanSeeTableRecords($assignedFindings->take(8))
|
||||
->assertCanNotSeeTableRecords($assignedFindings->slice(8));
|
||||
|
||||
$assignedInboxOrder = $assignedFindings
|
||||
->sortByDesc(fn (Finding $finding): int => (int) $finding->getKey())
|
||||
->values();
|
||||
|
||||
$myFindings = Livewire::actingAs($user)->test(MyFindingsInbox::class);
|
||||
$myFindings
|
||||
->assertCanSeeTableRecords($assignedInboxOrder->take(8))
|
||||
->assertCanNotSeeTableRecords($assignedInboxOrder->slice(8));
|
||||
|
||||
setAdminPanelContext();
|
||||
|
||||
$intakeInboxOrder = $intakeFindings
|
||||
->sortByDesc(fn (Finding $finding): int => (int) $finding->getKey())
|
||||
->values();
|
||||
|
||||
$intake = Livewire::actingAs($user)->test(FindingsIntakeQueue::class);
|
||||
$intake
|
||||
->assertCanSeeTableRecords($intakeInboxOrder->take(8))
|
||||
->assertCanNotSeeTableRecords($intakeInboxOrder->slice(8));
|
||||
});
|
||||
|
||||
it('keeps findings list inspection on row click and groups row actions under more', function (): void {
|
||||
[$user, $tenant] = spec399ActingTenantContext();
|
||||
|
||||
$finding = Finding::factory()->for($tenant)->create([
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
]);
|
||||
|
||||
$table = spec399Table(Livewire::actingAs($user)->test(ListFindings::class));
|
||||
$actions = collect($table->getActions());
|
||||
$topLevelActionNames = $actions
|
||||
->reject(static fn ($action): bool => $action instanceof ActionGroup)
|
||||
->map(static fn ($action): ?string => $action instanceof Action ? $action->getName() : null)
|
||||
->filter()
|
||||
->values()
|
||||
->all();
|
||||
$moreGroup = $actions->first(static fn ($action): bool => $action instanceof ActionGroup);
|
||||
$moreActionNames = collect($moreGroup?->getActions() ?? [])
|
||||
->map(static fn ($action): ?string => $action instanceof Action ? $action->getName() : null)
|
||||
->filter()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
|
||||
->and($table->getRecordUrl($finding))->toBe(FindingResource::getUrl('view', ['record' => $finding], tenant: $tenant))
|
||||
->and($topLevelActionNames)->toBe([])
|
||||
->and($moreGroup)->toBeInstanceOf(ActionGroup::class)
|
||||
->and($moreActionNames)->toContain('primary_drill_down', 'triage', 'assign', 'request_exception');
|
||||
});
|
||||
|
||||
it('caps findings inbox tables and keeps managed environment labels human readable', function (): void {
|
||||
[$user] = spec399ActingTenantContext();
|
||||
|
||||
foreach ([MyFindingsInbox::class, FindingsIntakeQueue::class] as $pageClass) {
|
||||
setAdminPanelContext();
|
||||
|
||||
$table = spec399Table(Livewire::actingAs($user)->test($pageClass));
|
||||
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
|
||||
->and($table->getColumn('tenant.name')?->getLabel())->toBe('Managed environment')
|
||||
->and($table->getFilter('managed_environment_id')?->getLabel())->toBe('Managed environment');
|
||||
}
|
||||
});
|
||||
@ -17,7 +17,6 @@
|
||||
use App\Models\Workspace;
|
||||
use App\Support\Auth\PlatformCapabilities;
|
||||
use App\Support\Filament\TablePaginationProfiles;
|
||||
use App\Support\OperationRunLinks;
|
||||
use App\Support\OperationRunOutcome;
|
||||
use App\Support\OperationRunStatus;
|
||||
use App\Support\OperationRunType;
|
||||
@ -149,7 +148,7 @@ function spec125DetailPlatformContext(): PlatformUser
|
||||
|
||||
expect($table->getDefaultSortColumn())->toBe('created_at');
|
||||
expect($table->getDefaultSortDirection())->toBe('desc');
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::widget());
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface());
|
||||
expect($table->getEmptyStateHeading())->toBe('No operations yet');
|
||||
expect($table->isSearchable())->toBeFalse();
|
||||
expect($table->getColumn('type')?->isSortable())->toBeTrue();
|
||||
@ -158,9 +157,8 @@ function spec125DetailPlatformContext(): PlatformUser
|
||||
expect($table->getColumn('created_at')?->isSortable())->toBeTrue();
|
||||
expect($table->getColumn('status')?->isToggleable())->toBeTrue();
|
||||
expect($table->getColumn('status')?->isToggledHiddenByDefault())->toBeTrue();
|
||||
expect($table->getRecordUrl($operation))->toBe(OperationRunLinks::view($operation, $tenant));
|
||||
expect($table->getRecordUrl($operation))->toBeNull();
|
||||
expect(array_keys($table->getVisibleColumns()))->toBe([
|
||||
'short_id',
|
||||
'type',
|
||||
'outcome',
|
||||
'created_at',
|
||||
|
||||
@ -189,7 +189,7 @@ function spec125CriticalTenantContext(bool $ensureDefaultMicrosoftProviderConnec
|
||||
|
||||
expect($table->getDefaultSortColumn())->toBe('created_at');
|
||||
expect($table->getDefaultSortDirection())->toBe('desc');
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::resource());
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface());
|
||||
expect($table->persistsSearchInSession())->toBeTrue();
|
||||
expect($table->persistsSortInSession())->toBeTrue();
|
||||
expect($table->persistsFiltersInSession())->toBeTrue();
|
||||
@ -217,7 +217,7 @@ function spec125CriticalTenantContext(bool $ensureDefaultMicrosoftProviderConnec
|
||||
|
||||
expect($table->getDefaultSortColumn())->toBe('created_at');
|
||||
expect($table->getDefaultSortDirection())->toBe('desc');
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::resource());
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface());
|
||||
expect($table->persistsSearchInSession())->toBeTrue();
|
||||
expect($table->persistsSortInSession())->toBeTrue();
|
||||
expect($table->persistsFiltersInSession())->toBeTrue();
|
||||
@ -227,7 +227,7 @@ function spec125CriticalTenantContext(bool $ensureDefaultMicrosoftProviderConnec
|
||||
expect($table->getColumn('type')?->isSearchable())->toBeTrue();
|
||||
expect($table->getColumn('type')?->isSortable())->toBeTrue();
|
||||
expect($table->getColumn('created_at')?->isSortable())->toBeTrue();
|
||||
expect(count($table->getVisibleColumns()))->toBeLessThanOrEqual(7);
|
||||
expect(count($table->getVisibleColumns()))->toBeLessThanOrEqual(8);
|
||||
});
|
||||
|
||||
it('standardizes the backup-items relation manager without disturbing its action surface', function (): void {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
use App\Models\Finding;
|
||||
use App\Models\ManagedEnvironment;
|
||||
use App\Models\User;
|
||||
use App\Support\Filament\TablePaginationProfiles;
|
||||
use App\Support\Workspaces\WorkspaceContext;
|
||||
use Filament\Facades\Filament;
|
||||
use Livewire\Livewire;
|
||||
@ -134,6 +135,12 @@ function makeIntakeFinding(ManagedEnvironment $tenant, array $attributes = []):
|
||||
'visible_overdue' => 1,
|
||||
]);
|
||||
|
||||
$table = $component->instance()->getTable();
|
||||
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
|
||||
->and($table->getColumn('tenant.name')?->getLabel())->toBe('Managed environment')
|
||||
->and($table->getFilter('managed_environment_id')?->getLabel())->toBe('Managed environment');
|
||||
|
||||
$queueViews = collect($component->instance()->queueViews())->keyBy('key');
|
||||
|
||||
expect($queueViews['unassigned']['badge_count'])->toBe(4)
|
||||
|
||||
@ -66,7 +66,7 @@ function findingsDefaultIndicatorLabels($component): array
|
||||
$component = Livewire::test(ListFindings::class);
|
||||
$table = $component->instance()->getTable();
|
||||
|
||||
expect($table->getPaginationPageOptions())->toBe(\App\Support\Filament\TablePaginationProfiles::resource());
|
||||
expect($table->getPaginationPageOptions())->toBe(\App\Support\Filament\TablePaginationProfiles::productSurface());
|
||||
expect($table->getDefaultSortColumn())->toBe('created_at');
|
||||
expect($table->getDefaultSortDirection())->toBe('desc');
|
||||
expect($table->getEmptyStateHeading())->toBe('No findings match this view');
|
||||
|
||||
@ -214,7 +214,7 @@ function findingFilterIndicatorLabels($component): array
|
||||
->assertCanNotSeeTableRecords([$assignedToOther, $unassigned]);
|
||||
});
|
||||
|
||||
it('persists findings search, sort, and filter state while keeping the resource pagination profile', function (): void {
|
||||
it('persists findings search, sort, and filter state while keeping the product-surface pagination profile', function (): void {
|
||||
actingAsFindingsManagerForFilters();
|
||||
|
||||
$component = Livewire::test(ListFindings::class)
|
||||
@ -224,7 +224,7 @@ function findingFilterIndicatorLabels($component): array
|
||||
|
||||
$table = $component->instance()->getTable();
|
||||
|
||||
expect($table->getPaginationPageOptions())->toBe(\App\Support\Filament\TablePaginationProfiles::resource());
|
||||
expect($table->getPaginationPageOptions())->toBe(\App\Support\Filament\TablePaginationProfiles::productSurface());
|
||||
expect(session()->get($component->instance()->getTableSearchSessionKey()))->toBe('drift');
|
||||
expect(session()->get($component->instance()->getTableSortSessionKey()))->toBe('created_at:asc');
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
use App\Models\Finding;
|
||||
use App\Models\ManagedEnvironment;
|
||||
use App\Models\User;
|
||||
use App\Support\Filament\TablePaginationProfiles;
|
||||
use App\Support\Workspaces\WorkspaceContext;
|
||||
use Filament\Facades\Filament;
|
||||
use Livewire\Livewire;
|
||||
@ -117,6 +118,12 @@ function makeAssignedFindingForInbox(ManagedEnvironment $tenant, User $assignee,
|
||||
'overdue_assigned' => 1,
|
||||
]);
|
||||
|
||||
$table = $component->instance()->getTable();
|
||||
|
||||
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
|
||||
->and($table->getColumn('tenant.name')?->getLabel())->toBe('Managed environment')
|
||||
->and($table->getFilter('managed_environment_id')?->getLabel())->toBe('Managed environment');
|
||||
|
||||
expect($component->instance()->availableFilters())->toBe([
|
||||
[
|
||||
'key' => 'assignee_scope',
|
||||
|
||||
@ -28,10 +28,10 @@
|
||||
->assertOk()
|
||||
->assertSee('Operations Hub')
|
||||
->assertSee('Which operation needs attention now?')
|
||||
->assertSee('Recent runs')
|
||||
->assertSee('Recent operations')
|
||||
->assertSee('All')
|
||||
->assertSee('Active')
|
||||
->assertSee('Likely stale')
|
||||
->assertSee('Needs attention')
|
||||
->assertSee('Terminal follow-up')
|
||||
->assertSee('Succeeded')
|
||||
->assertSee('Partial')
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
->assertSee('Operations Hub')
|
||||
->assertSee('Execution follow-up')
|
||||
->assertSee('Which operation needs attention now?')
|
||||
->assertSee('Recent runs')
|
||||
->assertSee('Recent operations')
|
||||
->assertSee('Next action');
|
||||
});
|
||||
|
||||
@ -57,5 +57,5 @@
|
||||
->assertSee('Which operation needs attention now?')
|
||||
->assertSee('Back to backup set')
|
||||
->assertSee('/admin/tenant/backup-sets/1', false)
|
||||
->assertSee('Recent runs');
|
||||
->assertSee('Recent operations');
|
||||
});
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
->assertSee('data-stat-key="needs-attention"', false)
|
||||
->assertSee('data-stat-value="5"', false)
|
||||
->assertSee('data-stat-color="warning"', false)
|
||||
->assertSee('Failed, blocked, partial, or stale OperationRuns in scope.')
|
||||
->assertSee('Failed, blocked, partial, or stale operations in scope.')
|
||||
->assertSee('data-testid="operations-workbench-stat-active-operations"', false)
|
||||
->assertSee('data-stat-key="active-operations"', false)
|
||||
->assertSee('data-stat-color="info"', false)
|
||||
@ -101,12 +101,12 @@
|
||||
->assertSee('Environment: Spec328 Environment Alpha')
|
||||
->assertSee('class="fi-badge fi-size-sm"', false)
|
||||
->assertSee('fi-badge-label', false)
|
||||
->assertSee('Proof')
|
||||
->assertSee('Operation detail available')
|
||||
->assertSee('Detail path')
|
||||
->assertSee('Technical detail available')
|
||||
->assertSee('Next action')
|
||||
->assertSee('Next action')
|
||||
->assertSee('Operation summary')
|
||||
->assertSee('Recent runs')
|
||||
->assertSee('Recent operations')
|
||||
->assertSee('Chronological operation record')
|
||||
->assertSee('Diagnostics')
|
||||
->assertSee('Collapsed')
|
||||
@ -151,7 +151,7 @@
|
||||
|
||||
Livewire::test(OperationsWorkbenchStats::class)
|
||||
->assertSee('Needs attention')
|
||||
->assertSee('Failed, blocked, partial, or stale OperationRuns in scope.')
|
||||
->assertSee('Failed, blocked, partial, or stale operations in scope.')
|
||||
->assertSee('data-testid="operations-workbench-stat-needs-attention"', false)
|
||||
->assertSee('data-stat-value="5"', false)
|
||||
->assertSee('data-stat-color="warning"', false)
|
||||
@ -194,8 +194,8 @@
|
||||
->assertOk()
|
||||
->assertSee('Which operation needs attention now?')
|
||||
->assertSee('No operations need follow-up')
|
||||
->assertSee('No failed, blocked, partial, or stale OperationRuns are visible in this scope.')
|
||||
->assertSee('Operation detail available')
|
||||
->assertSee('No failed, blocked, partial, or stale operations are visible in this scope.')
|
||||
->assertSee('Technical detail available')
|
||||
->assertDontSee('environment is healthy')
|
||||
->assertDontSee('governance health is complete')
|
||||
->assertDontSee('customer-safe evidence readiness');
|
||||
|
||||
@ -221,7 +221,7 @@
|
||||
])
|
||||
->get(\App\Support\OperationRunLinks::index())
|
||||
->assertOk()
|
||||
->assertSee('Likely stale')
|
||||
->assertSee('Needs attention')
|
||||
->assertSee('Terminal follow-up')
|
||||
->assertSee('Succeeded')
|
||||
->assertSee('Partial')
|
||||
|
||||
@ -157,7 +157,7 @@
|
||||
->assertSee('Environment filter:')
|
||||
->assertSee('Spec391 Empty Environment')
|
||||
->assertSee('No operations need follow-up')
|
||||
->assertSee('No failed, blocked, partial, or stale OperationRuns are visible in this scope.')
|
||||
->assertSee('No failed, blocked, partial, or stale operations are visible in this scope.')
|
||||
->assertSee('No operations found')
|
||||
->assertDontSee('environment is healthy')
|
||||
->assertDontSee('governance health is complete')
|
||||
|
||||
@ -34,9 +34,9 @@ ## Spec 325 Target Image Coverage
|
||||
|
||||
| Selected surface group | Source row(s) | Target brief | Runtime implemented |
|
||||
| --- | --- | --- | --- |
|
||||
| Workspace Overview | UI-001, UI-002 | `target-experience-briefs/workspace-overview.md` | No |
|
||||
| Workspace Overview | UI-001, UI-002 | `target-experience-briefs/workspace-overview.md` | Partial - Spec 399 collapses recent operation recency details behind disclosure by default; broader target implementation remains separate. |
|
||||
| Environment Dashboard | UI-011 | `target-experience-briefs/environment-dashboard.md` | No |
|
||||
| Operations Hub | UI-016 | `target-experience-briefs/operations-hub.md` | No |
|
||||
| Operations Hub | UI-016 | `target-experience-briefs/operations-hub.md` | Partial - Spec 399 caps the default operations table and removes raw `Operation #` / OperationRun proof wording from the default workbench; broader target implementation remains separate. |
|
||||
| Governance Inbox | UI-028 | `target-experience-briefs/governance-inbox.md` | No |
|
||||
| Customer Review Workspace | UI-038 | `target-experience-briefs/customer-review-workspace.md` | No |
|
||||
| Audit Log | UI-025 | `target-experience-briefs/audit-log.md` | No |
|
||||
@ -50,16 +50,16 @@ ## Coverage By Area
|
||||
| --- | ---: | --- |
|
||||
| Platform/system | 14 | Spec 396 adds focused browser proof for `/system`, `/system/login`, `/system/ops/runs`, and `/system/security/access-logs`; remaining directory, control, detail, and repair surfaces stay route-discovered or follow-up. |
|
||||
| Governance | 13 | Strong browser coverage for inbox, decisions, exceptions, baselines; Spec 397 adds baseline snapshot detail receipt proof; baseline profile/detail and compare routes remain broader follow-up. |
|
||||
| Monitoring | 9 | Operations hub and alert delivery landing captured; record details and config forms remain pattern/manual review. |
|
||||
| Monitoring | 9 | Operations hub and alert delivery landing captured; Spec 399 caps the Operations Hub hot table and removes default raw run identifiers/technical wording while record details and config forms remain pattern/manual review. |
|
||||
| Inventory | 8 | Route-discovered only; coverage, policy version detail, and raw-data exposure need later review. |
|
||||
| Evidence / audit | 8 | Audit log captured; Spec 397 adds receipt-reduction proof for Evidence Snapshot, Baseline Snapshot, and Stored Report detail surfaces while Evidence Overview remains follow-up. |
|
||||
| Reviews | 8 | Review register, customer workspace, review pack detail, rendered-report, and the Spec 386 publication-resolution workflow now have bounded browser evidence; Spec 397 reduces Review Pack receipt internals while deeper evidence/report surfaces still remain open elsewhere. |
|
||||
| Backup / restore | 6 | High-risk area; Spec 371 adds seeded browser proof for Backup Sets list/detail. Spec 390 adds Restore create/view readiness guidance; Spec 397 verifies completed Restore Run detail receipt reduction while Restore list and broader failure/conflict browser coverage remain unresolved. |
|
||||
| Settings / admin | 5 | Workspace and environment access are RBAC-sensitive and need later review. |
|
||||
| Provider / integration | 5 | Provider connections and required permissions are captured; create/edit/onboarding remain high-risk unresolved surfaces. |
|
||||
| Findings | 5 | Queue/inbox patterns captured; finding detail needs individual triage target. |
|
||||
| Findings | 5 | Queue/inbox patterns captured; Spec 399 caps My Findings, Findings Intake, and Environment Findings hot tables while finding detail still needs individual triage target. |
|
||||
| Auth/access | 4 | Mostly flow/guard surfaces; copy and denial states should be pattern-reviewed. |
|
||||
| App shell | 4 | Workspace overview captured; chooser/context routes need domain pattern pass. |
|
||||
| App shell | 4 | Workspace overview captured; Spec 399 collapses recent-operation recency details by default while chooser/context routes need domain pattern pass. |
|
||||
| Workspace / environment | 2 | Environment dashboard captured; managed-environments landing now has a runtime report. |
|
||||
| Utility | 2 | Non-product endpoints; design-system cleanup only. |
|
||||
| Support | 2 | Diagnostics/support surfaces should stay secondary to operator workflows. |
|
||||
|
||||
@ -6,8 +6,8 @@ # Route Inventory
|
||||
|
||||
| ID | Route / URL | Source | Page Name | Area | Scope | Reachability | Auth/RBAC Notes | Primary Archetype | Secondary Archetype | Design Depth | Repo Truth | Screenshot | Page Report | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| UI-001 | `/admin` -> `/admin/workspaces/{workspace}/overview` | route + `WorkspaceOverview` | Workspace Overview | App shell | workspace | reachable | workspace member | Overview / Dashboard | Workspace / Tenant Context | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-001-workspace-overview.png) | [report](page-reports/ui-001-workspace-overview.md) | Redirected from `/admin`; first workspace-level landing page. |
|
||||
| UI-002 | `/admin/workspaces/{workspace}/overview` | route + page class | Workspace Overview direct | App shell | workspace | reachable | workspace member | Overview / Dashboard | Workspace / Tenant Context | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-001-workspace-overview.png) | [report](page-reports/ui-001-workspace-overview.md) | Same surface as UI-001, route-owned workspace shell. |
|
||||
| UI-001 | `/admin` -> `/admin/workspaces/{workspace}/overview` | route + `WorkspaceOverview` | Workspace Overview | App shell | workspace | reachable | workspace member | Overview / Dashboard | Workspace / Tenant Context | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-001-workspace-overview.png) | [report](page-reports/ui-001-workspace-overview.md) | Redirected from `/admin`; first workspace-level landing page. Spec 399 keeps recent operation recency collapsed behind disclosure by default. |
|
||||
| UI-002 | `/admin/workspaces/{workspace}/overview` | route + page class | Workspace Overview direct | App shell | workspace | reachable | workspace member | Overview / Dashboard | Workspace / Tenant Context | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-001-workspace-overview.png) | [report](page-reports/ui-001-workspace-overview.md) | Same surface as UI-001, route-owned workspace shell. Spec 399 keeps recent operation recency collapsed behind disclosure by default. |
|
||||
| UI-003 | `/admin/choose-workspace` | Filament page | Choose Workspace | App shell | workspace chooser | reachable | authenticated user | Workspace / Tenant Context | Auth / Access | Domain Pattern Surface | repo-verified | - | - | Workspace context entry point; should remain low-friction and explicit. |
|
||||
| UI-004 | `/admin/choose-environment` | Filament page | Choose Environment | App shell | workspace + environment selector | reachable | workspace member | Workspace / Tenant Context | Auth / Access | Domain Pattern Surface | repo-verified | - | - | Explicit environment-context entry point. |
|
||||
| UI-005 | `/admin/no-access` | Filament page | No Access | Auth/access | admin plane | reachable as guard output | authenticated user | Auth / Access | Utility / Internal | Design-System Cleanup Surface | repo-verified | - | - | Customer-safe denial copy should be checked in later copy pass. |
|
||||
@ -21,7 +21,7 @@ # Route Inventory
|
||||
| UI-013 | `/admin/workspaces/{workspace}/environments/{environment}/access-scopes` | resource page | Environment Access Scopes | Settings / admin | environment-bound | route exists | owner/manager capability expected | Settings / Admin | Auth / Access | Strategic Surface | repo-verified | - | - | RBAC-sensitive environment access surface. |
|
||||
| UI-014 | `/admin/onboarding` | route + wizard | Environment Onboarding | Provider / onboarding | workspace | route exists | workspace capability | Provider / Integration | Workspace / Tenant Context | Strategic Surface | repo-verified | - | - | Large wizard; individual target treatment likely needed. |
|
||||
| UI-015 | `/admin/onboarding/{onboardingDraft}` | route + wizard | Onboarding Draft | Provider / onboarding | workspace | route exists | scoped draft resolver | Provider / Integration | Workspace / Tenant Context | Domain Pattern Surface | repo-verified | - | - | Dynamic workflow state requires seeded draft to review. |
|
||||
| UI-016 | `/admin/workspaces/{workspace}/operations` | route + `Operations` | Operations | Monitoring | workspace | reachable | workspace member | Operations / Monitoring | Evidence / Audit | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-003-operations.png) | [report](page-reports/ui-003-operations.md) | Canonical OperationRun hub. |
|
||||
| UI-016 | `/admin/workspaces/{workspace}/operations` | route + `Operations` | Operations | Monitoring | workspace | reachable | workspace member | Operations / Monitoring | Evidence / Audit | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-003-operations.png) | [report](page-reports/ui-003-operations.md) | Canonical operations hub. Spec 399 caps the hot table to the product-surface profile and removes raw `Operation #` / OperationRun proof wording from the default view. |
|
||||
| UI-017 | `/admin/workspaces/{workspace}/operations/{run}` | route + viewer | Operation Detail | Monitoring | workspace record | route exists | workspace + run entitlement | Operations / Monitoring | Evidence / Audit | Strategic Surface | repo-verified | - | - | Dynamic record route; requires run fixture for full review. |
|
||||
| UI-018 | `/admin/alerts` | cluster route | Alerts | Monitoring | workspace hub | reachable, redirects/lands on alert deliveries | workspace member | Operations / Monitoring | Evidence / Audit | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-007-alerts.png) | [report](page-reports/ui-007-alerts.md) | Browser landed on Alert Deliveries for cluster subnavigation. |
|
||||
| UI-019 | `/admin/alerts/alert-deliveries` | resource | Alert Deliveries | Monitoring | workspace hub | reachable | workspace member | Operations / Monitoring | Evidence / Audit | Domain Pattern Surface | repo-verified | [desktop](screenshots/desktop/ui-007-alerts.png) | [report](page-reports/ui-007-alerts.md) | Table-backed alert signal surface. |
|
||||
@ -35,10 +35,10 @@ # Route Inventory
|
||||
| UI-027 | `/admin/finding-exceptions/open-queue/{environment}` | route/controller | Exception Queue Deep Link | Governance | environment filter link | route exists | environment entitlement | Exceptions / Accepted Risk | Utility / Internal | Domain Pattern Surface | repo-verified | - | - | Navigation helper into queue; not a standalone product page. |
|
||||
| UI-028 | `/admin/governance/inbox` | page | Governance Inbox | Governance | workspace hub | reachable | workspace member | Findings / Inbox | Evidence / Audit | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-004-governance-inbox.png) | [report](page-reports/ui-004-governance-inbox.md) | Strategic operator work surface. |
|
||||
| UI-029 | `/admin/governance/decisions` | page | Decision Register | Governance | workspace hub | reachable | capability-gated access | Evidence / Audit | Findings / Inbox | Strategic Surface | repo-verified | [desktop](screenshots/desktop/ui-005-decision-register.png) | [report](page-reports/ui-005-decision-register.md) | Decision and proof-link surface. |
|
||||
| UI-030 | `/admin/findings/my-work` | page | My Findings | Findings | workspace analysis | route exists | workspace member | Findings / Inbox | Operations / Monitoring | Domain Pattern Surface | repo-verified | - | - | Workspace-owned analysis surface with optional environment filtering. |
|
||||
| UI-031 | `/admin/findings/intake` | page | Findings Intake | Findings | workspace analysis | route exists | workspace member | Findings / Inbox | Operations / Monitoring | Domain Pattern Surface | repo-verified | - | - | Intake queue pattern. |
|
||||
| UI-030 | `/admin/findings/my-work` | page | My Findings | Findings | workspace analysis | route exists | workspace member | Findings / Inbox | Operations / Monitoring | Domain Pattern Surface | repo-verified | - | - | Workspace-owned analysis surface with optional environment filtering. Spec 399 caps the table to the product-surface profile and uses human managed-environment labels. |
|
||||
| UI-031 | `/admin/findings/intake` | page | Findings Intake | Findings | workspace analysis | route exists | workspace member | Findings / Inbox | Operations / Monitoring | Domain Pattern Surface | repo-verified | - | - | Intake queue pattern. Spec 399 caps the table to the product-surface profile and uses human managed-environment labels. |
|
||||
| UI-032 | `/admin/findings/hygiene` | page | Findings Hygiene | Findings | workspace analysis | route exists | workspace member | Findings / Inbox | Support / Diagnostics | Domain Pattern Surface | repo-verified | - | - | Hygiene report pattern. |
|
||||
| UI-033 | `/admin/workspaces/{workspace}/environments/{environment}/findings` | resource | Environment Findings | Findings | environment-bound | route exists | environment entitlement | Findings / Inbox | Evidence / Audit | Domain Pattern Surface | repo-verified | - | - | Environment list page. |
|
||||
| UI-033 | `/admin/workspaces/{workspace}/environments/{environment}/findings` | resource | Environment Findings | Findings | environment-bound | route exists | environment entitlement | Findings / Inbox | Evidence / Audit | Domain Pattern Surface | repo-verified | - | - | Environment list page. Spec 399 caps the table to the product-surface profile and groups row actions under More while row click remains inspect. |
|
||||
| UI-034 | `/admin/workspaces/{workspace}/environments/{environment}/findings/{record}` | resource | Finding Detail | Findings | environment record | route exists | environment + record entitlement | Findings / Inbox | Evidence / Audit | Strategic Surface | repo-verified | - | - | Core triage detail route; needs individual review. |
|
||||
| UI-035 | `/admin/workspaces/{workspace}/environments/{environment}/finding-exceptions` | resource | Environment Exceptions | Governance | environment-bound | route exists | environment entitlement | Exceptions / Accepted Risk | Findings / Inbox | Domain Pattern Surface | repo-verified | - | - | Environment-specific exception list. |
|
||||
| UI-036 | `/admin/workspaces/{workspace}/environments/{environment}/finding-exceptions/{record}` | resource | Exception Detail | Governance | environment record | reachable | environment + record entitlement | Exceptions / Accepted Risk | Evidence / Audit | Strategic Surface | repo-verified | [desktop](../../specs/354-finding-exceptions-accepted-risk-resolution-guidance-v1/artifacts/screenshots/spec354-ui-036-exception-detail-guidance.png) | [report](page-reports/ui-036-exception-detail.md) | Accepted-risk lifecycle detail re-validated for incomplete-governance and calm-ready owner states. |
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
# Requirements Checklist: Spec 399 - Dashboard / Inbox / Table Contract Migration v1
|
||||
|
||||
**Purpose**: Validate that the Spec 399 preparation package is complete, bounded, testable, and ready for implementation review.
|
||||
**Created**: 2026-06-22
|
||||
**Feature**: `specs/399-dashboard-inbox-table-contract/spec.md`
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] CHK001 Feature value is stated from an operator/admin perspective, not as implementation-only cleanup.
|
||||
- [x] CHK002 Selected candidate, source, close alternatives, and deferral rationale are recorded.
|
||||
- [x] CHK003 Completed related specs are treated as read-only context and are not reopened.
|
||||
- [x] CHK004 Scope is limited to existing dashboard, inbox, and table-heavy `/admin` surfaces.
|
||||
- [x] CHK005 Explicit non-goals forbid runtime framework, presenter family, status enum family, persisted taxonomy, and compatibility-mode work.
|
||||
- [x] CHK006 No application implementation or runtime-code edit is included in this preparation package.
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] CHK007 No `[NEEDS CLARIFICATION]` markers remain.
|
||||
- [x] CHK008 User stories are independently testable and prioritized.
|
||||
- [x] CHK009 Functional requirements are observable and testable.
|
||||
- [x] CHK010 Acceptance criteria map to the named dashboard, inbox, table, Operations Hub, and technical-proof behavior.
|
||||
- [x] CHK011 Success criteria are measurable and include browser proof, table budgets, visible complexity, and no new runtime truth.
|
||||
- [x] CHK012 Edge cases cover calm states, native pagination limitations, technical-annex tables, OperationRun proof, RBAC-hidden actions, and unrelated browser failures.
|
||||
- [x] CHK013 Assumptions and open questions are non-blocking.
|
||||
|
||||
## Product Surface Contract
|
||||
|
||||
- [x] CHK014 `docs/product/standards/product-surface-contract.md` is referenced as an active gate.
|
||||
- [x] CHK015 No-legacy posture is explicit: canonical replacement, no hidden old layouts, aliases, old labels, fallback readers, or legacy fixtures.
|
||||
- [x] CHK016 Product Surface Impact records page archetypes, primary questions, primary actions, surface budgets, Technical Annex/deep-link demotion, status vocabulary, and exceptions.
|
||||
- [x] CHK017 Product Surface exceptions are `none planned`; any future exception is a stop condition requiring spec/plan update.
|
||||
- [x] CHK018 Browser proof is required for rendered UI changes.
|
||||
- [x] CHK019 Human Product Sanity is required and has reviewer questions.
|
||||
- [x] CHK020 Implementation report close-out fields are named in spec, plan, and tasks.
|
||||
|
||||
## UI And Filament Readiness
|
||||
|
||||
- [x] CHK021 UI Surface Impact is explicitly checked and is consistent with Productization Coverage.
|
||||
- [x] CHK022 Route inventory and design coverage matrix update expectations are recorded.
|
||||
- [x] CHK023 Page reports are proportional and not required by default.
|
||||
- [x] CHK024 Filament/Livewire posture records Livewire v4.1.4 compliance and no Livewire v3 usage.
|
||||
- [x] CHK025 Provider registration posture records no panel provider changes and current Laravel 12 provider location.
|
||||
- [x] CHK026 Global search posture is unchanged unless implementation explicitly updates spec/plan first.
|
||||
- [x] CHK027 Destructive/high-impact action requirements include confirmation, authorization, audit safety, and test coverage.
|
||||
- [x] CHK028 Asset strategy records no new assets expected and `filament:assets` only if assets are registered later.
|
||||
- [x] CHK028A List/table surface work references `docs/product/standards/list-surface-review-checklist.md`.
|
||||
- [x] CHK028B Dark mode, accessibility, and Filament-native/shared-primitive proof is required for touched custom Blade surfaces.
|
||||
|
||||
## Task Readiness
|
||||
|
||||
- [x] CHK029 `spec.md`, `plan.md`, and `tasks.md` exist for `specs/399-dashboard-inbox-table-contract/`.
|
||||
- [x] CHK030 Tasks are ordered by discovery, tests-first expectations, user-story implementation, proof continuity, browser/coverage close-out, and non-goals.
|
||||
- [x] CHK031 Tasks name concrete likely files and preserve implementation discovery before runtime edits.
|
||||
- [x] CHK032 Tasks include Product Surface browser proof, Human Product Sanity, implementation report, Pint, and diff checks.
|
||||
- [x] CHK033 Tasks explicitly forbid completed-spec rewrites and broad framework/persistence/status-family expansion.
|
||||
|
||||
## Review Outcome
|
||||
|
||||
- [x] CHK034 Review outcome class: `acceptable-special-case`.
|
||||
- [x] CHK035 Workflow outcome: `keep`.
|
||||
- [x] CHK036 Final note location: active implementation report and PR close-out under Guardrail / Exception / Smoke Coverage.
|
||||
@ -0,0 +1,91 @@
|
||||
# Implementation Report: Spec 399 - Dashboard / Inbox / Table Contract Migration v1
|
||||
|
||||
## Selected Slice
|
||||
|
||||
- Runtime slice: Environment Dashboard recent operations widget, Workspace Overview recent operations section, Findings resource list, My Findings inbox, Findings Intake queue, Operations Hub, and the shared OperationRun table used by Operations Hub.
|
||||
- Repo-inspected but not runtime-edited: Environment Dashboard summary/page builder and Governance Inbox. Existing structures did not require a bounded runtime edit in this pass beyond the shared recent-operations/table reductions and no Product Surface exception was needed.
|
||||
- Deferred surfaces: secondary hot tables outside the selected files, detail/receipt pages, Customer Review Workspace, System Panel, Baseline Compare, Restore Preview, and Review Publication Resolution.
|
||||
|
||||
## Product Surface Gate
|
||||
|
||||
- No-legacy posture: no compatibility flags, alternate layouts, hidden legacy routes, or old table profiles were added.
|
||||
- Product Surface exceptions: none.
|
||||
- Page archetypes:
|
||||
- Workspace Overview: Dashboard Page; recent operation detail is collapsed by default.
|
||||
- Environment Dashboard recent operations: Dashboard widget/table; table defaults to product-surface pagination and no raw run link/identifier column.
|
||||
- Findings resource/list and inboxes: Inbox/Search-Index surfaces; table cap is product-surface pagination and row actions are grouped under More where applicable.
|
||||
- Operations Hub: Inbox Page with technical detail demoted; raw OperationRun detail remains deliberate technical/audit context.
|
||||
- Table caps: `TablePaginationProfiles::productSurface()` returns `[8, 25, 50]` and is used by directly touched hot tables.
|
||||
- Technical Annex / deep-link demotion:
|
||||
- Recent Operations widget no longer shows the short OperationRun identifier or row-level OperationRun detail links by default.
|
||||
- Workspace Overview recent operations remain available in a closed disclosure instead of default-open diagnostic content.
|
||||
- Findings list keeps row click as the inspect path and moves related/workflow row actions into More.
|
||||
- Operations Hub copy uses operation/product wording and "Detail path" / "Technical detail available" instead of default OperationRun/proof phrasing.
|
||||
- Operations Hub default workbench payload/view no longer exposes the raw `Operation #<id>` badge; authorized run detail remains reachable only through deliberate detail paths.
|
||||
- Action hierarchy:
|
||||
- Findings resource: clickable row is primary inspect; row actions are grouped under More; bulk actions remain under existing `BulkActionGroup`.
|
||||
- Operations Hub: existing OperationRunLinks/OperationRunResource primary action paths remain delegated; no local queued toast/link/event/dedupe/notification behavior added.
|
||||
- Destructive/high-impact actions: no new destructive or high-impact action was introduced. Existing mutating Finding workflow actions remain capability-gated in their existing action callbacks and grouped under More.
|
||||
- Asset strategy: no new assets. No `FilamentAsset` registration changes; deployment `filament:assets` requirement unchanged.
|
||||
- Provider registration: no panel/provider changes. Laravel 11+/12 provider registration remains in `bootstrap/providers.php`.
|
||||
- Livewire / Filament posture: Filament v5 code remains on Livewire v4; tests mount Filament Livewire page/widget components.
|
||||
- Global search posture: no global-search configuration changed. Findings resource already has a View page for searchable record navigation; no new globally searchable resource added.
|
||||
- Deployment impact: no migrations, env vars, queues, scheduler, storage, Graph scopes, provider contracts, or runtime services changed.
|
||||
|
||||
## Test Governance
|
||||
|
||||
- Lane assignment: Feature/Livewire table/action tests plus one focused Pest Browser smoke are the narrowest sufficient proof for this rendered Product Surface contract.
|
||||
- Test family: added one focused Feature file, one focused Browser smoke file, and updated existing Feature assertions that encoded the old overloaded defaults.
|
||||
- Fixture/helper cost: reused existing factories, `createUserWithTenant`, workspace session helpers, and local smoke browser patterns. No broad seed or factory behavior changed.
|
||||
- Planned validation commands:
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec399`
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php`
|
||||
- targeted affected Feature tests for Filament table standards, Findings, and Operations Hub
|
||||
- `cd apps/platform && ./vendor/bin/sail pint --dirty`
|
||||
- `git diff --check`
|
||||
|
||||
## Proof Continuity
|
||||
|
||||
- Environment Dashboard recent operation links demoted: the dashboard widget no longer makes OperationRun detail the default row target; authorized operation detail remains available through Operations Hub and operation resource routes.
|
||||
- Workspace Overview recent operation detail demoted: existing destinations remain inside the closed disclosure; default workspace landing no longer foregrounds diagnostic recency.
|
||||
- Governance Inbox source/proof paths: no runtime edit in this slice; existing proof/source paths were not expanded.
|
||||
- Findings technical/detail paths: row click still opens the Finding detail route; related record action remains available in More; technical operation IDs remain detail-only.
|
||||
- Operations Hub technical paths: existing `OperationRunLinks` and `OperationRunResource` paths are preserved for deliberate detail access.
|
||||
|
||||
## Human Product Sanity
|
||||
|
||||
- Result: pass for the selected slice.
|
||||
- Visible complexity outcome: fewer default rows, fewer primary links, no default raw run/proof language on touched Operations Hub surfaces, and Workspace Overview diagnostic recency collapsed by default.
|
||||
- Dark mode/accessibility/Filament-native proof: Pest Browser smoke toggled dark mode on Operations Hub, proved native `<details>/<summary>` disclosure starts closed and expands on deliberate click, and passed JavaScript checks.
|
||||
- Browser proof depth: Spec 399 smoke now proves a non-empty Governance Inbox lane with collapsed item detail, product-surface row caps on My Findings, Findings Intake, and Environment Findings, hidden source keys/raw payloads, hidden `Operation #` identifiers, and Operations Hub diagnostics collapsed by default.
|
||||
- Integrated browser result: pass for Workspace Overview, Governance Inbox, My Findings, Findings Intake, Environment Findings, Environment Dashboard, and Operations Hub in the authenticated in-app browser session. Findings table row caps were verified against the primary Filament table because the local Laravel Debugbar adds its own request tables in development. Operations Hub diagnostics were verified closed by default and expandable through a direct in-app browser DOM click. One stale integrated-browser tab produced transient CDP navigation timeouts; a fresh in-app tab loaded the same authenticated routes successfully.
|
||||
|
||||
## Validation Results
|
||||
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec399`: passed, 6 tests / 116 assertions.
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php`: passed, 1 test / 49 assertions.
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec328OperationsHubProductizationSmokeTest.php tests/Browser/Spec391OperationsHubStabilitySmokeTest.php`: passed, 4 tests / 95 assertions.
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/TableDetailVisibilityTest.php tests/Feature/Filament/TableStandardsCriticalListsTest.php tests/Feature/Findings/FindingsListDefaultsTest.php tests/Feature/Findings/FindingsListFiltersTest.php tests/Feature/Findings/MyWorkInboxTest.php tests/Feature/Findings/FindingsIntakeQueueTest.php tests/Feature/Monitoring/OperationsHubProductizationTest.php tests/Feature/Monitoring/Spec391OperationsHubStabilityTest.php tests/Feature/Monitoring/OperationsHeaderHierarchyTest.php tests/Feature/Monitoring/OperationsDbOnlyTest.php tests/Feature/Monitoring/OperationsTenantScopeTest.php`: passed, 71 tests / 722 assertions.
|
||||
- `cd apps/platform && ./vendor/bin/sail pint --dirty`: passed, 0 files changed.
|
||||
- `git diff --check`: passed.
|
||||
- Sail note: Docker Desktop context `desktop-linux` is available; stale orphaned Pest Browser/Playwright processes from earlier interrupted runs were cleaned before rerunning Sail validation.
|
||||
- Intermediate validation findings fixed in-loop:
|
||||
- Browser smoke asserted a fixture-specific Environment Dashboard recent-operations heading; narrowed to rendered default hierarchy and raw-payload absence.
|
||||
- Browser smoke asserted any occurrence of `Proof`; narrowed to the legacy labels replaced by this spec.
|
||||
- Existing Operations table standard expected at most seven visible columns; updated to the Spec 399 product-surface cap of eight.
|
||||
- Final manual review findings fixed in-loop:
|
||||
- Removed the default Operations Hub raw `Operation #<id>` workbench badge while preserving authorized OperationRun detail paths.
|
||||
- Strengthened Spec 399 Feature and Browser proof for Governance Inbox non-empty lane behavior, table row caps, hidden technical identifiers, collapsed diagnostics, and disclosure expansion.
|
||||
- Corrected `tasks.md` evidence paths so completed tasks reference the actual Spec 399 Feature/Browser files and existing affected tests.
|
||||
- Stabilized the Spec 399 Pest Browser smoke by leaving the Operations Hub page after the final assertion and aligning terminal OperationRun fixtures with `completed_at`.
|
||||
|
||||
## Files Changed
|
||||
|
||||
- Runtime: `TablePaginationProfiles`, Recent Operations dashboard widget, Workspace Overview recent operations view, Findings resource/list tables, My Findings inbox, Findings Intake queue, Operations Hub page/view/stats, OperationRun resource table.
|
||||
- Tests: Spec 399 Feature and Browser smoke coverage plus affected existing Filament/Findings/Monitoring tests.
|
||||
- Docs: UI route inventory and design coverage matrix.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- Broader secondary hot tables remain intentionally outside this selected slice.
|
||||
- Sail Browser validation is sensitive to orphaned Playwright server processes after interrupted runs; stale Spec 399 browser processes were cleaned before the final Sail validation.
|
||||
288
specs/399-dashboard-inbox-table-contract/plan.md
Normal file
288
specs/399-dashboard-inbox-table-contract/plan.md
Normal file
@ -0,0 +1,288 @@
|
||||
# Implementation Plan: Spec 399 - Dashboard / Inbox / Table Contract Migration v1
|
||||
|
||||
**Branch**: `399-dashboard-inbox-table-contract` | **Date**: 2026-06-22 | **Spec**: `specs/399-dashboard-inbox-table-contract/spec.md`
|
||||
**Input**: Feature specification from `/specs/399-dashboard-inbox-table-contract/spec.md`
|
||||
|
||||
## Summary
|
||||
|
||||
Migrate existing `/admin` dashboard, inbox, and table-heavy surfaces to the Product Surface Contract introduced by Spec 395. The implementation should reduce default-visible complexity on Environment Dashboard, Workspace Overview, Governance Inbox, Findings list/inbox surfaces, Operations Hub, and directly touched hot tables. It must demote technical proof links, cap or product-paginate tables, preserve existing RBAC/audit/OperationRun behavior, and avoid any new runtime Product Surface framework.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: PHP 8.4.15
|
||||
**Primary Dependencies**: Laravel 12.52, Filament 5.2.1, Livewire 4.1.4, Pest 4.3, Tailwind CSS 4.2 through existing assets only
|
||||
**Storage**: PostgreSQL via existing Laravel models; no schema change planned
|
||||
**Testing**: Pest Feature/Livewire/Filament tests and Pest Browser focused smoke
|
||||
**Validation Lanes**: confidence + browser; fast-feedback only for pure helper assertions if introduced
|
||||
**Target Platform**: Laravel Sail locally, Dokploy container deployments for staging/production
|
||||
**Project Type**: Laravel monolith in `apps/platform` with Filament admin panel at `/admin`
|
||||
**Performance Goals**: no new render-time remote calls; dashboard/inbox/table default views remain DB-only where currently DB-only
|
||||
**Constraints**: no migrations, no new persisted truth, no new Product Surface runtime framework, no completed-spec rewrites, no legacy compatibility shims
|
||||
**Scale/Scope**: existing operator-facing `/admin` dashboard/inbox/table surfaces and directly touched hot tables only
|
||||
|
||||
## UI / Surface Guardrail Plan
|
||||
|
||||
- **Guardrail scope**: changed rendered operator-facing surfaces.
|
||||
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**:
|
||||
- Environment Dashboard: `apps/platform/app/Filament/Pages/EnvironmentDashboard.php`, `apps/platform/app/Filament/Widgets/Dashboard/EnvironmentDashboardOverview.php`, `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-overview.blade.php`, and related dashboard widgets if touched.
|
||||
- Workspace Overview: `apps/platform/app/Filament/Pages/WorkspaceOverview.php`, `apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php`, workspace widgets under `apps/platform/app/Filament/Widgets/Workspace/`.
|
||||
- Governance Inbox: `apps/platform/app/Filament/Pages/Governance/GovernanceInbox.php`, `apps/platform/resources/views/filament/pages/governance/governance-inbox.blade.php`.
|
||||
- Findings: `apps/platform/app/Filament/Resources/FindingResource.php`, `apps/platform/app/Filament/Resources/FindingResource/Pages/ListFindings.php`, `apps/platform/app/Filament/Pages/Findings/MyFindingsInbox.php`, `apps/platform/app/Filament/Pages/Findings/FindingsIntakeQueue.php` where selected.
|
||||
- Operations Hub: `apps/platform/app/Filament/Pages/Monitoring/Operations.php`, `apps/platform/resources/views/filament/pages/monitoring/operations.blade.php`, and operation widgets if touched.
|
||||
- Touched hot tables in resources/pages/widgets named by implementation discovery.
|
||||
- **No-impact class, if applicable**: N/A.
|
||||
- **Native vs custom classification summary**: mixed. Native Filament tables/actions should be used first; existing custom Blade/dashboard views may be reduced in place without inventing a parallel UI system.
|
||||
- **Shared-family relevance**: dashboard signals, inbox lanes, Filament tables, action surfaces, OperationRun links, technical/audit links, badges/status messaging.
|
||||
- **State layers in scope**: page, widget/builder payload, table state, row/bulk actions, URL-query filters where already present.
|
||||
- **Audience modes in scope**: operator-MSP and manager by default; support-platform only for existing technical/detail paths; no new customer-facing default path.
|
||||
- **Decision/diagnostic/raw hierarchy plan**: decision-first defaults, diagnostics second, raw/support technical proof hidden/collapsed/capability-gated.
|
||||
- **Raw/support gating plan**: collapse or demote raw proof and technical detail; keep existing authorization.
|
||||
- **One-primary-action / duplicate-truth control**: every touched page/section/item gets one primary action or triage path; repeated readiness/status summaries are removed or demoted.
|
||||
- **Handling modes by drift class or surface**:
|
||||
- Product-facing dashboard/inbox/table overload: review-mandatory and fix in feature.
|
||||
- Existing completed-spec behavior outside touched files: report-only/context.
|
||||
- Product Surface budget exception: exception-required before runtime edit continues.
|
||||
- New runtime framework/status family/persistence need: hard-stop-candidate.
|
||||
- **Repository-signal treatment**: default `document-in-feature`; escalate to `follow-up-spec` only for recurring table/action framework gaps outside the selected slice.
|
||||
- **Special surface test profiles**: `standard-native-filament` for native tables, `monitoring-state-page` for Operations Hub, `global-context-shell` where Workspace Overview/Governance Inbox filters or shell state are affected.
|
||||
- **List-surface review checklist**: `docs/product/standards/list-surface-review-checklist.md` must be reviewed before table/list edits and its result recorded in the implementation report.
|
||||
- **Required tests or manual smoke**: Feature/Livewire table and action tests, focused browser smoke, Human Product Sanity.
|
||||
- **Exception path and spread control**: no exceptions planned. Any exception must name the page/table, violated Product Surface rule, reason, why it remains safe, and follow-up if temporary.
|
||||
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
|
||||
- **UI/Productization coverage decision**: update coverage artifacts for each rendered surface whose default UI changes.
|
||||
- **Coverage artifacts to update**: `docs/ui-ux-enterprise-audit/route-inventory.md` and `docs/ui-ux-enterprise-audit/design-coverage-matrix.md`; page reports only when route/archetype/coverage classification materially changes.
|
||||
- **No-impact rationale**: N/A.
|
||||
- **Navigation / Filament provider-panel handling**: no panel provider or navigation restructure planned. If navigation links to target surfaces change visibility/prominence, record coverage artifact updates first.
|
||||
- **Screenshot or page-report need**: focused browser screenshots/proof required for changed rendered surfaces; full page reports are proportional only when the existing registry becomes inaccurate.
|
||||
|
||||
## Product Surface Contract Plan
|
||||
|
||||
- **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md`.
|
||||
- **No-legacy posture**: canonical replacement. Do not preserve old overloaded layouts, labels, default row counts, proof links, or fixtures.
|
||||
- **Page archetype and surface budget plan**:
|
||||
- Environment Dashboard: Dashboard Page, planned pass.
|
||||
- Workspace Overview: Dashboard Page, planned pass.
|
||||
- Governance Inbox: Inbox Page, planned pass.
|
||||
- Findings list/inbox: Inbox Page or Search/Index Page by exact host, planned pass.
|
||||
- Operations Hub: Inbox Page with technical details demoted, planned pass.
|
||||
- Touched hot tables: inherit host archetype and must satisfy table caps/action budgets unless documented exception.
|
||||
- **Technical Annex and deep-link demotion plan**: demote OperationRun, raw evidence, source keys, detectors, fingerprints, UUIDs, payloads, provider payloads, raw report artifacts, restore proof, and technical logs from default product hierarchy.
|
||||
- **Canonical status vocabulary plan**: map top-level product statuses to `Ready`, `Needs attention`, `Blocked`, `Running`, `Failed`, `Expired`, `Not configured`, `Unknown`, `Historical`, `Superseded`; use allowed severities only.
|
||||
- **Product Surface exceptions**: none planned.
|
||||
- **Browser verification plan**: focused Spec 399 browser smoke over Environment Dashboard, Workspace Overview, Governance Inbox, Findings, Operations Hub, and at least one directly touched hot table.
|
||||
- **Human Product Sanity plan**: 5 to 15 minute review of changed surfaces, recorded in implementation report.
|
||||
- **Visible complexity outcome target**: decreased. Neutral is allowed only when implementation proves a larger removal on the same surface.
|
||||
- **Implementation report target**: `specs/399-dashboard-inbox-table-contract/implementation-report.md` during implementation.
|
||||
|
||||
## Filament / Livewire / Deployment Posture
|
||||
|
||||
- **Livewire v4 compliance**: Livewire 4.1.4 confirmed by Laravel Boost application info. No Livewire v3 APIs may be introduced.
|
||||
- **Panel provider registration location**: no panel provider changes planned; Laravel 12 panel providers remain in `apps/platform/bootstrap/providers.php`.
|
||||
- **Global search posture**: no global search changes planned. If a touched Resource's global search behavior is changed, implementation must update spec/plan first and ensure a safe View/Edit page plus `$recordTitleAttribute`, or keep global search disabled.
|
||||
- **Destructive/high-impact action posture**: no new destructive/high-impact actions planned. Any touched existing destructive or high-impact action must use `Action::make(...)->action(...)`, `->requiresConfirmation()`, server-side policy/gate authorization, audit logging where mutating, notification/error feedback, and Pest coverage.
|
||||
- **Asset strategy**: no new Filament assets planned. Use existing CSS/Blade/Filament primitives. `filament:assets` is not required unless implementation registers new assets, which is not expected.
|
||||
- **Testing plan**:
|
||||
- Feature/Livewire tests for row caps, table pagination/caps, default-hidden technical links, one primary action, and action grouping.
|
||||
- Existing surface tests updated where they assert old overloaded defaults.
|
||||
- Browser smoke over touched dashboard/inbox/table surfaces.
|
||||
- Browser or implementation-report proof for dark mode correctness, accessibility affordances, and Filament-native/shared-primitive semantics on touched custom Blade surfaces.
|
||||
- RBAC/authorization tests for any touched mutating or dangerous action.
|
||||
- **Deployment impact**: no env vars, migrations, queues, scheduler, storage, or assets expected.
|
||||
|
||||
## Shared Pattern & System Fit
|
||||
|
||||
- **Cross-cutting feature marker**: yes.
|
||||
- **Systems touched**: Product Surface Contract, Filament Table UX Standard, action-surface declarations, dashboard widgets/builders, inbox page/lane builders, OperationRun link/presenter helpers, badge/status helpers, UI audit coverage artifacts.
|
||||
- **Shared abstractions reused**: `TablePaginationProfiles`, `ActionSurfaceDeclaration` and related action-surface guard patterns, `BadgeCatalog` / `BadgeRenderer`, `UiEnforcement`, `WorkspaceUiEnforcement`, `OperationRunLinks`, `OperationUxPresenter`, existing surface builders/presenters.
|
||||
- **New abstraction introduced? why?**: none planned. Small local helpers are allowed only when they reduce duplication inside a touched surface and do not become a cross-domain runtime framework.
|
||||
- **Why the existing abstraction was sufficient or insufficient**: existing contracts already define budgets, status vocabulary, table profiles, and action/RBAC patterns. The implementation problem is default-visible hierarchy and table/link/action demotion, not missing platform truth.
|
||||
- **Bounded deviation / spread control**: any page-local collapse/cap/helper must stay in the touched surface or existing domain builder and be documented in the implementation report.
|
||||
|
||||
## OperationRun UX Impact
|
||||
|
||||
- **Touches OperationRun start/completion/link UX?**: yes, by demoting default OperationRun proof links and preserving existing operation start/completion behavior.
|
||||
- **Central contract reused**: `OperationRunLinks`, `OperationUxPresenter`, `OpsUxBrowserEvents`, `OperationRunService`, and the existing OperationRun lifecycle/notification path.
|
||||
- **Delegated UX behaviors**: queued toast, operation link, artifact link, run-enqueued browser event, dedupe/blocked/start-failure messaging, and tenant/workspace-safe URL resolution remain delegated to existing helpers.
|
||||
- **Surface-owned behavior kept local**: only placement/hierarchy of operation links within dashboards/inboxes/tables.
|
||||
- **Queued DB-notification policy**: unchanged; no new queued DB notification opt-in.
|
||||
- **Terminal notification path**: unchanged through central lifecycle.
|
||||
- **Exception path**: none planned.
|
||||
|
||||
## Provider Boundary & Portability Fit
|
||||
|
||||
- **Shared provider/platform boundary touched?**: no.
|
||||
- **Provider-owned seams**: existing provider-readiness/provider-connection display may be demoted if already on a touched surface, but provider credentials, Graph contracts, provider capability registry, and provider identity seams are not changed.
|
||||
- **Platform-core seams**: Product Surface vocabulary and operator UI labels only.
|
||||
- **Neutral platform terms / contracts preserved**: provider, environment, operation, evidence, finding, workspace.
|
||||
- **Retained provider-specific semantics and why**: Microsoft/Intune details remain only where already repo-real and required in technical/detail paths.
|
||||
- **Bounded extraction or follow-up path**: none planned.
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before implementation. Re-check after implementation discovery and before runtime UI edits if scope changes.*
|
||||
|
||||
- Inventory-first: pass; no Inventory truth changes.
|
||||
- Read/write separation: pass; no new writes. Existing writes/dangerous actions must keep preview/confirmation/audit/tests.
|
||||
- Graph contract path: pass; no Graph calls or contract changes.
|
||||
- Deterministic capabilities: pass; existing capability checks remain authoritative.
|
||||
- RBAC-UX: pass; UI visibility is not security, non-member 404 and member missing capability 403 semantics must remain intact.
|
||||
- Workspace isolation: pass; workspace route/filter ownership remains explicit.
|
||||
- Tenant isolation / managed-environment entitlement: pass; no cross-tenant aggregation changes.
|
||||
- Run observability: pass; no new OperationRun types or lifecycle paths.
|
||||
- OperationRun start UX: pass if existing helpers are reused; any local OperationRun UX composition is a blocker.
|
||||
- Ops-UX 3-surface feedback: pass; unchanged.
|
||||
- OperationRun lifecycle and summary counts: pass; no status/outcome/summary-count mutation planned.
|
||||
- Data minimization: pass; technical proof is demoted rather than expanded.
|
||||
- Test governance: pass with explicit confidence + browser lanes.
|
||||
- Proportionality: pass; no new persistence, abstraction, status family, taxonomy, or UI framework approved.
|
||||
- Shared pattern first: pass if existing table/action/badge/OperationRun helpers are reused.
|
||||
- Provider boundary: pass; no provider seam changes.
|
||||
- UI semantics / one truth few layers: pass; display maps existing truth directly to Product Surface vocabulary.
|
||||
- Product Surface Contract Gate: pass planned; active spec/plan/tasks name surfaces, budgets, browser proof, human sanity, no-legacy posture, and implementation-report fields.
|
||||
- Filament-native UI: pass planned; use native Filament components/shared primitives first and keep custom Blade inside existing surface conventions.
|
||||
- Action-surface discipline: pass planned; one inspect/open model, grouped destructive/bulk actions, no empty groups.
|
||||
- UI/Productization coverage: pass planned; route inventory and design matrix updates required for changed rendered surfaces.
|
||||
|
||||
## Test Governance Check
|
||||
|
||||
- **Test purpose / classification by changed surface**:
|
||||
- Environment Dashboard and Workspace Overview: Feature/Livewire + Browser.
|
||||
- Governance Inbox: Feature + Browser.
|
||||
- Findings table/inbox: Feature/Livewire table/action tests + Browser for selected host.
|
||||
- Operations Hub: Feature + Browser under `monitoring-state-page`.
|
||||
- Touched native tables: Feature/Livewire, browser only via changed host page.
|
||||
- **Affected validation lanes**: confidence and browser.
|
||||
- **Why this lane mix is the narrowest sufficient proof**: contract behavior is rendered UI plus table/action state; Feature tests prove data/action/link shape, Browser smoke proves first-viewport hierarchy and absence of runtime/console/Filament errors.
|
||||
- **Narrowest proving commands**:
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec399`
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php`
|
||||
- targeted existing Feature/Browser tests selected by implementation discovery
|
||||
- `cd apps/platform && ./vendor/bin/sail pint --dirty`
|
||||
- `git diff --check`
|
||||
- **Fixture / helper / factory / seed / context cost risks**: keep reuse of existing surface fixtures explicit; do not widen default factories or browser setup.
|
||||
- **Expensive defaults or shared helper growth introduced?**: no planned.
|
||||
- **Heavy-family additions, promotions, or visibility changes**: one explicit focused browser smoke; no broad browser audit.
|
||||
- **Surface-class relief / special coverage rule**: `standard-native-filament` relief for ordinary table cap tests; dashboard/inbox/Operations still require browser.
|
||||
- **Closing validation and reviewer handoff**: implementation report must state commands, results, browser proof, unrelated failures, Product Surface exceptions, Human Product Sanity, visible complexity outcome, and no completed-spec rewrite assertion.
|
||||
- **Budget / baseline / trend follow-up**: none expected; document-in-feature if browser fixture cost grows.
|
||||
- **Review-stop questions**: lane fit, breadth, hidden fixture cost, heavy-family risk, Product Surface exception status.
|
||||
- **Escalation path**: document-in-feature for contained exceptions; follow-up-spec only for structural table/action framework gaps.
|
||||
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
|
||||
- **Why no dedicated follow-up spec is needed**: this spec already owns the current dashboard/inbox/table Product Surface migration. Follow-up is only for secondary tables outside the touched slice.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/399-dashboard-inbox-table-contract/
|
||||
├── checklists/
|
||||
│ └── requirements.md
|
||||
├── plan.md
|
||||
├── spec.md
|
||||
└── tasks.md
|
||||
```
|
||||
|
||||
No data model, contracts, or quickstart are required for preparation because this feature introduces no API, persisted entity, external contract, or new runtime data model.
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
Likely implementation surfaces, subject to implementation discovery:
|
||||
|
||||
```text
|
||||
apps/platform/app/Filament/Pages/
|
||||
├── EnvironmentDashboard.php
|
||||
├── WorkspaceOverview.php
|
||||
├── Governance/GovernanceInbox.php
|
||||
├── Findings/MyFindingsInbox.php
|
||||
├── Findings/FindingsIntakeQueue.php
|
||||
└── Monitoring/Operations.php
|
||||
|
||||
apps/platform/app/Filament/Widgets/
|
||||
├── Dashboard/EnvironmentDashboardOverview.php
|
||||
├── Dashboard/RecentOperations.php
|
||||
└── Workspace/...
|
||||
|
||||
apps/platform/app/Filament/Resources/
|
||||
├── FindingResource.php
|
||||
├── FindingResource/Pages/ListFindings.php
|
||||
└── OperationRunResource.php
|
||||
|
||||
Secondary/deferred table candidates, not default implementation surfaces unless T014 records a direct narrow touch:
|
||||
|
||||
apps/platform/app/Filament/Resources/
|
||||
├── InventoryItemResource.php
|
||||
├── PolicyResource.php
|
||||
├── PolicyVersionResource.php
|
||||
├── ProviderConnectionResource.php
|
||||
├── BackupSetResource.php
|
||||
├── RestoreRunResource.php
|
||||
└── StoredReportResource.php
|
||||
|
||||
apps/platform/resources/views/filament/
|
||||
├── widgets/dashboard/environment-dashboard-overview.blade.php
|
||||
├── pages/governance/governance-inbox.blade.php
|
||||
└── pages/monitoring/operations.blade.php
|
||||
|
||||
apps/platform/tests/Feature/
|
||||
apps/platform/tests/Browser/
|
||||
|
||||
docs/ui-ux-enterprise-audit/
|
||||
├── route-inventory.md
|
||||
└── design-coverage-matrix.md
|
||||
```
|
||||
|
||||
**Structure Decision**: Use existing Laravel/Filament page, widget, resource, view, and test directories only. Do not create new base folders or runtime frameworks.
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||||
|-----------|------------|-------------------------------------|
|
||||
| None planned | N/A | N/A |
|
||||
|
||||
## Proportionality Review
|
||||
|
||||
- **Current operator problem**: dashboard, inbox, and table-heavy pages expose internal technical detail and too many actions/links/rows by default, making the next action harder to see.
|
||||
- **Existing structure is insufficient because**: the existing Product Surface Contract exists, but the selected runtime surfaces still need migration to its budgets and technical demotion rules.
|
||||
- **Narrowest correct implementation**: reduce existing surfaces and tests in place using native Filament/shared primitives first.
|
||||
- **Ownership cost created**: focused Feature/Browser tests and implementation-report evidence only.
|
||||
- **Alternative intentionally rejected**: Product Surface runtime framework, presenter/status family, persisted surface taxonomy, broad redesign, or compatibility mode.
|
||||
- **Release truth**: current-release productization cleanup.
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 0 - Discovery and target lock
|
||||
|
||||
- Re-read active spec, plan, `docs/product/standards/product-surface-contract.md`, `docs/product/standards/filament-table-ux.md`, `docs/ui/action-surface-contract.md`, `docs/ui/operator-ux-surface-standards.md`, `docs/filament-guidelines.md`, and relevant existing specs.
|
||||
- Inspect target files and tests to decide the exact first implementation slice.
|
||||
- Record selected surfaces, untouched/deferred surfaces, and Product Surface exceptions before runtime UI edits.
|
||||
|
||||
### Phase 1 - Table budget and action contract foundation
|
||||
|
||||
- Identify every table/list section touched by the selected surfaces.
|
||||
- Apply native Filament pagination/caps, product labels, hidden technical columns, one inspect/open model, and grouped destructive/bulk actions.
|
||||
- Add or update Feature/Livewire tests before or alongside implementation.
|
||||
|
||||
### Phase 2 - Dashboard default reduction
|
||||
|
||||
- Reduce Environment Dashboard and Workspace Overview default content to one primary question, compact summary, top attention items, one next action, and demoted proof/detail links.
|
||||
- Preserve existing authorized secondary/detail paths.
|
||||
- Update Feature tests and focused browser expectations.
|
||||
|
||||
### Phase 3 - Inbox and Findings triage reduction
|
||||
|
||||
- Reduce Governance Inbox and selected Findings surfaces to prioritized work items, product row labels, severity/state/scope, and one next action.
|
||||
- Demote source/evidence/OperationRun proof links.
|
||||
- Update lane/list tests and browser smoke.
|
||||
|
||||
### Phase 4 - Operations Hub classification and technical demotion
|
||||
|
||||
- Keep Operations Hub as attention-oriented Inbox behavior with technical details demoted.
|
||||
- Preserve OperationRun detail/technical paths for authorized users.
|
||||
- Ensure operation status/progress/outcome semantics remain existing truth and no new OperationRun UX is composed locally.
|
||||
|
||||
### Phase 5 - Coverage artifacts, browser proof, and close-out
|
||||
|
||||
- Update `docs/ui-ux-enterprise-audit/route-inventory.md` and `docs/ui-ux-enterprise-audit/design-coverage-matrix.md` for changed rendered surfaces.
|
||||
- Run focused tests/browser smoke, Pint, and diff checks.
|
||||
- Complete implementation report with Product Surface fields, no completed-spec rewrite assertion, Human Product Sanity, visible complexity outcome, deployment impact, and unrelated failure triage.
|
||||
537
specs/399-dashboard-inbox-table-contract/spec.md
Normal file
537
specs/399-dashboard-inbox-table-contract/spec.md
Normal file
@ -0,0 +1,537 @@
|
||||
# Feature Specification: Spec 399 - Dashboard / Inbox / Table Contract Migration v1
|
||||
|
||||
**Feature Branch**: `399-dashboard-inbox-table-contract`
|
||||
**Created**: 2026-06-22
|
||||
**Status**: Draft / Ready for preparation review
|
||||
**Type**: Product Surface Contract migration / dashboard-inbox-table runtime reduction
|
||||
**Input**: User-provided "Spec 399 - Dashboard / Inbox / Table Contract Migration v1" candidate, plus repo truth from Specs 327, 328, 330, 352, 370, 371, 391, 395, 397, 398, `docs/product/spec-candidates.md`, `docs/product/roadmap.md`, `docs/product/standards/product-surface-contract.md`, and current `/admin` surface code.
|
||||
|
||||
## Candidate Selection Context
|
||||
|
||||
- **Selected candidate**: Dashboard / Inbox / Table Contract Migration v1.
|
||||
- **Source**: Direct user-provided Spec 399 draft. Spec 395 also records "Dashboard and Inbox Link Budget Pass: Environment Dashboard, Workspace Overview, Governance Inbox, Findings, Operations Hub" as a follow-up candidate in `specs/395-product-surface-gate/implementation-report.md`.
|
||||
- **Why selected**: The active automatic queue in `docs/product/spec-candidates.md` remains empty, but this request provides an explicit productization candidate. Spec 397 prepared the receipt-page pass and Spec 398 prepared the decision-page pass. This package covers the remaining Product Surface Contract runtime-reduction family named by Spec 395: dashboard, inbox, and table-heavy surfaces.
|
||||
- **Close alternatives deferred**:
|
||||
- `management-report-pdf-staging-runtime-validation`: already represented by Spec 380 and not a dashboard/inbox/table migration.
|
||||
- `governance-artifact-lifecycle-retention-runtime`: manual-promotion only and broader than the selected UI contract pass.
|
||||
- `provider-readiness-onboarding-productization`: optional/manual provider-readiness work, not a surface-budget migration.
|
||||
- `cross-domain-indicator-runtime-follow-through`: broader guardrail follow-through; this spec is page-archetype based and narrower.
|
||||
- Receipt pages and decision pages: already covered by Specs 397 and 398 and must not be reopened here.
|
||||
- **Roadmap relationship**: Supports the roadmap's UI/Product Maturity Polish lane and the Product Surface Contract runtime-reduction direction without reopening completed productization lanes.
|
||||
- **Completed-spec guardrail result**: No `specs/399-*` package existed before this run. Related Specs 327, 328, 330, 352, 370, 371, 391, 395, 397, and 398 are context only. Completed close-out, validation, screenshots, browser evidence, checked task history, and post-implementation review language must not be rewritten.
|
||||
- **Smallest viable implementation slice**: Migrate existing `/admin` dashboard, inbox, and table-heavy default views to the existing Product Surface Contract. Primary targets are Environment Dashboard, Workspace Overview, Governance Inbox, Findings list/inbox surfaces, Operations Hub classification, and only the hot tables directly touched by those surfaces. Secondary tables are included only when narrow and directly related.
|
||||
|
||||
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
|
||||
|
||||
- **Problem**: Dashboard, inbox, and table-heavy `/admin` surfaces can still expose too many links, rows, statuses, readiness signals, technical proof references, bulk actions, or competing next actions by default.
|
||||
- **Today's failure**: Operators can land on surfaces that behave like internal object graphs instead of answering what needs attention, what needs triage, or how to find the right record. This can obscure the next action, make technical proof feel like product truth, and preserve UI bloat that Spec 395 explicitly flagged for runtime reduction.
|
||||
- **User-visible improvement**: Dashboards answer one attention question, inboxes prioritize triage work, hot tables cap or paginate default rows, and technical proof remains available only through deliberate detail/audit paths.
|
||||
- **Smallest enterprise-capable version**: A Product Surface Contract migration over existing pages, widgets, resources, table declarations, and views only. Reduce default visible complexity, cap touched hot tables, demote OperationRun/evidence/raw technical links, and verify with focused Feature/Filament plus browser proof.
|
||||
- **Explicit non-goals**: No new Product Surface runtime framework, no new presenter family, no new status enum family, no persisted taxonomy, no new dashboard redesign, no navigation redesign, no receipt-page rewrite, no decision-page rewrite, no customer portal work, no compatibility mode for old overloaded views, and no point-fix-only implementation.
|
||||
- **Permanent complexity imported**: Focused tests, browser smoke coverage, implementation-report evidence, and possibly small page-local or existing-shared helper cleanup if it reduces review burden. No new database table, migration, provider framework, status taxonomy, cross-domain UI framework, or broad abstraction is approved by this spec.
|
||||
- **Why now**: Spec 395 installed the Product Surface Contract gate and explicitly deferred dashboard/inbox/table reduction. Specs 397 and 398 prepared the adjacent receipt and decision page passes, leaving this as the next explicit Product Surface runtime-reduction slice.
|
||||
- **Why not local**: One-card or one-table tweaks would preserve the same failure mode on adjacent dashboard/inbox/table surfaces. This spec is cross-surface enough to enforce the existing contract, but bounded to named surfaces and touched tables.
|
||||
- **Approval class**: Cleanup / Workflow Compression.
|
||||
- **Red flags triggered**: Multiple surfaces and UI contract migration. Defense: the scope reduces visible complexity on existing surfaces, adds no new product truth, preserves existing safety controls, and forbids broad frameworks, new status families, and compatibility paths.
|
||||
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 2 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 12/12**
|
||||
- **Decision**: approve as a bounded Product Surface Contract dashboard/inbox/table migration slice.
|
||||
|
||||
## Spec Scope Fields *(mandatory)*
|
||||
|
||||
- **Scope**: canonical-view over existing `/admin` workspace and environment operator surfaces.
|
||||
- **Primary Routes / Surfaces**:
|
||||
- Environment Dashboard: `/admin/workspaces/{workspace}/environments/{environment}`, `App\Filament\Pages\EnvironmentDashboard`, `EnvironmentDashboardOverview`, `RecentOperations`, and dashboard Blade sections.
|
||||
- Workspace Overview: `/admin/workspaces/{workspace}/overview`, `App\Filament\Pages\WorkspaceOverview`, `WorkspaceOverviewBuilder`, and workspace summary/attention/operations widgets.
|
||||
- Governance Inbox: current `App\Filament\Pages\Governance\GovernanceInbox` workspace-hub route, including the canonical `environment_id` page filter where present.
|
||||
- Findings list / inbox surfaces: `App\Filament\Resources\FindingResource`, `ListFindings`, `MyFindingsInbox`, and `FindingsIntakeQueue` where selected by implementation.
|
||||
- Operations Hub: `App\Filament\Pages\Monitoring\Operations` and the related operations table/default workbench; OperationRun detail stays technical/detail context.
|
||||
- Hot tables directly touched by this spec: Findings, Governance Inbox lanes/list sections, Environment Dashboard table/widget sections, Workspace Overview table/widget sections, and Operations Hub table/history. Evidence Overview, Inventory, Policies, Policy Versions, Required Permissions, Provider Connections, Backup Sets, Restore Runs, and Stored Reports are secondary targets only if implementation touches them directly and can keep the change narrow.
|
||||
- **Data Ownership**: Existing workspace-owned and managed-environment-owned records remain authoritative. No new data owner, table, entity, persisted UI state, or Product Surface truth is introduced.
|
||||
- **RBAC**: Existing workspace membership, managed-environment entitlement, resource policies, capability checks, `UiEnforcement`, `WorkspaceUiEnforcement`, and deny-as-not-found behavior remain authoritative. Technical/audit detail requires the same or stricter authorization as today.
|
||||
|
||||
For canonical-view specs:
|
||||
|
||||
- **Default filter behavior when tenant-context is active**: Target pages remain route-owned by explicit workspace and, when applicable, explicit managed-environment route parameters or `environment_id` page filters. Hidden session or shell context must not change which environment or rows are shown.
|
||||
- **Explicit entitlement checks preventing cross-tenant leakage**: All linked findings, operation runs, evidence artifacts, provider connections, inventory rows, policies, backups, restore runs, and technical/audit paths must resolve through existing workspace/environment entitlement checks before display.
|
||||
|
||||
## No Legacy / No Backward Compatibility Constraint *(mandatory)*
|
||||
|
||||
TenantPilot is pre-production for this product-surface behavior.
|
||||
|
||||
- **Compatibility posture**: canonical replacement.
|
||||
- **Legacy aliases, fallback readers, hidden routes, duplicate UI, old labels, or historical fixtures kept?**: no.
|
||||
- **Why clean replacement is safe now**: There is no production customer-data compatibility requirement. Existing tests that assert old overloaded dashboard, inbox, or table defaults must be updated to the canonical Product Surface Contract behavior.
|
||||
|
||||
Forbidden implementation behavior:
|
||||
|
||||
- Keeping old overloaded dashboard/inbox/table layouts in parallel.
|
||||
- Preserving old default row counts because tests expect 25 rows.
|
||||
- Keeping OperationRun, Evidence Snapshot, source key, detector, fingerprint, UUID, or payload links as default product links.
|
||||
- Keeping raw IDs or technical identifiers as primary row labels.
|
||||
- Keeping destructive or bulk actions visually equivalent to normal navigation.
|
||||
- Adding compatibility helpers for old action labels, route aliases, table behavior, or dashboard sections.
|
||||
- Implementing isolated point fixes that do not satisfy the family-level dashboard/inbox/table contract for touched surfaces.
|
||||
|
||||
## UI Surface Impact *(mandatory - UI-COV-001)*
|
||||
|
||||
Does this spec add, remove, rename, or materially change any reachable UI surface?
|
||||
|
||||
- [ ] No UI surface impact
|
||||
- [x] Existing page changed
|
||||
- [ ] New page/route added
|
||||
- [ ] Navigation changed
|
||||
- [ ] Filament panel/provider surface changed
|
||||
- [ ] New modal/drawer/wizard/action added
|
||||
- [x] Existing table/form/state presentation changed
|
||||
- [ ] Customer-facing surface changed
|
||||
- [x] Dangerous or high-impact action presentation changed
|
||||
- [x] Status/evidence/review presentation changed
|
||||
- [x] Workspace/environment context presentation changed
|
||||
|
||||
## UI/Productization Coverage *(mandatory when UI Surface Impact is not "No UI surface impact")*
|
||||
|
||||
| Route/page/surface | Current/new archetype | Design depth | Repo-truth level | Existing pattern reused | New pattern required | Screenshot/browser proof | Page audit required | Customer-safe review | Dangerous-action review |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| Environment Dashboard | Dashboard Page | Strategic Surface | repo-verified | Specs 330/352, `EnvironmentDashboardOverview`, `EnvironmentDashboardSummaryBuilder`, Product Surface Contract | none expected; existing dashboard composition only | yes | no full page audit unless classification changes | no | yes for any touched operation/start/danger action |
|
||||
| Workspace Overview | Dashboard Page | Strategic Surface | repo-verified | `WorkspaceOverview`, `WorkspaceOverviewBuilder`, workspace summary/attention widgets, Product Surface Contract | none expected; existing overview composition only | yes | no full page audit unless classification changes | no | yes if any action hierarchy changes |
|
||||
| Governance Inbox | Inbox Page | Strategic Surface | repo-verified | Specs 327/346/389, `GovernanceInbox`, existing lane contracts and browser smoke | none expected; lane/link/demote work only | yes | no full page audit unless classification changes | no customer default | yes if any high-impact source actions are touched |
|
||||
| Findings list / findings inbox | Inbox Page / Search-Index Page | Domain Pattern Surface | repo-verified | `FindingResource`, Findings inbox/intake pages, `TablePaginationProfiles`, action-surface contract | none expected; existing Filament table/page patterns | yes | no full page audit unless classification changes | no | yes for bulk/exception/assignment actions |
|
||||
| Operations Hub | Inbox Page with technical details demoted | Strategic / Technical Boundary Surface | repo-verified | Specs 328/365/367/391, `Operations`, `OperationRunLinks`, `OperationsWorkbenchStats` | none expected; classify and reduce default technical exposure | yes | no full page audit unless route purpose changes | no | yes if retry/cancel/rerun actions are touched |
|
||||
| Hot tables directly touched | Search/Index, Inbox, Dashboard section, or Technical Annex by host page | Domain Pattern Surface | repo-verified per host | `TablePaginationProfiles`, Filament table standards, action-surface declarations | none expected | yes for rendered changed host page | no unless existing registry is inaccurate | no unless customer path is touched | yes where destructive/bulk actions exist |
|
||||
|
||||
Coverage files to update or explicitly not needed during implementation:
|
||||
|
||||
- [x] `docs/ui-ux-enterprise-audit/route-inventory.md`
|
||||
- [x] `docs/ui-ux-enterprise-audit/design-coverage-matrix.md`
|
||||
- [ ] `docs/ui-ux-enterprise-audit/page-reports/...`
|
||||
- [ ] `docs/ui-ux-enterprise-audit/strategic-surfaces.md`
|
||||
- [ ] `docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md`
|
||||
- [ ] `docs/ui-ux-enterprise-audit/unresolved-pages.md`
|
||||
- [ ] `N/A - no reachable UI surface impact`
|
||||
|
||||
Spec-level coverage registry decision:
|
||||
|
||||
| Coverage artifact | Decision | Reason |
|
||||
|---|---|---|
|
||||
| `docs/ui-ux-enterprise-audit/route-inventory.md` | Update during implementation for each target surface whose default rendered UI changes. | Dashboard/Inbox/Table classification and Product Surface migration must be visible in durable route inventory. |
|
||||
| `docs/ui-ux-enterprise-audit/design-coverage-matrix.md` | Update during implementation for each target surface whose default rendered UI changes. | The matrix must reflect Product Surface budget migration and focused browser-proof expectation. |
|
||||
| `docs/ui-ux-enterprise-audit/page-reports/...` | Not required by default. | Add or update page reports only if implementation changes archetype, expands default content, or discovers an existing page report is materially inaccurate. |
|
||||
| `docs/ui-ux-enterprise-audit/strategic-surfaces.md` | Not required by default. | No new strategic surface or navigation prominence is introduced. |
|
||||
| `docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md` | Not required by default. | Follow-up candidates are recorded in this active spec. |
|
||||
| `docs/ui-ux-enterprise-audit/unresolved-pages.md` | Not required unless implementation cannot classify or render a touched surface. | Planned target surfaces are classifiable under the Product Surface Contract. |
|
||||
|
||||
## Product Surface Impact *(mandatory for UI-affecting specs)*
|
||||
|
||||
Reference: `docs/product/standards/product-surface-contract.md`.
|
||||
|
||||
- **Product Surface Contract applies?**: yes. This spec materially changes rendered product dashboard, inbox, and table-heavy surfaces.
|
||||
- **Page archetype**:
|
||||
- Environment Dashboard: Dashboard Page.
|
||||
- Workspace Overview: Dashboard Page.
|
||||
- Governance Inbox: Inbox Page.
|
||||
- Findings list / findings inbox: Inbox Page or Search/Index Page, depending on the exact host.
|
||||
- Operations Hub: Inbox Page with technical details demoted. OperationRun detail remains technical/audit detail.
|
||||
- Hot tables: inherit the host page archetype, or Technical Annex/System Admin only when the host page is explicitly classified that way.
|
||||
- **Primary user question**:
|
||||
- Environment Dashboard: What needs attention in this environment right now?
|
||||
- Workspace Overview: Which workspace areas need attention first?
|
||||
- Governance Inbox: Which governance items need triage and what is the next action?
|
||||
- Findings: Which findings need action first?
|
||||
- Operations Hub: Which operations need attention, and where can internal users inspect technical run detail?
|
||||
- **Primary action**: Exactly one dominant product action or triage path per touched surface or focused card/row group.
|
||||
- **Surface budget result**: planned pass. Any exception must be documented in this spec and plan before runtime UI edits continue.
|
||||
- **Technical Annex / deep-link demotion**: OperationRun links, raw Evidence Snapshot or Evidence Artifact links, source keys, detectors, raw Finding fingerprints, UUIDs, provider payloads, raw report artifacts, restore operation proof, technical logs, JSON summaries, and payload links must be hidden, collapsed, capped, or moved to authorized detail/audit paths by default.
|
||||
- **Canonical status vocabulary**: Use `Ready`, `Needs attention`, `Blocked`, `Running`, `Failed`, `Expired`, `Not configured`, `Unknown`, `Historical`, `Superseded`, plus allowed severity states `Critical`, `High`, `Medium`, `Low`, and `Info`.
|
||||
- **List surface review checklist**: Because this spec modifies list/table surfaces, implementation must review `docs/product/standards/list-surface-review-checklist.md` before table edits and record the result in the implementation report.
|
||||
- **Visible complexity impact**: decreased or neutral only with documented larger removal elsewhere on the same surface.
|
||||
- **Product Surface exceptions**: none planned. Any unavoidable exception is a stop condition requiring spec and plan update.
|
||||
|
||||
## UI Action Matrix
|
||||
|
||||
| Surface | Primary action | Secondary actions | Technical/audit actions | Dangerous/high-impact actions | Mutation scope |
|
||||
|---|---|---|---|---|---|
|
||||
| Environment Dashboard | One state-based attention action such as `Review blockers`, `Verify provider`, `Open review`, or `Resolve finding`. | Up to two contextual actions per focused section, such as `Open environment`, `Open report`, or `Compare to current`. | `View audit trail`, `View technical run details`, or `View internal evidence details`; secondary and not default-dominant. | Existing operation-start or dangerous actions touched by implementation must remain non-primary, confirmed, authorized, audited, and observable. | Mostly read-only dashboard navigation; any operation start remains existing TenantPilot operation path. |
|
||||
| Workspace Overview | One workspace triage path such as `Review workspace attention`, `Open environment`, or `Review blockers`. | Up to two contextual actions per focused card/section. | Operations, evidence, report, or audit links are secondary/detail only. | None expected; any touched high-impact action must remain separated and confirmed. | Read-only overview and navigation unless existing actions are explicitly invoked. |
|
||||
| Governance Inbox | One triage action per work item or one top summary next action. | Up to two contextual links per item or lane. | Proof/evidence/run/detail links collapsed or secondary. | No new destructive action. Existing source-surface dangerous actions stay on their source pages or remain separated. | Mostly navigation/triage; mutations remain in source surfaces. |
|
||||
| Findings list / inbox | One inspect/triage action per row, shaped by Inbox or Search/Index archetype. | Up to two row secondary actions where justified. | Fingerprint, source key, detector, raw evidence, and operation detail hidden or technical. | Bulk exception/assignment/destructive actions must be grouped and confirmation/authorization protected where mutating. | Existing finding lifecycle, assignment, and exception paths only. |
|
||||
| Operations Hub | One attention/open action for the selected or highest-priority operation. | Up to two contextual artifact/source actions where authorized. | Raw OperationRun detail, context, payloads, failure internals, and technical run links are secondary or detail-only. | Retry/cancel/rerun actions, if touched, must remain secondary, confirmed where high-impact, authorized, audited, and Ops-UX compliant. | Existing OperationRun/operation action paths only. |
|
||||
| Touched hot tables | One row primary action or inspect model. | At most two visible secondary row actions by default. | Technical columns/links hidden, toggleable, collapsed, or moved to detail. | Bulk destructive/high-impact actions grouped and not visually equivalent to navigation. | Existing model/action scopes only. |
|
||||
|
||||
## Browser Verification Plan *(mandatory)*
|
||||
|
||||
- **Browser proof required?**: yes.
|
||||
- **No-browser rationale**: N/A - rendered UI changes are the purpose of this spec.
|
||||
- **Focused path when required**:
|
||||
- Environment Dashboard for one attention-needed environment and one calm/no-action environment where feasible.
|
||||
- Workspace Overview for a workspace with multiple visible environments or attention families.
|
||||
- Governance Inbox with at least one non-empty lane and one filtered or calm state.
|
||||
- Findings list/inbox with enough rows to prove row cap or product pagination.
|
||||
- Operations Hub with one attention-needed operation and diagnostics collapsed by default.
|
||||
- At least one directly touched hot table.
|
||||
- **Primary interaction to execute**:
|
||||
- Render first viewport and confirm one primary user question/action.
|
||||
- Verify table cap/pagination and one row primary action.
|
||||
- Expand one deliberate technical/audit disclosure where present and confirm technical detail is not default-visible.
|
||||
- Verify destructive/bulk actions are grouped/separated if touched.
|
||||
- **Console, Livewire, Filament, network, and 500-error checks**: required for focused browser smoke.
|
||||
- **Full-suite failure triage**: If unrelated browser failures remain, implementation must document the command, affected failures, why they are unrelated, and prove no touched dashboard/inbox/table surface failed.
|
||||
|
||||
## Human Product Sanity Check *(mandatory)*
|
||||
|
||||
- **Required?**: yes.
|
||||
- **No-human-sanity rationale**: N/A - rendered product surfaces change.
|
||||
- **Reviewer questions**:
|
||||
- Does each dashboard answer what needs attention now?
|
||||
- Does each inbox answer what needs triage?
|
||||
- Are tables capped or paginated before they become product noise?
|
||||
- Are technical details demoted?
|
||||
- Are there fewer default deep links?
|
||||
- Is there one dominant next action or triage path?
|
||||
- Are destructive/bulk actions separated?
|
||||
- Does the page feel less complex than before?
|
||||
- Would an operator trust the page?
|
||||
- **Planned result location**: implementation report and PR close-out.
|
||||
|
||||
## Product Surface Merge Gate Checklist *(mandatory)*
|
||||
|
||||
- [ ] No-legacy posture or approved exception recorded.
|
||||
- [ ] Product Surface Impact is completed and exceptions are `none` or explicitly approved.
|
||||
- [ ] Browser proof is completed for every rendered UI surface changed.
|
||||
- [ ] Human Product Sanity is completed.
|
||||
- [ ] Implementation report states Livewire v4 compliance, provider registration location, global search posture, destructive/high-impact action posture, asset strategy, tests/browser result, deployment impact, visible complexity outcome, and no completed-spec rewrite assertion.
|
||||
|
||||
## Cross-Cutting / Shared Pattern Reuse *(mandatory)*
|
||||
|
||||
- **Cross-cutting feature?**: yes.
|
||||
- **Interaction classes**: dashboard signals/cards, inbox lanes, table pagination/row actions, status messaging, action links, technical/audit links, OperationRun evidence links, destructive/bulk action grouping, and browser/human sanity proof.
|
||||
- **Systems touched**:
|
||||
- `App\Filament\Pages\EnvironmentDashboard`
|
||||
- `App\Filament\Widgets\Dashboard\EnvironmentDashboardOverview`
|
||||
- `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-overview.blade.php`
|
||||
- `App\Filament\Pages\WorkspaceOverview`
|
||||
- `App\Support\Workspaces\WorkspaceOverviewBuilder`
|
||||
- `App\Filament\Pages\Governance\GovernanceInbox`
|
||||
- `apps/platform/resources/views/filament/pages/governance/governance-inbox.blade.php`
|
||||
- `App\Filament\Resources\FindingResource`
|
||||
- `App\Filament\Pages\Monitoring\Operations`
|
||||
- `apps/platform/resources/views/filament/pages/monitoring/operations.blade.php`
|
||||
- directly touched table resources/pages/widgets.
|
||||
- **Existing pattern(s) to extend**: Product Surface Contract, Filament Table UX Standard, `TablePaginationProfiles`, action-surface declarations, `BadgeCatalog` / `BadgeRenderer`, `UiEnforcement`, `WorkspaceUiEnforcement`, `OperationRunLinks`, `OperationUxPresenter`, and existing browser fixture helpers.
|
||||
- **Shared contract / presenter / builder / renderer to reuse**: reuse existing builders/presenters/helpers first. New helper extraction is allowed only when it reduces real review burden inside touched surfaces and does not become a generic Product Surface runtime framework.
|
||||
- **Why the existing shared path is sufficient or insufficient**: The Product Surface Contract already supplies the vocabulary and budgets. Existing page builders and Filament table APIs already supply most state and interaction structure. The gap is default-visible hierarchy, row/link/action budget enforcement, and technical demotion, not missing product truth.
|
||||
- **Allowed deviation and why**: page-local collapsed detail, row-cap, or link-demotion helpers may be used if current Filament/table/view structure cannot express the contract cleanly. No cross-domain Product Surface runtime framework is approved.
|
||||
- **Consistency impact**: one primary question/action, canonical status vocabulary, row/action/link budgets, technical demotion, and high-impact action separation must stay aligned across touched dashboard, inbox, and table surfaces.
|
||||
- **Review focus**: no point fixes, no default OperationRun proof, no raw evidence/payload leakage, no duplicate readiness summaries, no fake "all clear", no weakened RBAC, no completed-spec rewrites, and no new framework.
|
||||
|
||||
## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)*
|
||||
|
||||
- **Touches OperationRun start/completion/link UX?**: yes, by demoting default OperationRun proof links and preserving existing operation-start behavior on touched surfaces.
|
||||
- **Shared OperationRun UX contract/layer reused**: existing `OperationRunLinks`, `OperationUxPresenter`, `OpsUxBrowserEvents`, `OperationRunService`, and current operation resource links.
|
||||
- **Delegated start/completion UX behaviors**: existing queued toast, artifact link, `Open operation` link, run-enqueued browser event, tenant/workspace-safe URL resolution, dedupe/start-failure messaging, and terminal notification paths remain delegated to existing helpers.
|
||||
- **Local surface-owned behavior that remains**: deciding whether an operation link is product-secondary/audit detail or hidden from the default dashboard/inbox/table view.
|
||||
- **Queued DB-notification policy**: unchanged; no new queued DB notification opt-in.
|
||||
- **Terminal notification path**: unchanged through central lifecycle mechanism.
|
||||
- **Exception required?**: none planned.
|
||||
|
||||
## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)*
|
||||
|
||||
- **Shared provider/platform boundary touched?**: no new shared provider/platform boundary.
|
||||
- **Boundary classification**: N/A.
|
||||
- **Seams affected**: existing provider-readiness/provider-connection display may be demoted when already present on dashboard/table surfaces, but no provider identity, contract, registry, credential, Graph endpoint, or provider capability seam changes are in scope.
|
||||
- **Neutral platform terms preserved or introduced**: use `provider`, `environment`, `operation`, `evidence`, `finding`, and Product Surface vocabulary where product-facing; provider-specific terms remain diagnostics/detail when not required for the immediate decision.
|
||||
- **Provider-specific semantics retained and why**: existing Microsoft/Intune details may remain in technical/audit detail only where repo-real and authorized.
|
||||
- **Why this does not deepen provider coupling accidentally**: the spec reduces default-visible provider technical detail and introduces no new provider-owned truth.
|
||||
- **Follow-up path**: none planned.
|
||||
|
||||
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*
|
||||
|
||||
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|
||||
|---|---|---|---|---|---|---|
|
||||
| Environment Dashboard reduction | yes | mixed Filament Page, widgets, Blade | dashboard signals, action links, status messaging | page, widget payload, route environment | none planned | existing route only |
|
||||
| Workspace Overview reduction | yes | mixed Filament Page, widgets, builder payload | dashboard signals, operations/action links | page, builder payload, workspace route | none planned | existing route only |
|
||||
| Governance Inbox reduction | yes | custom Blade inside Filament Page | inbox lanes, action links, disclosure | page, URL-query filter, lane state | none planned | existing route only |
|
||||
| Findings table/inbox reduction | yes | native Filament table/pages plus inbox pages | table/action-surface family | table state, row actions, bulk actions | none planned | existing routes only |
|
||||
| Operations Hub classification/reduction | yes | mixed Filament Page, widgets, Blade/table | operations, OperationRun links, status messaging | page, URL-query filter, table state | none planned | existing route only |
|
||||
| Touched hot table contract | yes | native Filament tables where possible | table/action-surface family | table pagination, columns, row/bulk actions | none planned | host-page bounded |
|
||||
|
||||
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
|
||||
|
||||
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| Environment Dashboard | Primary Decision Surface | Operator decides what needs attention in one environment | environment state, top attention items, compact summary, recommended action | operations, evidence, provider diagnostics, raw payloads | Primary because it is the environment command surface | environment readiness/governance workflow | prevents scanning proof cards and related object links first |
|
||||
| Workspace Overview | Primary Decision Surface | Operator decides which workspace area or environment to inspect first | workspace state, top attention items, compact portfolio summary, triage path | operations history, evidence/report links, environment technical detail | Primary because it is the workspace entry surface | workspace triage workflow | reduces portfolio search and link floods |
|
||||
| Governance Inbox | Primary Decision Surface | Operator triages governance work items | prioritized items, state/severity, scope, impact/reason, next action | proof links, source detail, diagnostics | Primary because it is the governance work queue | triage workflow | reduces proof graph navigation before work selection |
|
||||
| Findings list / inbox | Primary Decision or Search/Index Surface | Operator finds and triages findings | finding label, severity/state, affected scope, owner/next action | fingerprint, detector, source key, raw evidence | Primary only for finding triage; search/index when browsing records | findings workflow | reduces row/link/action overload |
|
||||
| Operations Hub | Secondary Context Surface with Inbox behavior | Operator identifies operations needing attention and opens deliberate run detail | operation purpose/state/impact/next action | raw run context, payloads, stack traces, diagnostics | Not a raw product noun hub; supports operations follow-up | operations attention workflow | keeps technical run inspection secondary |
|
||||
|
||||
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
|
||||
|
||||
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| Environment Dashboard | operator-MSP, manager, support-platform | state, reason, top attention, next action | operations/evidence/provider detail | raw provider payloads, run context, evidence internals | review/resolve the primary blocker | raw IDs, OperationRun proof, evidence links | one readiness/status model per concept |
|
||||
| Workspace Overview | operator-MSP, manager | workspace posture, top attention items, environment scope | operations/evidence/report detail | internal raw records | open the highest-priority area | long tables, raw links, duplicate readiness | summary states each blocker once |
|
||||
| Governance Inbox | operator-MSP, manager | prioritized work, severity/state, reason, next action | source detail, proof summaries | raw evidence/run/payload detail | triage selected item | proof graph links and diagnostics | lanes add context without restating top blocker repeatedly |
|
||||
| Findings list / inbox | operator-MSP, manager | product finding label, severity/state, scope, owner/next action | source, detector, evidence when expanded | fingerprints, source keys, UUIDs | inspect/resolve finding | raw technical identifiers | table row uses one product identity |
|
||||
| Operations Hub | operator-MSP, support-platform | operation purpose, state/outcome, impact, next action | run detail, related artifact, progress detail | raw context, stack traces, payloads | open/resolve attention operation | raw run IDs and payloads | active/terminal truths not repeated as dashboards |
|
||||
|
||||
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
|
||||
|
||||
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| Environment Dashboard | Dashboard / Workbench | Dashboard Page | review top attention item | primary action/link per focused area | N/A | secondary card/detail path | More/detail only | `/admin/workspaces/{workspace}/environments/{environment}` | existing child/detail routes | workspace + environment | Environment Dashboard | state, top attention, next action | none |
|
||||
| Workspace Overview | Dashboard / Workbench | Dashboard Page | open highest-priority workspace area | primary card/action | N/A | secondary card/action group | More/detail only | `/admin/workspaces/{workspace}/overview` | existing environment/detail routes | workspace | Workspace Overview | workspace attention, environment priority | none |
|
||||
| Governance Inbox | Queue / Review | Inbox Page | triage selected governance item | explicit item action or selected detail | not default full-row click | source/detail disclosure | source surfaces only | current Governance Inbox route | source record routes | workspace + optional environment filter | Governance Inbox | prioritized work, impact, next action | none |
|
||||
| Findings list / inbox | List / Table / Queue | Inbox or Search/Index Page | inspect or resolve finding | row inspect/recordUrl per host contract | host-specific | More/detail or secondary row action | grouped bulk/detail | current FindingResource/inbox routes | finding detail route | workspace + environment | Findings | severity, state, scope, next action | none |
|
||||
| Operations Hub | Workbench / Monitoring | Inbox with technical detail demoted | open attention operation or related source | selected operation/action | host-specific | technical/detail path | More/detail only if present | current Operations route | OperationRun detail route | workspace + optional environment filter | Operations | operation purpose, state/outcome, impact | none |
|
||||
|
||||
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
|
||||
|
||||
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| Environment Dashboard | MSP operator / manager | Decide which environment issue needs attention first | Dashboard Page | What needs attention in this environment right now? | state, reason, top attention items, compact summary, next action | raw evidence, OperationRun proof, provider payloads, technical diagnostics | readiness/lifecycle, severity, operation attention where relevant | mostly navigation; operation starts through existing actions only | review blocker, verify provider, resolve finding, open review | none introduced; touched existing danger actions stay separated |
|
||||
| Workspace Overview | MSP operator / manager | Decide which workspace area or environment to inspect first | Dashboard Page | Which workspace areas need attention first? | workspace state, top environment/workspace attention, compact metrics, triage path | operations history, evidence/report internals | workspace attention, environment state, operation attention | navigation only unless existing action selected | open prioritized area/environment | none introduced |
|
||||
| Governance Inbox | MSP operator / manager | Triage governance items | Inbox Page | Which governance items need triage and what is the next action? | item, severity/state, scope, reason/impact, next action | source detail, proof, diagnostics | governance state, severity, due/freshness where existing | source-surface mutations only | triage item, open source | none introduced |
|
||||
| Findings list / inbox | MSP operator / manager | Triage findings by severity/state/scope | Inbox / Search-Index | Which findings need action first? | product label, severity, state, scope, owner/action | fingerprint, source key, detector output, raw evidence | finding state, severity, ownership | existing finding assignment/exception paths only | inspect/resolve finding | bulk/destructive actions grouped and confirmed |
|
||||
| Operations Hub | Operator / support reviewer | Identify operations needing attention and open deliberate run detail | Inbox with technical detail demoted | Which operations need attention? | operation purpose, state/outcome, impact, environment, next action | raw run context, stack traces, payloads | execution status, outcome, progress if trustworthy | existing operation action paths only | open attention operation/source | retry/cancel/rerun only if existing and separated |
|
||||
|
||||
## Proportionality Review *(mandatory when structural complexity is introduced)*
|
||||
|
||||
- **New source of truth?**: no.
|
||||
- **New persisted entity/table/artifact?**: no.
|
||||
- **New abstraction?**: no broad abstraction approved.
|
||||
- **New enum/state/reason family?**: no.
|
||||
- **New cross-domain UI framework/taxonomy?**: no.
|
||||
- **Current operator problem**: overloaded dashboards, inboxes, and tables hide the next action behind technical proof and row/link/action noise.
|
||||
- **Existing structure is insufficient because**: existing surfaces already have the data and shared contracts, but default presentation still violates Product Surface budgets and deep-link demotion rules on the named surface family.
|
||||
- **Narrowest correct implementation**: reduce existing pages, widgets, table definitions, views, and tests; do not introduce new Product Surface truth.
|
||||
- **Ownership cost**: focused tests, focused browser proof, implementation-report evidence, and page/table-specific cleanup only.
|
||||
- **Alternative intentionally rejected**: a reusable Product Surface runtime framework, dashboard engine, inbox engine, persisted surface taxonomy, or broad product redesign.
|
||||
- **Release truth**: current-release productization cleanup.
|
||||
|
||||
### Compatibility posture
|
||||
|
||||
This feature assumes a pre-production environment. Backward compatibility, legacy aliases, migration shims, hidden old layouts, old table defaults, and compatibility-specific tests are out of scope unless this spec is updated with an explicit approved exception.
|
||||
|
||||
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
|
||||
|
||||
- **Test purpose / classification**: Feature / Filament-Livewire / Browser, with Unit tests only for existing builders/helpers if their output must drive the surface budget.
|
||||
- **Validation lane(s)**: confidence plus browser. Fast-feedback may cover pure helper assertions; browser proof is required for changed rendered surfaces.
|
||||
- **Why this classification and these lanes are sufficient**: Feature/Livewire tests prove table row caps, link/action demotion, RBAC-visible action state, and default text. Browser smoke proves actual first-viewport hierarchy, table caps, disclosure state, and no runtime/console/Filament failures.
|
||||
- **New or expanded test families**: one explicit Spec 399 focused Feature/Filament set and one explicit browser smoke file if existing browser coverage cannot prove the contract.
|
||||
- **Fixture / helper cost impact**: reuse existing workspace/environment/browser harnesses and fixtures from Specs 327, 328, 330, 346, 352, 391, and related Feature tests. Do not widen default factories or browser setup.
|
||||
- **Heavy-family visibility / justification**: one focused browser family is explicit and justified because rendered UI and Product Surface Contract behavior are the product value of this spec.
|
||||
- **Special surface test profile**: `standard-native-filament` for native table reductions; `monitoring-state-page` for Operations Hub; `global-context-shell` for Workspace Overview/Governance Inbox filter behavior where affected.
|
||||
- **Standard-native relief or required special coverage**: standard-native relief applies only to ordinary table pagination/columns after Feature tests prove row/action/link budgets. Dashboard/inbox/Operations changes still require browser smoke.
|
||||
- **Reviewer handoff**: reviewers must confirm lane fit, hidden fixture cost, no completed-spec rewrite, Product Surface exceptions, and the exact proof commands in the implementation report.
|
||||
- **Budget / baseline / trend impact**: low to medium; bounded Feature/Browser additions. Escalate in-feature if browser setup grows beyond the named surfaces.
|
||||
- **Escalation needed**: document-in-feature for contained exceptions; follow-up-spec only if a recurring table/action framework gap is discovered.
|
||||
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
|
||||
- **Planned validation commands**:
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec399`
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php`
|
||||
- Affected existing Feature/Browser tests named by implementation discovery.
|
||||
- `cd apps/platform && ./vendor/bin/sail pint --dirty`
|
||||
- `git diff --check`
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - Dashboards answer one attention question (Priority: P1)
|
||||
|
||||
As an MSP operator, I want Environment Dashboard and Workspace Overview to show one primary attention question, compact summary, and a dominant next action so I can decide where to work without scanning technical proof and related object links first.
|
||||
|
||||
**Why this priority**: Dashboards are first-entry surfaces. If they remain noisy, later inbox/table reductions do not produce a calm operator path.
|
||||
|
||||
**Independent Test**: Open Environment Dashboard and Workspace Overview with representative fixtures. The first viewport shows the primary question, compact summary, top attention items, and one dominant next action. It does not default-show OperationRun proof links, raw evidence links, raw IDs, repeated readiness/status models, or long technical tables.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an environment with provider, findings, evidence, and operations context, **When** an authorized operator opens Environment Dashboard, **Then** the default view answers what needs attention and exposes only deliberate secondary/detail paths for proof.
|
||||
2. **Given** a workspace with multiple visible environments or attention families, **When** an authorized operator opens Workspace Overview, **Then** the default view prioritizes workspace areas and does not expose a long operations/evidence/report table by default.
|
||||
3. **Given** a calm/no-action environment or workspace, **When** the dashboard opens, **Then** it shows an honest calm state without false "all clear" product claims or duplicate readiness summaries.
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - Inboxes prioritize triage work (Priority: P1)
|
||||
|
||||
As an operator, I want Governance Inbox and Findings surfaces to show the item, state/severity, scope, impact/reason, and next action so I can triage work without following a proof graph per row.
|
||||
|
||||
**Why this priority**: Governance Inbox and Findings are work queues. Their default state must support triage, not technical reconstruction.
|
||||
|
||||
**Independent Test**: Open Governance Inbox and Findings list/inbox with non-empty fixtures. Rows/items show product labels, severity/state, scope, impact/reason, and one primary triage/inspect action. Default rows do not expose OperationRun links, source keys, detectors, fingerprints, UUIDs, or excessive inline links.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** active governance items, **When** Governance Inbox renders, **Then** each visible item has one primary triage path and technical/proof links are secondary or collapsed.
|
||||
2. **Given** more findings than the default table budget, **When** Findings renders, **Then** the default list uses product pagination or a maximum of eight visible rows; any inability to meet that budget requires a Product Surface exception before implementation continues.
|
||||
3. **Given** bulk or high-impact finding actions are available, **When** the operator scans the list, **Then** those actions are grouped/separated and cannot be confused with normal navigation.
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 - Hot tables obey row, link, and action budgets (Priority: P1)
|
||||
|
||||
As an operator scanning product-facing tables, I want hot tables to show a small number of product-labelled rows and one primary action so I can find the relevant record without technical columns and inline link floods.
|
||||
|
||||
**Why this priority**: Table overload is the repeated failure mode across dashboard and inbox surfaces.
|
||||
|
||||
**Independent Test**: For every hot table touched by implementation, Feature/Livewire tests assert row cap or product pagination, product row labels, one row primary action, no raw IDs as primary labels, no default technical columns, and grouped destructive/bulk actions.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** a touched product-facing table with more than eight records, **When** it renders in a dashboard/inbox/default product context, **Then** it shows at most eight visible rows before Show more, pagination, or full-table navigation; any inability to meet that budget requires a Product Surface exception before implementation continues.
|
||||
2. **Given** a touched row with technical references, **When** it renders, **Then** raw UUIDs, source keys, detector output, fingerprints, and raw payload references are absent from primary labels/default columns.
|
||||
3. **Given** a touched table has destructive or bulk actions, **When** the action area renders, **Then** destructive/high-impact actions are grouped or separated and remain confirmation/authorization protected.
|
||||
|
||||
---
|
||||
|
||||
### User Story 4 - Operations Hub is not a raw run browser by default (Priority: P2)
|
||||
|
||||
As an operations responder, I want Operations Hub to show operations needing attention while keeping raw OperationRun detail deliberate, so I can respond without treating internal run records as the product's primary noun.
|
||||
|
||||
**Why this priority**: Operations is a critical diagnostic surface, but it should not leak technical run detail into product entry points by default.
|
||||
|
||||
**Independent Test**: Open Operations Hub with attention-needed and completed runs. The default surface shows operation purpose, state/outcome, impact, environment/scope, and one next action. Raw run IDs, payloads, debug errors, and technical diagnostics are not default-visible. OperationRun detail remains reachable through authorized deliberate paths.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an attention-needed operation exists, **When** Operations Hub opens, **Then** the page answers which operation needs attention and shows one primary action or source/detail path.
|
||||
2. **Given** raw run context or failure internals exist, **When** the page opens, **Then** those details are collapsed, hidden, or moved to technical detail.
|
||||
3. **Given** successful historical operations exist, **When** the page opens, **Then** the surface does not present them as environment health, governance health, or a primary product success dashboard.
|
||||
|
||||
---
|
||||
|
||||
### User Story 5 - Technical proof remains reachable and safe (Priority: P2)
|
||||
|
||||
As an authorized internal user, I want technical proof and audit detail to remain reachable through deliberate paths so surface simplification does not remove troubleshooting or auditability.
|
||||
|
||||
**Why this priority**: Product Surface reduction must reduce default-visible complexity without hiding evidence from authorized users who need it.
|
||||
|
||||
**Independent Test**: For each touched surface, tests or browser smoke prove technical/audit/detail links are absent from the default primary hierarchy but available through an authorized secondary/detail path where the existing product already supported them.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authorized operator has access to a touched source record, **When** they choose a secondary/detail path, **Then** existing technical/audit proof remains reachable subject to current authorization.
|
||||
2. **Given** a user lacks workspace/environment entitlement, **When** they attempt to reach a demoted technical path, **Then** the system still denies as not found or forbidden according to existing RBAC semantics.
|
||||
3. **Given** implementation demotes a link from a dashboard/inbox/table, **When** the feature closes, **Then** the implementation report states where authorized users can still inspect the technical proof or why that proof path was intentionally not present before.
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- A touched dashboard has no attention items: show an honest no-action state without fake health or duplicate readiness claims.
|
||||
- A touched table cannot practically show exactly eight rows because it uses native pagination defaults: document the Product Surface pass or exception and prove the default does not create a product-facing row flood.
|
||||
- A table is clearly Technical Annex or System Admin: it may show more technical detail only when the host page is classified accordingly.
|
||||
- An OperationRun link is the only available path to diagnose a failed operation: keep it as secondary/detail, not as default product proof.
|
||||
- A destructive/bulk action is hidden by RBAC: the server-side authorization remains authoritative and tests must cover denied execution where the action is touched.
|
||||
- Existing browser full-suite failures unrelated to touched surfaces: document them without marking Spec 399 green if any touched surface fails.
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-399-001**: Environment Dashboard MUST answer "What needs attention in this environment right now?" and reduce default proof, deep-link, readiness, and diagnostics overload.
|
||||
- **FR-399-002**: Workspace Overview MUST answer "Which workspace areas need attention first?" and reduce default operations/evidence/report table overload.
|
||||
- **FR-399-003**: Governance Inbox MUST prioritize governance work items and demote proof/evidence/operation links from default row/item actions.
|
||||
- **FR-399-004**: Findings list/inbox surfaces touched by implementation MUST show product labels, severity/state, affected scope, owner or next action, and one primary inspect/triage action.
|
||||
- **FR-399-005**: Operations Hub MUST be treated as an Inbox Page with technical details demoted from the default view; OperationRun detail remains deliberate technical/audit context.
|
||||
- **FR-399-006**: Every touched product-facing hot table MUST obey row, link, action, and technical-column budgets from the Product Surface Contract or document a bounded exception before implementation continues.
|
||||
- **FR-399-007**: Touched dashboard/inbox/table default views MUST NOT expose OperationRun proof links, raw Evidence links, source keys, detectors, fingerprints, raw payloads, UUIDs, or technical logs as primary product content.
|
||||
- **FR-399-008**: Touched surfaces MUST keep exactly one dominant next action or triage path per page/section/item; any inability to meet this budget requires a Product Surface exception before implementation continues.
|
||||
- **FR-399-009**: Touched destructive, bulk, or high-impact actions MUST remain visually separated, confirmation-protected where mutating/destructive, server-authorized, and audit-safe.
|
||||
- **FR-399-010**: Tests that assert old overloaded dashboards, 25-row hot tables, default OperationRun proof links, or excessive evidence links MUST be updated to assert the new contract.
|
||||
- **FR-399-011**: Implementation MUST NOT create a Product Surface runtime framework, presenter family, status enum family, component framework, persisted taxonomy, or broad design system.
|
||||
- **FR-399-012**: Implementation MUST update Product Surface implementation-report fields and UI coverage artifacts for each rendered surface whose default UI changes.
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
- **NFR-399-001**: Rendered `/admin` pages must remain DB-only where they are currently DB-only; no Graph calls may be introduced during render.
|
||||
- **NFR-399-002**: Browser smoke must remain focused and fixture-bounded to touched surfaces.
|
||||
- **NFR-399-003**: Visible complexity must decrease or remain neutral only when the implementation report proves a larger removal on the same surface.
|
||||
- **NFR-399-004**: The implementation must preserve dark mode correctness, accessibility affordances, and Filament-native semantics for custom Blade areas touched.
|
||||
- **NFR-399-005**: The implementation must not broaden test fixtures, factories, browser setup, workspace context helpers, or heavy-governance lane cost beyond the named surface proof.
|
||||
|
||||
### UX Requirements
|
||||
|
||||
- Dashboard pages must default to compact attention, summary, and next-action content rather than proof graphs.
|
||||
- Inbox pages must default to prioritized work items rather than raw related-object navigation.
|
||||
- Product-facing tables must default to clear row identity, one primary action, product status, and capped/paginated rows.
|
||||
- Technical detail remains behind deliberate secondary/detail/audit disclosure.
|
||||
- Product copy must prefer `Needs attention`, `Review blockers`, `Resolve finding`, `Verify provider`, `Open environment`, `View audit trail`, and `View details`.
|
||||
- Default product copy must avoid `OperationRun`, `Evidence artifact`, `Source key`, `Detector`, `Fingerprint`, `Payload`, `UUID`, `Raw metadata`, `Scope key`, and `Technical dimension` except in technical/audit paths.
|
||||
|
||||
### RBAC / Security Requirements
|
||||
|
||||
- Existing workspace and managed-environment entitlement checks remain authoritative.
|
||||
- UI visibility is not authorization; every touched mutating action must retain server-side policy/gate enforcement.
|
||||
- Non-members or non-entitled users must continue to receive deny-as-not-found semantics where currently required.
|
||||
- Member-but-missing-capability execution denial remains 403 where existing policy semantics require it.
|
||||
- Technical/audit detail requires the same or stricter authorization as before.
|
||||
- Global search posture must not change unless the active implementation explicitly touches a Resource's global search behavior and updates this spec/plan first.
|
||||
|
||||
### Auditability / Observability Requirements
|
||||
|
||||
- No new OperationRun type, status, summary-count key, notification class, or operation lifecycle path is introduced.
|
||||
- Existing OperationRun start/completion UX must remain delegated to the central OperationRun UX layer when touched.
|
||||
- Existing audit logging for mutating/destructive/high-impact actions must not be weakened.
|
||||
- If a touched action newly changes mutation placement or grouping, tests must prove confirmation/authorization/audit behavior remains intact.
|
||||
|
||||
### Data / Truth-Source Requirements
|
||||
|
||||
- Prefer existing data and computed states.
|
||||
- No new tables, migrations, persisted UI state, or compatibility fields are in scope.
|
||||
- Product status display must map from existing domain truth to Product Surface vocabulary without creating a new status family.
|
||||
- Technical proof demotion must move display placement only; it must not delete evidence, operation, or audit truth.
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
- Rewriting Spec 395, Spec 397, or Spec 398.
|
||||
- Rewriting completed specs or removing historical validation/browser evidence.
|
||||
- Evidence Snapshot detail, Baseline Snapshot detail, Baseline Compare, Restore Preview, Review Publication Resolution, Customer Review Workspace, System Panel branding, and report receipt pages unless a small table/widget inside a target dashboard/inbox is directly touched and documented.
|
||||
- New dashboard redesign, navigation redesign, runtime Product Surface framework, presenter family, enum/status family, component framework, persisted taxonomy, or design-system rewrite.
|
||||
- New Microsoft Graph calls, Graph contract changes, migrations, models, jobs, queues, scheduler changes, env vars, storage changes, or external service dependencies.
|
||||
|
||||
## Acceptance Criteria *(mandatory)*
|
||||
|
||||
- **AC-399-001**: Environment Dashboard default view shows environment state, top attention items, compact summary, and recommended next action without default OperationRun proof/raw evidence/deep-link overload.
|
||||
- **AC-399-002**: Workspace Overview default view shows workspace-level triage and top attention items without long operations/evidence/report tables or raw technical links by default.
|
||||
- **AC-399-003**: Governance Inbox rows/items show work item, state/severity, scope, impact/reason, and next action without default proof-graph navigation.
|
||||
- **AC-399-004**: Findings default table/list shows at most eight visible rows before pagination/show more unless a Product Surface exception is documented before implementation continues, uses product labels, and avoids UUID/fingerprint/detector/source key as primary labels.
|
||||
- **AC-399-005**: Operations Hub shows operation attention and deliberate technical detail paths without making raw OperationRun detail the default product surface.
|
||||
- **AC-399-006**: Every touched hot table respects row, link, action, and technical-column budgets or records a bounded Product Surface exception before code changes continue.
|
||||
- **AC-399-007**: Touched destructive/bulk/high-impact actions are visually separated and confirmation-protected/authorized/audited where mutating.
|
||||
- **AC-399-008**: Tests no longer expect old overloaded dashboards, 25-row hot tables, default OperationRun proof links, or excessive evidence links on touched surfaces.
|
||||
- **AC-399-009**: Implementation introduces no new Product Surface runtime framework, presenter/status enum family, component framework, or persisted taxonomy.
|
||||
- **AC-399-010**: Focused Spec 399 Feature/Filament tests, focused browser smoke, Pint, and diff checks pass or failures are documented as unrelated only when no touched surface failed.
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-399-001**: Each touched primary page has exactly one documented primary user question and one dominant next action/triage path in the implementation report.
|
||||
- **SC-399-002**: Each touched product-facing table either defaults to at most eight visible rows before Show more/pagination/full-table path or documents an approved exception.
|
||||
- **SC-399-003**: Focused browser proof verifies no default-visible OperationRun proof links, raw evidence/source key/detector/payload identifiers, or default-open diagnostics on the touched dashboard/inbox/table surfaces.
|
||||
- **SC-399-004**: Human Product Sanity records visible complexity as decreased or neutral with proof, and no touched surface is judged louder or more ambiguous than before.
|
||||
- **SC-399-005**: No application implementation introduces migrations, new persisted truth, new status families, or new Product Surface framework code for this spec.
|
||||
|
||||
## Risks
|
||||
|
||||
- **Risk 1 - Operators lose access to proof/detail**: mitigate by preserving authorized secondary/detail/audit paths and documenting proof continuity in the implementation report.
|
||||
- **Risk 2 - Tests preserve overloaded defaults**: mitigate by updating tests to the new table/dashboard/inbox contract and forbidding compatibility behavior.
|
||||
- **Risk 3 - Dashboards become too sparse**: mitigate by requiring state, top attention items, compact summary, and next action.
|
||||
- **Risk 4 - Operations Hub classification remains ambiguous**: mitigate by treating the default route as Inbox behavior with technical detail demoted; any Technical Annex exception must be documented before implementation continues.
|
||||
- **Risk 5 - Scope expands into broad redesign**: mitigate by limiting implementation to named surfaces and touched hot tables, with receipt/decision/customer/system surfaces out of scope.
|
||||
- **Risk 6 - Runtime framework creep**: mitigate by explicitly forbidding new Product Surface frameworks, presenter families, enum/status families, component frameworks, and persisted taxonomies.
|
||||
|
||||
## Assumptions
|
||||
|
||||
- The current `/admin` panel remains the operator surface; `/system` and retired `/admin/t` routes are not product targets for this spec.
|
||||
- Existing Specs 327, 328, 330, 346, 352, 391, 397, and 398 provide context and tests/browser fixtures that can be reused or updated, but their historical close-out evidence must not be rewritten.
|
||||
- Existing Filament v5 / Livewire v4 behavior, `TablePaginationProfiles`, action-surface declarations, `BadgeCatalog`, and OperationRun helpers are sufficient for the intended migration.
|
||||
- Implementation may narrow secondary hot tables if touching all listed tables would exceed a bounded implementation loop; every touched table must still obey the contract.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None blocking preparation. During implementation, if a touched table cannot practically meet the eight-row default because of native pagination constraints or route purpose, the implementer must update this spec and plan with a Product Surface exception before continuing.
|
||||
|
||||
## Follow-up Spec Candidates
|
||||
|
||||
- Secondary hot-table follow-through for Evidence Overview, Inventory, Policies, Policy Versions, Required Permissions, Provider Connections, Backup Sets, Restore Runs, or Stored Reports if implementation discovers recurring table overload outside the primary surfaces.
|
||||
- Product Surface strictness/guard expansion only after at least one more runtime surface migration proves false-positive behavior is manageable.
|
||||
- Manual system-panel browser fixture or audit procedure remains separate from this `/admin` product-surface migration.
|
||||
169
specs/399-dashboard-inbox-table-contract/tasks.md
Normal file
169
specs/399-dashboard-inbox-table-contract/tasks.md
Normal file
@ -0,0 +1,169 @@
|
||||
# Tasks: Spec 399 - Dashboard / Inbox / Table Contract Migration v1
|
||||
|
||||
**Input**: Design documents from `/specs/399-dashboard-inbox-table-contract/`
|
||||
**Prerequisites**: `spec.md`, `plan.md`
|
||||
**Tests**: Required. Runtime UI changes must include Pest Feature/Livewire tests and focused Pest Browser smoke.
|
||||
|
||||
**Completion note**: Completed tasks include runtime edits, focused tests/browser proof, docs/report updates, and no-op inspection decisions for repo-verified surfaces where the selected Spec 399 slice did not require a bounded code change. See `implementation-report.md` for evidence and deferred secondary surfaces.
|
||||
|
||||
## Test Governance Checklist
|
||||
|
||||
- [x] T001 Confirm lane assignment in `specs/399-dashboard-inbox-table-contract/implementation-report.md`: Feature/Livewire + Browser are the narrowest sufficient proof for the changed dashboard/inbox/table behavior.
|
||||
- [x] T002 Confirm new or changed tests stay in the smallest honest family in `specs/399-dashboard-inbox-table-contract/implementation-report.md`, with any browser addition named as Spec 399.
|
||||
- [x] T003 Confirm shared helpers, factories, seeds, fixtures, and browser harness changes stay cheap by default in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T004 Confirm planned validation commands in `specs/399-dashboard-inbox-table-contract/implementation-report.md` cover touched surfaces without broad suite cost.
|
||||
- [x] T005 Confirm Product Surface browser proof and Human Product Sanity close-out are planned in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
|
||||
## Phase 1: Discovery And Guardrails
|
||||
|
||||
**Purpose**: Lock exact touched surfaces, reuse paths, and exception boundaries before runtime UI edits.
|
||||
|
||||
- [x] T006 Re-read `specs/399-dashboard-inbox-table-contract/spec.md`, `specs/399-dashboard-inbox-table-contract/plan.md`, and `docs/product/standards/product-surface-contract.md`; record selected implementation slice in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T007 Re-read table/action standards in `docs/product/standards/filament-table-ux.md`, `docs/product/standards/list-surface-review-checklist.md`, `docs/ui/action-surface-contract.md`, `docs/ui/operator-ux-surface-standards.md`, and `docs/filament-guidelines.md`; record applicable shared paths and checklist result in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T008 Inspect Environment Dashboard surfaces in `apps/platform/app/Filament/Pages/EnvironmentDashboard.php`, `apps/platform/app/Filament/Widgets/Dashboard/EnvironmentDashboardOverview.php`, `apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummaryBuilder.php`, and `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-overview.blade.php`.
|
||||
- [x] T009 Inspect Workspace Overview surfaces in `apps/platform/app/Filament/Pages/WorkspaceOverview.php`, `apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php`, and `apps/platform/app/Filament/Widgets/Workspace/`.
|
||||
- [x] T010 Inspect Governance Inbox surfaces in `apps/platform/app/Filament/Pages/Governance/GovernanceInbox.php` and `apps/platform/resources/views/filament/pages/governance/governance-inbox.blade.php`.
|
||||
- [x] T011 Inspect Findings surfaces in `apps/platform/app/Filament/Resources/FindingResource.php`, `apps/platform/app/Filament/Resources/FindingResource/Pages/ListFindings.php`, `apps/platform/app/Filament/Pages/Findings/MyFindingsInbox.php`, and `apps/platform/app/Filament/Pages/Findings/FindingsIntakeQueue.php`.
|
||||
- [x] T012 Inspect Operations Hub surfaces in `apps/platform/app/Filament/Pages/Monitoring/Operations.php`, `apps/platform/resources/views/filament/pages/monitoring/operations.blade.php`, and `apps/platform/app/Filament/Resources/OperationRunResource.php`.
|
||||
- [x] T013 Inspect existing Product Surface/browser context in `specs/327-governance-inbox-decision-first-workbench-productization/`, `specs/328-operations-hub-decision-first-workbench-productization/`, `specs/330-environment-dashboard-baseline-compare-productization/`, `specs/346-governance-inbox-final-operator-workflow/`, `specs/352-environment-dashboard-operator-guidance-consolidation/`, `specs/391-operations-hub-stability-debug-safe-runtime/`, `specs/397-receipt-page-reduction/`, and `specs/398-decision-page-contract-migration/` without rewriting those packages.
|
||||
- [x] T014 Decide exact touched surfaces and explicitly defer untouched secondary hot tables in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T015 If any Product Surface exception is required, update `specs/399-dashboard-inbox-table-contract/spec.md` and `specs/399-dashboard-inbox-table-contract/plan.md` before editing runtime UI files.
|
||||
|
||||
## Phase 2: Tests First - Contract Expectations
|
||||
|
||||
**Purpose**: Encode new dashboard/inbox/table expectations before or alongside implementation.
|
||||
|
||||
- [x] T016 [P] Add or update Environment Dashboard Feature coverage in `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` proving the default view has one attention question, one dominant next action, no default OperationRun proof, and no raw evidence/source-key/detector/payload exposure.
|
||||
- [x] T017 Add or update Workspace Overview Feature coverage in `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` proving the default view prioritizes workspace attention and does not expose long operations/evidence/report tables by default.
|
||||
- [x] T018 [P] Add or update Governance Inbox Feature and Browser coverage in `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` and `apps/platform/tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php` proving visible items show work item, state/severity, scope, impact/reason, and next action while proof links are secondary or collapsed.
|
||||
- [x] T019 [P] Add or update Findings Feature/Livewire coverage in `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` proving product row labels, table cap/product pagination, one row primary action, and hidden technical identifiers.
|
||||
- [x] T020 [P] Add or update Operations Hub Feature coverage in `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` plus affected existing Monitoring tests proving default attention behavior and hidden raw OperationRun diagnostics.
|
||||
- [x] T021 [P] Add or update table/action budget coverage for directly touched hot tables in `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` and affected existing table-standard tests.
|
||||
- [x] T022 Add or update destructive/bulk action assertions in `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` and affected existing table-standard tests proving touched destructive/high-impact actions are grouped, confirmation-protected, and not primary navigation.
|
||||
- [x] T023 [P] Add browser smoke scaffold in `apps/platform/tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php` using existing workspace/environment browser harness patterns.
|
||||
- [x] T024 Update existing tests that encode old overloaded defaults in the narrowest relevant files under `apps/platform/tests/Feature/Filament/`, `apps/platform/tests/Feature/Governance/`, `apps/platform/tests/Feature/Monitoring/`, `apps/platform/tests/Feature/Findings/`, and `apps/platform/tests/Browser/`.
|
||||
|
||||
## Phase 3: User Story 1 - Dashboards Answer One Attention Question (P1)
|
||||
|
||||
**Goal**: Environment Dashboard and Workspace Overview reduce default-visible proof/link/readiness overload and show one dominant next action.
|
||||
|
||||
**Independent Test**: T016, T017, and the dashboard sections of T023 pass independently.
|
||||
|
||||
- [x] T025 [US1] Update Environment Dashboard payload/action hierarchy in `apps/platform/app/Filament/Pages/EnvironmentDashboard.php` so the page exposes only one dominant product next action and secondary actions are grouped/demoted.
|
||||
- [x] T026 [US1] Update Environment Dashboard summary selection in `apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummaryBuilder.php` so repeated readiness/status summaries are reduced to one top-level product truth per concept.
|
||||
- [x] T027 [US1] Update Environment Dashboard widget behavior in `apps/platform/app/Filament/Widgets/Dashboard/EnvironmentDashboardOverview.php` to support the Product Surface budgets without adding new persisted state.
|
||||
- [x] T028 [US1] Update Environment Dashboard default Blade hierarchy in `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-overview.blade.php` to hide/demote OperationRun proof, raw evidence, source keys, detector/fingerprint/payload detail, and excessive secondary links.
|
||||
- [x] T029 [US1] Update Environment Dashboard recent operations/table widget behavior in `apps/platform/app/Filament/Widgets/Dashboard/RecentOperations.php` if implementation discovery confirms it is default-visible and violates Product Surface table/link budgets.
|
||||
- [x] T030 [US1] Update Workspace Overview page hierarchy in `apps/platform/app/Filament/Pages/WorkspaceOverview.php` so one workspace triage path is dominant and technical/proof navigation is secondary.
|
||||
- [x] T031 [US1] Update Workspace Overview builder output in `apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php` so summary metrics stay at four or fewer above the fold and attention items do not duplicate the same blocker truth.
|
||||
- [x] T032 [US1] Update Workspace Overview widgets in `apps/platform/app/Filament/Widgets/Workspace/WorkspaceNeedsAttention.php`, `apps/platform/app/Filament/Widgets/Workspace/WorkspaceSummaryStats.php`, and `apps/platform/app/Filament/Widgets/Workspace/WorkspaceRecentOperations.php` where touched to respect row/link/action budgets.
|
||||
- [x] T033 [US1] Update localization labels touched by dashboard copy in `apps/platform/lang/` only when existing labels expose implementation-first terms as primary product copy.
|
||||
- [x] T034 [US1] Run focused dashboard Feature tests from `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php`.
|
||||
|
||||
## Phase 4: User Story 2 - Inboxes Prioritize Triage Work (P1)
|
||||
|
||||
**Goal**: Governance Inbox and Findings surfaces show actionable triage rows/items rather than proof graphs.
|
||||
|
||||
**Independent Test**: T018, T019, and the inbox sections of T023 pass independently.
|
||||
|
||||
- [x] T035 [US2] Inspect Governance Inbox page payload/action structure in `apps/platform/app/Filament/Pages/Governance/GovernanceInbox.php` and record that no runtime edit was selected because the current lane contract already keeps one primary triage path and secondary/collapsed proof links for this slice.
|
||||
- [x] T036 [US2] Inspect Governance Inbox Blade hierarchy in `apps/platform/resources/views/filament/pages/governance/governance-inbox.blade.php` and cover its existing row/action/link budgets, collapsed diagnostics, and hidden raw technical identifiers through Spec 399 Feature/Browser proof.
|
||||
- [x] T037 [US2] Inspect existing Governance Inbox tests in `apps/platform/tests/Feature/Governance/GovernanceInboxPageTest.php` and `apps/platform/tests/Feature/Governance/Spec346GovernanceInboxOperatorWorkflowTest.php`; no assertion change was required there, and Spec 399 coverage now lives in the focused Feature/Browser files.
|
||||
- [x] T038 [US2] Update FindingResource table configuration in `apps/platform/app/Filament/Resources/FindingResource.php` to prefer product labels, one inspect/triage action, hidden technical columns, and grouped bulk/destructive actions.
|
||||
- [x] T039 [US2] Update Findings list page behavior in `apps/platform/app/Filament/Resources/FindingResource/Pages/ListFindings.php` where needed for default pagination/caps and action hierarchy.
|
||||
- [x] T040 [US2] Update My Findings Inbox in `apps/platform/app/Filament/Pages/Findings/MyFindingsInbox.php` if selected by discovery to ensure inbox rows demote technical proof and cap visible work items.
|
||||
- [x] T041 [US2] Update Findings Intake Queue in `apps/platform/app/Filament/Pages/Findings/FindingsIntakeQueue.php` if selected by discovery to ensure one primary triage action and no raw technical labels by default.
|
||||
- [x] T042 [US2] Update findings-related localization labels in `apps/platform/lang/` only when existing primary copy exposes implementation-first terms.
|
||||
- [x] T043 [US2] Run focused Governance Inbox and Findings Feature tests from `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` plus affected existing Governance/Findings tests.
|
||||
|
||||
## Phase 5: User Story 3 - Hot Tables Obey Budgets (P1)
|
||||
|
||||
**Goal**: Every touched product-facing hot table follows row, link, action, and technical-column budgets.
|
||||
|
||||
**Independent Test**: T021 and T022 pass for every directly touched hot table.
|
||||
|
||||
- [x] T044 [US3] Apply native Filament table caps or product pagination to directly touched tables in `apps/platform/app/Filament/Resources/FindingResource.php`, `apps/platform/app/Filament/Pages/Governance/GovernanceInbox.php`, `apps/platform/app/Filament/Pages/Monitoring/Operations.php`, and any selected dashboard/widget table file.
|
||||
- [x] T045 [US3] Hide or toggle technical columns by default in every touched table file, using `toggleable(isToggledHiddenByDefault: true)` or equivalent host pattern when native Filament table APIs are in use.
|
||||
- [x] T046 [US3] Remove or demote raw UUID, fingerprint, source key, detector, payload, and OperationRun/evidence proof links from primary row labels in every touched table file.
|
||||
- [x] T047 [US3] Ensure every touched table has one primary inspect/open/triage model in its table configuration file and does not render duplicate `View` actions when `recordUrl()` or an equivalent inspect path is primary.
|
||||
- [x] T048 [US3] Group or separate every touched bulk/destructive action using existing ActionGroup/BulkActionGroup patterns in the relevant Filament resource/page file.
|
||||
- [x] T049 [US3] Remove empty `ActionGroup` or `BulkActionGroup` placeholders in touched table files if RBAC/state filtering can make them empty.
|
||||
- [x] T050 [US3] Update table empty states in touched table files so each has domain-specific copy and at most one primary CTA where relevant.
|
||||
- [x] T051 [US3] Run focused hot-table tests from `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` plus affected existing table-standard tests.
|
||||
|
||||
## Phase 6: User Story 4 - Operations Hub Is Not A Raw Run Browser (P2)
|
||||
|
||||
**Goal**: Operations Hub keeps attention-oriented Inbox behavior and demotes raw OperationRun detail from default product hierarchy.
|
||||
|
||||
**Independent Test**: T020 and the Operations Hub sections of T023 pass independently.
|
||||
|
||||
- [x] T052 [US4] Update Operations Hub page payload/action hierarchy in `apps/platform/app/Filament/Pages/Monitoring/Operations.php` so the default view emphasizes operation purpose, state/outcome, impact, environment/scope, and one next action.
|
||||
- [x] T053 [US4] Update Operations Hub Blade hierarchy in `apps/platform/resources/views/filament/pages/monitoring/operations.blade.php` so raw run IDs, raw context, payloads, stack traces, and diagnostics are hidden/collapsed by default.
|
||||
- [x] T054 [US4] Preserve authorized OperationRun detail and related artifact/source links through existing `OperationRunLinks` usage in `apps/platform/app/Filament/Pages/Monitoring/Operations.php`.
|
||||
- [x] T055 [US4] Ensure Operations Hub does not introduce local OperationRun queued toast/link/event/dedupe/notification behavior in `apps/platform/app/Filament/Pages/Monitoring/Operations.php`.
|
||||
- [x] T056 [US4] Update existing Operations tests in `apps/platform/tests/Feature/Monitoring/OperationsHubProductizationTest.php`, `apps/platform/tests/Feature/Monitoring/Spec391OperationsHubStabilityTest.php`, and `apps/platform/tests/Browser/Spec391OperationsHubStabilitySmokeTest.php` where old technical-default expectations conflict with Spec 399.
|
||||
- [x] T057 [US4] Run focused Operations tests from `apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php` plus affected existing Monitoring tests.
|
||||
|
||||
## Phase 7: User Story 5 - Technical Proof Remains Reachable And Safe (P2)
|
||||
|
||||
**Goal**: Technical proof is demoted by default but remains available to authorized users through deliberate paths.
|
||||
|
||||
**Independent Test**: Feature and browser tests prove default demotion plus authorized secondary/detail path continuity.
|
||||
|
||||
- [x] T058 [US5] Verify each demoted Environment Dashboard proof path still has an authorized secondary/detail route or document why no such path existed in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T059 [US5] Verify each demoted Workspace Overview proof path still has an authorized secondary/detail route or document why no such path existed in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T060 [US5] Verify each demoted Governance Inbox source/proof path still has an authorized secondary/detail route or document why no such path existed in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T061 [US5] Verify each demoted Findings technical identifier/proof path still has an authorized detail/audit route or document why no such path existed in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T062 [US5] Verify each demoted Operations Hub technical path still resolves through existing `OperationRunLinks` or authorized detail routes in `apps/platform/app/Filament/Pages/Monitoring/Operations.php`.
|
||||
- [x] T063 [US5] Confirm existing RBAC/authorization assertions remain in the affected Feature tests under `apps/platform/tests/Feature/` for touched technical/audit paths; Spec 399 added no new authorization path.
|
||||
|
||||
## Phase 8: Browser Smoke, Coverage Artifacts, And Close-Out
|
||||
|
||||
**Purpose**: Prove rendered behavior, update required coverage artifacts, and record implementation evidence.
|
||||
|
||||
- [x] T064 Update `docs/ui-ux-enterprise-audit/route-inventory.md` for every rendered route whose page archetype, Product Surface classification, or default UI changed.
|
||||
- [x] T065 Update `docs/ui-ux-enterprise-audit/design-coverage-matrix.md` for every rendered route whose Product Surface migration was implemented.
|
||||
- [x] T066 Update a page report under `docs/ui-ux-enterprise-audit/page-reports/` only if implementation changes a route archetype, expands default content, or discovers the existing page report is materially inaccurate.
|
||||
- [x] T067 Complete browser smoke in `apps/platform/tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php` for Environment Dashboard, Workspace Overview, Governance Inbox, Findings, Operations Hub, and at least one touched hot table, including dark mode correctness, accessibility affordances, and Filament-native/shared-primitive semantics for touched custom Blade surfaces.
|
||||
- [x] T068 Save any intentional browser screenshots under `specs/399-dashboard-inbox-table-contract/artifacts/screenshots/` and confirm no accidental screenshot artifacts remain elsewhere.
|
||||
- [x] T069 Complete Human Product Sanity results in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T070 Complete Product Surface implementation-report fields in `specs/399-dashboard-inbox-table-contract/implementation-report.md`: files changed, target surfaces, archetype per surface, primary user question, table caps, list-surface checklist result, deep links demoted, action hierarchy, destructive/bulk separation, dark mode/accessibility/Filament-native proof, tests, browser proof, human sanity, no-legacy, no point fixes, no runtime framework, visible complexity outcome, deployment impact, and no completed-spec rewrite assertion.
|
||||
- [x] T071 Run `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec399`.
|
||||
- [x] T072 Run `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec399DashboardInboxTableContractMigrationSmokeTest.php`.
|
||||
- [x] T073 Run affected existing Feature/Browser tests listed in `specs/399-dashboard-inbox-table-contract/implementation-report.md`.
|
||||
- [x] T074 Run `cd apps/platform && ./vendor/bin/sail pint --dirty`.
|
||||
- [x] T075 Run `git diff --check`.
|
||||
- [x] T076 Record any unrelated failures in `specs/399-dashboard-inbox-table-contract/implementation-report.md` with command, failure count, why unrelated, and confirmation no touched dashboard/inbox/table surface failed.
|
||||
- [x] T077 Confirm final implementation response states Livewire v4 compliance, provider registration location, global search posture, destructive/high-impact action handling, asset strategy, tests/browser coverage, deployment impact, and no application secrets/raw tenant data in screenshots.
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
- [x] T078 Complete Phase 1 before any runtime UI edit in `apps/platform/app/`, `apps/platform/resources/`, or `apps/platform/tests/`.
|
||||
- [x] T079 Complete Phase 2 tests before or alongside corresponding implementation tasks in Phases 3 through 7.
|
||||
- [x] T080 Complete dashboard tasks T025-T034 before final browser smoke assertions for Environment Dashboard and Workspace Overview in T067.
|
||||
- [x] T081 Complete inbox/tasks T035-T043 before final browser smoke assertions for Governance Inbox and Findings in T067.
|
||||
- [x] T082 Complete table tasks T044-T051 before final browser smoke assertions for touched hot tables in T067.
|
||||
- [x] T083 Complete Operations tasks T052-T057 before final browser smoke assertions for Operations Hub in T067.
|
||||
- [x] T084 Complete proof continuity tasks T058-T063 before implementation-report close-out in T070.
|
||||
|
||||
## Parallel Execution Notes
|
||||
|
||||
- [x] T085 Tests T016-T023 can be drafted in parallel after Phase 1 target lock only where they touch different files; T016/T017 and T021/T022 must coordinate because each pair shares one test file.
|
||||
- [x] T086 Dashboard implementation T025-T034 and inbox implementation T035-T043 can proceed in parallel only if they do not edit shared localization files in `apps/platform/lang/`.
|
||||
- [x] T087 Table contract work T044-T051 must coordinate with surface-specific work to avoid conflicting edits in the same Filament page/resource files.
|
||||
- [x] T088 Browser smoke T067 must wait for all selected runtime surfaces and fixtures to be stable.
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
- [x] T089 MVP first: complete US1 dashboards plus the shared table budget tasks that those dashboards touch, then run focused dashboard Feature and browser proof.
|
||||
- [x] T090 Incremental delivery: add US2 inbox/findings, US3 hot tables, US4 Operations Hub, and US5 proof continuity in order, validating each story independently before moving on.
|
||||
- [x] T091 Stop and update `specs/399-dashboard-inbox-table-contract/spec.md` and `specs/399-dashboard-inbox-table-contract/plan.md` if implementation discovers the selected slice needs new persistence, new status families, new Product Surface runtime infrastructure, new Graph behavior, or a Product Surface exception.
|
||||
|
||||
## Non-Goals Checklist
|
||||
|
||||
- [x] T092 Do not modify completed Specs 327, 328, 330, 352, 370, 371, 391, 395, 397, or 398 except as read-only context.
|
||||
- [x] T093 Do not create migrations, models, jobs, commands, provider contracts, Graph endpoints, queues, scheduler changes, storage changes, or env vars for Spec 399.
|
||||
- [x] T094 Do not create a Product Surface runtime framework, presenter family, enum/status family, component framework, persisted taxonomy, or broad design system.
|
||||
- [x] T095 Do not preserve old overloaded dashboard/inbox/table behavior through compatibility flags, old layouts, hidden routes, old labels, fallback readers, or legacy fixtures.
|
||||
- [x] T096 Do not touch receipt pages, decision pages, Customer Review Workspace, System Panel branding, Baseline Compare, Restore Preview, or Review Publication Resolution unless the spec/plan are updated with explicit scope approval.
|
||||
- [x] T097 Do not mark Spec 399 complete unless focused Feature tests, focused browser smoke, Human Product Sanity, Product Surface close-out, Pint, and diff checks are recorded.
|
||||
Loading…
Reference in New Issue
Block a user