## 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
14 KiB
14 KiB
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}/operationspage. - Selected-operation priority is derived locally from existing
OperationRunstatus, outcome, problem class, timestamps, and scoped queries; no persisted priority engine was added. - Determinate progress is delegated to
OperationRunProgressContractand 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
OperationsWorkbenchStatsFilamentStatsOverviewWidgetusingStat::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. OperationsKpiHeaderremains 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_idremains 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/.