## Summary - productize the operations hub decision-first workbench and related monitoring page surfaces - add the operations workbench stats widget plus tenantless run viewer and admin scope updates - extend monitoring, ops UX, and browser coverage for the new workbench behavior - add Spec 328 artifacts under `specs/328-operations-hub-decision-first-workbench-productization` ## Testing - not run as part of this handoff Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #389
106 lines
14 KiB
Markdown
106 lines
14 KiB
Markdown
# Spec 328 Repo Truth Map
|
|
|
|
Status: implemented / validated
|
|
Created: 2026-05-18
|
|
Purpose: classify each Operations Hub decision-first workbench element before runtime implementation. This map is based on repository inspection only; implementation must update it before runtime changes if new source gaps appear.
|
|
|
|
## Classification Legend
|
|
|
|
- `repo-verified`: exact runtime source exists and was inspected.
|
|
- `foundation-real`: backend model/service/policy exists, but exact page binding still needs implementation verification.
|
|
- `derived from existing model`: display value can be derived from existing persisted/domain truth.
|
|
- `empty state / unavailable`: no safe source/action exists for v1; show explicit unavailable state or omit.
|
|
- `deferred future capability`: outside Spec 328 and must not be shown as live runtime truth.
|
|
|
|
## Required Data Areas
|
|
|
|
| Data area | Repo source | Preparation finding |
|
|
|---|---|---|
|
|
| Operations route | `apps/platform/routes/web.php`, route `admin.operations.index` | repo-real path is `/admin/workspaces/{workspace}/operations` |
|
|
| Operations page | `Operations` Filament page and `operations.blade.php` | repo-real current layout is decision-first workbench with secondary history table |
|
|
| OperationRun table | `OperationRunResource::table()` | repo-real status/outcome/type/timing table with filters, row URL, empty state |
|
|
| OperationRun detail | `TenantlessOperationRunViewer`, `OperationRunResource::infolist()` | repo-real detail/proof/diagnostic destination |
|
|
| OperationRun statuses | `OperationRunStatus` | repo-real `queued`, `running`, `completed` |
|
|
| OperationRun outcomes | `OperationRunOutcome` | repo-real `pending`, `succeeded`, `partially_succeeded`, `blocked`, `failed`; `cancelled` is reserved |
|
|
| OperationRun problem classes | `OperationRun::problemClass()`, scopes `activeStaleAttention()`, `terminalFollowUp()`, `dashboardNeedsFollowUp()` | repo-real for attention grouping without new priority engine |
|
|
| Summary counts | `summary_counts`, `OperationSummaryKeys`, `SummaryCountsNormalizer` | repo-real numeric keys and normalized rendering |
|
|
| Progress | `OperationRunProgressContract` | repo-real active-only progress semantics; terminal runs return `none` |
|
|
| Operation labels | `OperationCatalog::label()` | repo-real labels for canonical/legacy operation types |
|
|
| Environment relationship | `OperationRun::tenant()` relation to `ManagedEnvironment` | repo-real affected environment where present and accessible |
|
|
| Artifact/evidence links | `OperationRunLinks::related()`, `ArtifactTruthPresenter`, related resources | foundation-real/repo-real depending on operation type and linked artifact |
|
|
| Diagnostics | run detail technical sections, support diagnostics action, `failure_summary`, `context` | repo-real but default index must not expose raw data |
|
|
| RBAC | `OperationRunPolicy`, `OperationRunCapabilityResolver`, source policies/capabilities | repo-real membership, environment entitlement, capability checks |
|
|
| Workspace / Environment filter state | `WorkspaceContext`, `WorkspaceHubEnvironmentFilter`, `WorkspaceHubFilterStateResetter`, `CanonicalAdminEnvironmentFilterState`, filter chip partial | repo-real canonical `environment_id`, clear filter, alias rejection, cross-workspace guard |
|
|
|
|
## UI Element Map
|
|
|
|
| UI element | Source model/service/page | Status source | Authorization/capability | Workspace/Environment scope | OperationRun/evidence/artifact/audit link | Fallback/empty state | Classification |
|
|
|---|---|---|---|---|---|---|---|
|
|
| Operations Hub route | `admin.operations.index`, `OperationRunLinks::index()` | route + helper | workspace middleware and page access | current workspace route param | none | workspace chooser / 404 per existing middleware | repo-verified |
|
|
| Operations Hub title | `Operations` page/view | static copy to update | page access | workspace | none | static title | repo-verified |
|
|
| Workspace scope label | `OperateHubShell`, `WorkspaceContext` | current workspace/session | workspace membership | workspace shell | none | omit/404 if unavailable | repo-verified |
|
|
| Environment filter chip | `environmentFilterChip()`, shared chip partial | `WorkspaceHubEnvironmentFilter::fromRequest()` and table state | actor must access environment | `?environment_id={id}` only | none | no chip on clean URL | repo-verified |
|
|
| Clear filter action | `cleanWorkspaceHubUrl()`, shared resetter | generated clean route | page access | removes canonical filter/table state | none | omit when unfiltered | repo-verified |
|
|
| Legacy alias rejection | `WorkspaceHubFilterStateResetter`, navigation tests | forbidden query/session keys | page/source access | aliases do not set filter | none | workspace-wide view or safe 404 | repo-verified |
|
|
| Cross-workspace environment guard | `WorkspaceHubEnvironmentFilter::fromRequest()` | environment scoped by workspace and entitlement | workspace and environment entitlement | current workspace only | none | `abort(404)` / safe no-access | repo-verified |
|
|
| Main workbench question | `Operations::decisionWorkbench()` and `operations.blade.php` | static stable copy | page access | current scope | none | visible with no-attention state | repo-verified |
|
|
| Highest-priority operation | `Operations::selectedWorkbenchOperation()`, `OperationRun` problem class, outcome, status, freshness, timestamps | derived ordering from existing status/outcome/problem class | existing scoped Operations page query and OperationRun visibility | current workspace/filter | canonical detail link | `No operations need attention` | derived from existing model |
|
|
| Operation title/type | `OperationCatalog::label($run->type)` | type field | run visibility | current workspace/filter | detail link | fallback raw-safe type label | repo-verified |
|
|
| Outcome/status | `OperationRun.status`, `outcome`, badge renderer | status/outcome enums | run visibility | current workspace/filter | detail link | `Outcome unavailable` only if missing | repo-verified |
|
|
| Reason | problem class, lifecycle/freshness, outcome, `OperationUxPresenter`, `ReasonPresenter`, `failure_summary` summary where safe | derived from run truth | run/detail/source capabilities | current scope | detail link | `Reason unavailable` | derived from existing model |
|
|
| Impact | outcome, problem class, artifact truth, related artifact/review/restore context | derived from existing run/artifact truth | run/source capabilities | current scope | related links if authorized | `Impact unavailable` | derived from existing model |
|
|
| Environment | `OperationRun::tenant()` / `ManagedEnvironment` | managed environment relationship | entitlement via `OperationRunPolicy` / scope resolver | workspace and environment | related environment/resource links if existing | `Workspace-level operation` or unavailable | repo-verified |
|
|
| Timing | `created_at`, `started_at`, `completed_at`, `RunDurationInsights` | timestamps | run visibility | current scope | detail link | `Timing unavailable` | repo-verified |
|
|
| Proof/artifact state | `OperationRunLinks::related()`, `ArtifactTruthPresenter`, related resources | related route presence, artifact truth envelope | source policies/capabilities | current scope | artifact/evidence/review/backup/restore links | `Proof unavailable` or omit | foundation-real |
|
|
| Operation detail proof | `OperationRunLinks::tenantlessView()` | run id / route | `OperationRunPolicy` | current workspace/filter | canonical run detail | unavailable only if unauthorized | repo-verified |
|
|
| Progress state | `OperationRunProgressContract::forRun()` | summary counts/context/status | run visibility | current scope | detail link | no progress for terminal or unsupported | repo-verified |
|
|
| Determinate progress | `summary_counts.processed`, `summary_counts.total` | numeric trustworthy counts | run visibility | current scope | detail link | indeterminate/activity/unavailable | repo-verified |
|
|
| Terminal outcome guidance | `OperationRunResource::surfaceGuidance()`, `resolvePrimaryNextStep()`, `OperationUxPresenter` | status/outcome/problem class | run visibility | current scope | detail link/source links | generic review operation | foundation-real |
|
|
| Primary next action | `OperationRunLinks::tenantlessView()`, existing detail/source actions | route/action availability | run/source capability | current scope | operation detail link | unavailable when no selected operation | repo-verified for open operation; stronger proof links remain deferred to detail/source surfaces |
|
|
| Summary card: needs attention | `dashboardNeedsFollowUp()` / problem class scopes | stale active + terminal follow-up | scoped query | current workspace/filter | operations tab/deep link | 0 count with careful copy | repo-verified |
|
|
| Summary card: active operations | `status in queued/running` | status field | scoped query | current workspace/filter | active tab link | 0 count | repo-verified |
|
|
| Summary card: failed/blocked | completed failed/blocked outcomes | outcome field | scoped query | current workspace/filter | failed/follow-up tab link | 0 count | repo-verified |
|
|
| Summary card: follow-up required | terminal follow-up/problem class | problem class/outcome/reconciliation | scoped query | current workspace/filter | follow-up tab link | 0 count | repo-verified |
|
|
| Summary card: completed recently | completed_at within window | timestamp/outcome | scoped query | current workspace/filter | table filter/tab | 0 count | repo-verified |
|
|
| Summary card: artifact available | related artifact/evidence/link presence | related route / artifact truth | source capabilities | current workspace/filter | artifact/evidence links | unavailable if no safe aggregate | foundation-real |
|
|
| Right operation/proof panel | `operations.blade.php` over selected run payload | selected/highest run payload | run/source capabilities | current scope | operation detail link | no-attention/empty panel | repo-verified |
|
|
| Operations table/history | `OperationRunResource::table()` | table query, filters, row URL | run visibility | workspace + environment scoping | canonical detail route | existing `No operations found` | repo-verified |
|
|
| Tabs / problemClass links | `activeTab`, `problemClass`, `tabUrl()` | query/livewire state | page access | current scope | active/stale/follow-up/succeeded/partial/failed views | all tab default | repo-verified |
|
|
| Diagnostics disclosure | run detail technical sections, support diagnostics action | raw context/failure summary/support bundle | `SUPPORT_DIAGNOSTICS_VIEW` where action exposed | current scope | detail/support diagnostics only | collapsed/hidden | foundation-real |
|
|
| Raw provider payloads | raw Graph/provider payloads | not safe default | support-only future | N/A | N/A | never default-visible | deferred future capability |
|
|
| Retry/cancel/rerun action | existing detail/source actions only if present | action availability | source capability and confirmation | source scope | existing action owner | hidden/unavailable | foundation-real / deferred if unsupported |
|
|
| Platform-context tenant copy guard | runtime copy/tests | string assertions | N/A | page copy | N/A | use Workspace/Environment | repo-verified need; implementation test required |
|
|
|
|
## Required Runtime Element Decisions
|
|
|
|
| Element | v1 decision |
|
|
|---|---|
|
|
| Top summary-card rendering | native Filament `StatsOverviewWidget` / `Stat`; no custom Blade/Tailwind card component or explicit accent-bar system |
|
|
| New persisted operations workbench item | deferred future capability; do not build |
|
|
| New priority engine | deferred future capability; derive local ordering from existing status/outcome/problem class |
|
|
| New OperationRun status/outcome | deferred future capability; do not add |
|
|
| New summary-count keys | deferred future capability; do not add |
|
|
| AI operation summary | deferred future capability; do not show |
|
|
| Owner/due for operation | unavailable unless source operation context already proves it |
|
|
| Artifact/evidence where absent | explicit unavailable/missing state; do not invent |
|
|
| Green success state | allowed only for exact execution completion copy; never environment/governance health |
|
|
| Diagnostics | collapsed/hidden by default and capability-aware if exposed |
|
|
| Dangerous/mutating actions | do not add unless spec/plan updated first |
|
|
| Legacy query aliases | rejected/neutralized; do not support |
|
|
|
|
## Implementation Update Rule
|
|
|
|
If implementation discovers that a planned UI element has no safe source, no authorization path, or would require new persisted truth, the element must become `empty state / unavailable` or `deferred future capability`. Do not create backend foundation inside Spec 328 without updating `spec.md`, `plan.md`, and this map first.
|
|
|
|
## Implementation Close-Out
|
|
|
|
- Implemented the decision-first workbench on the existing `/admin/workspaces/{workspace}/operations` page.
|
|
- Selected-operation priority is derived locally from existing `OperationRun` status, outcome, problem class, timestamps, and scoped queries; no persisted priority engine was added.
|
|
- Determinate progress is delegated to `OperationRunProgressContract` and remains hidden for terminal outcomes.
|
|
- Primary next action is `OperationRunLinks::tenantlessView()` only; artifact/evidence/source-specific actions remain on existing detail/source surfaces.
|
|
- Summary cards are compact execution/attention signals backed by scoped OperationRun counts; they now render through the narrow native `OperationsWorkbenchStats` Filament `StatsOverviewWidget` using `Stat::make(...)`, descriptions, description icons, semantic colors, and disabled polling. No fake trends, sparklines, chart placeholders, custom Blade/Tailwind stat-card component, explicit custom accent bars, generic total-operation KPI, or average-duration KPI is used.
|
|
- `OperationsKpiHeader` remains available as existing widget code, but the Operations page no longer renders it above the workbench because the first viewport is owned by the decision-first summary cards.
|
|
- Diagnostics stay collapsed by default and raw provider/debug payloads are not default-visible.
|
|
- Clean workspace entry remains workspace-wide; `environment_id` remains the only accepted visible filter key.
|
|
- UI coverage registry files were not changed because the route and archetype remain the existing UI-003 Operations strategic surface; screenshots were stored under `artifacts/screenshots/`.
|