TenantAtlas/specs/328-operations-hub-decision-first-workbench-productization/plan.md
ahmido 815262399a feat: productize operations hub decision-first workbench (#389)
## 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
2026-05-19 00:49:13 +00:00

22 KiB

Implementation Plan: Spec 328 - Operations Hub Decision-First Workbench Productization

Branch: 328-operations-hub-decision-first-workbench-productization | Date: 2026-05-18 | Spec: specs/328-operations-hub-decision-first-workbench-productization/spec.md
Input: User-provided Spec 328 and repo inspection.

Summary

Productize the existing workspace-scoped Operations Hub into a decision-first OperationRun workbench. The implementation must keep the current route and OperationRun truth, introduce no backend foundation, and make the first viewport answer:

Which operation needs attention now?

The workbench will elevate the highest-priority operation, outcome, reason, impact, affected environment, trustworthy progress/proof state, and a single next action, while keeping the existing OperationRun table as secondary context and diagnostics collapsed.

Technical Context

Language/Version: PHP 8.4.15, Laravel 12.52.0.
Primary Dependencies: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, Tailwind CSS 4.2.2.
Storage: PostgreSQL; no schema change expected.
Testing: Pest 4 Feature/Livewire/Browser tests.
Validation Lanes: confidence and browser; targeted navigation guard tests.
Target Platform: Laravel Sail locally; Dokploy/container deployment posture unchanged.
Project Type: Laravel monolith under apps/platform.
Performance Goals: DB-only page render; no Graph calls during render; no extra heavy query family beyond existing operations table/detail queries unless bounded and eager-loaded.
Constraints: No new persisted truth, migration, package, queue/scheduler/storage/env change, deployment asset, compatibility route, or legacy alias support.
Scale/Scope: One existing Filament page, its Blade view, existing OperationRun table/resource helpers, feature tests, browser smoke, and spec artifacts.

UI / Surface Guardrail Plan

  • Guardrail scope: changed existing operator-facing strategic surface.
  • Affected routes/pages/actions/states/navigation/panel/provider surfaces:
    • /admin/workspaces/{workspace}/operations
    • /admin/workspaces/{workspace}/operations/{run} only as linked canonical detail context
    • apps/platform/app/Filament/Pages/Monitoring/Operations.php
    • apps/platform/resources/views/filament/pages/monitoring/operations.blade.php
    • apps/platform/app/Filament/Resources/OperationRunResource.php
    • apps/platform/app/Filament/Widgets/Operations/OperationsKpiHeader.php only if summary card/KPI wording must be adjusted
  • No-impact class, if applicable: N/A.
  • Native vs custom classification summary: Native Filament page/table plus existing Blade composition; no new UI framework.
  • Shared-family relevance: status messaging, OperationRun links, progress contract, proof/artifact links, workspace/environment filter chip, diagnostics disclosure.
  • State layers in scope: page payload, URL query (environment_id, activeTab, problemClass), table filters/session state, highest-priority operation selection, diagnostics disclosure.
  • Audience modes in scope: operator-MSP, manager, support reviewer, auditor.
  • Decision/diagnostic/raw hierarchy plan: decision-first, proof/artifact second, diagnostics/support raw third.
  • Raw/support gating plan: collapsed by default and capability-gated where existing capabilities support access.
  • One-primary-action / duplicate-truth control: selected/highest-priority operation owns one primary next action; table rows and related links remain secondary.
  • Handling modes by drift class or surface: review-mandatory for UI-003 strategic surface; document-in-feature for any UI coverage registry no-change decision.
  • Repository-signal treatment: Spec 325 target image is visual direction only; runtime claims must be repo-verified or unavailable.

Constitution Check

  • Inventory-first, snapshots-second: N/A, no Graph, inventory, snapshot, backup, or restore data model change.
  • Read/write separation by default: Page remains read-first. Any unexpected mutation requires spec/plan update, confirmation, authorization, audit, notification, and tests.
  • Single Contract Path to Graph: No Graph calls may be added.
  • Deterministic Capabilities: Reuse existing OperationRunPolicy, OperationRunCapabilityResolver, source policies, and capability resolvers.
  • Proportionality / anti-bloat: No new source of truth, persisted entity, enum/status family, public abstraction, priority engine, or cross-domain UI framework.
  • Workspace isolation: Clean workspace URL stays workspace-wide; environment_id is resolved through current workspace and actor entitlement.
  • Tenant/environment language: Runtime copy must avoid tenant as platform context; provider-specific tenant wording only where explicitly provider-bound.
  • OperationRun UX: Presentation/link semantics only. No operation start, queueing, lifecycle transition, notification, or summary-count writer changes.
  • Progress contract: OperationRunProgressContract remains authoritative. Terminal runs show outcome guidance, not progress.
  • UI-COV-001: Existing strategic surface UI-003 changes; active spec package carries repo-truth map, tests, and browser screenshots. Implementation close-out decides whether route inventory/coverage matrix updates are needed.
  • TEST-GOV-001: Targeted Feature and Browser tests are explicit; no broad heavy-governance lane unless implementation reveals structural risk.

Current Repo Truth Summary

Existing verified surfaces:

  • Operations is a Filament Page rendered by admin.operations.index.
  • admin.operations.index is /admin/workspaces/{workspace}/operations.
  • The view currently renders Monitoring landing, scope/return/reset cards, tabs, lifecycle warning, and the OperationRun table.
  • OperationRunResource::table() owns columns, row detail URL, filters, empty state, status/outcome badges, and no row/bulk actions.
  • OperationRun owns status, outcome, problem classes, freshness/lifecycle helpers, workspace and managed-environment scope.
  • OperationRunProgressContract already separates active counted/activity/phased/composite/none progress and returns none for terminal runs.
  • TenantlessOperationRunViewer and OperationRunResource::infolist() already provide richer run detail, related links, proof/artifact sections, support diagnostics, and technical sections.
  • OperationRunLinks provides canonical index/detail URLs and related resource links.
  • WorkspaceHubEnvironmentFilter::fromRequest() accepts canonical environment_id, scopes to current workspace, and rejects inaccessible/cross-workspace IDs.
  • Existing tests cover canonical operations URLs, workspace hub clean entry, environment filter behavior, detail access, DB-only rendering, and OperationRun authorization.

Known current productization gap:

  • The page is still monitoring/table-first. It does not yet consistently promote an attention-needed operation with outcome, reason, impact, environment, progress/proof state, and one primary next action ahead of the table.

Existing Repository Surfaces Likely Affected

Runtime files, only during later implementation:

  • apps/platform/app/Filament/Pages/Monitoring/Operations.php
  • apps/platform/resources/views/filament/pages/monitoring/operations.blade.php
  • apps/platform/app/Filament/Resources/OperationRunResource.php
  • apps/platform/app/Filament/Widgets/Operations/OperationsKpiHeader.php remains existing widget code, but it must not render before the Spec 328 workbench when the decision-first summary cards own the first viewport.
  • apps/platform/resources/lang/en/* and apps/platform/resources/lang/de/* only if current project pattern requires localized strings for new stable copy.

Tests, only during later implementation:

  • apps/platform/tests/Feature/Monitoring/MonitoringOperationsTest.php
  • apps/platform/tests/Feature/Monitoring/OperationsWorkspaceHubContractTest.php
  • apps/platform/tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
  • apps/platform/tests/Feature/Monitoring/OperationsHeaderHierarchyTest.php
  • apps/platform/tests/Feature/Monitoring/OperationsTenantScopeTest.php
  • apps/platform/tests/Feature/Monitoring/OperationLifecycleFreshnessPresentationTest.php
  • apps/platform/tests/Feature/Operations/TenantlessOperationRunViewerTest.php
  • apps/platform/tests/Feature/Operations/OperationRunBlockedExecutionPresentationTest.php
  • apps/platform/tests/Unit/Support/OpsUx/OperationRunProgressContractTest.php
  • apps/platform/tests/Feature/Navigation/WorkspaceHubEnvironmentFilterContractTest.php
  • apps/platform/tests/Feature/Navigation/WorkspaceHubClearFilterContractTest.php
  • apps/platform/tests/Browser/Spec328OperationsHubProductizationSmokeTest.php

Spec/UI artifacts:

  • specs/328-operations-hub-decision-first-workbench-productization/repo-truth-map.md
  • screenshot artifacts under specs/328-operations-hub-decision-first-workbench-productization/artifacts/screenshots/
  • optional UI coverage registry updates only if implementation materially changes route/archetype/coverage state.

Domain / Model Implications

  • No new model, table, migration, enum, status family, source of truth, or persisted display state.
  • Workbench item state must derive from existing OperationRun truth:
    • status: queued, running, completed.
    • outcome: pending, succeeded, partially_succeeded, blocked, failed, reserved cancelled.
    • problemClass(): active stale attention, terminal follow-up, none.
    • freshnessState() and lifecycle reconciliation payload.
    • summary_counts through OperationRunProgressContract and SummaryCountsNormalizer.
    • OperationCatalog::label() for operation type labels.
    • managed_environment_id / tenant relation for affected environment.
    • started_at, completed_at, created_at for timing.
    • context, failure_summary, and related models only behind safe proof/diagnostic paths.
  • If exact reason, impact, artifact, evidence, or next action is missing, render explicit unavailable/missing state.

UI / Filament Implications

  • Filament v5 and Livewire v4.0+ compliance must be preserved.
  • Panel providers remain in apps/platform/bootstrap/providers.php; no panel provider changes expected.
  • No globally searchable resource is added or changed. OperationRunResource remains protected static bool $isGloballySearchable = false.
  • The layout should use Filament sections/cards/badges/buttons and Tailwind utility classes consistent with existing pages; no heavy one-off CSS.
  • Header must stay short:
    • Operations Hub
    • workspace label
    • scope label: workspace-wide or filtered environment
    • visible filter chip and clear action when filtered
    • subtitle explaining execution truth and follow-up
  • Main workbench must render before the operations table.
  • Summary cards should be compact and action-relevant.
  • Follow-up summary-card alignment: the four workbench summary cards should use native Filament StatsOverviewWidget / Stat rendering while remaining execution/attention signals. Use title, large value, concise subline, optional description/status icon, and semantic Stat::color(...). Do not reintroduce custom Blade/Tailwind stat-card markup, explicit custom accent bars, generic Total Operations / Avg Duration cards, fake trends, fake sparklines, decorative charts, or health claims.
  • Card emphasis should reflect execution risk: Needs attention strongest when actionable, Active operations neutral when zero, Failed or blocked danger/warning, and Completed recently muted success/secondary.
  • Right-side detail/proof panel should be desktop aside and mobile stack.
  • Diagnostics must be collapsed by default.

Livewire / Page State Implications

  • Existing internal methods/properties may keep legacy names only as implementation detail; runtime URL/filter language must be environment_id and Environment.
  • Existing activeTab and problemClass query filters can remain if they do not conflict with environment_id contract.
  • Highest-priority operation selection should be deterministic on page load. If interactive selection is implemented, it must not introduce persisted state or break reload/back/forward behavior.
  • Clear filter must remove environment_id and any environment-like table/session filter state through existing helpers.

OperationRun / Monitoring Implications

  • No new OperationRun creation or lifecycle transition.
  • No queued/running/terminal DB notification changes.
  • No new summary-count writer, progress key, operation type, status, or outcome.
  • Any operation proof link must use existing OperationRunLinks, OperationRunResource, related routes, and authorization.
  • Raw OperationRun.context, failure_summary, stack traces, and payload-like data must not be default-visible.

RBAC / Policy Implications

Reuse existing authorization:

  • Workspace page access through current workspace membership checks and WorkspaceCapabilityResolver::isMember().
  • Environment access through ManagedEnvironmentAccessScopeResolver and current accessible environments.
  • Run visibility through OperationRunPolicy.
  • Run capability mapping through OperationRunCapabilityResolver.
  • Evidence and artifacts through existing source policies/capabilities where links are shown.
  • Support diagnostics through Capabilities::SUPPORT_DIAGNOSTICS_VIEW where diagnostics are exposed.
  • Existing detail actions such as support diagnostics, support request, resume capture, retry/resume, or related links remain owned by the detail/source surfaces.

No new permission semantics should be added unless implementation proves existing capabilities cannot express the action and spec/plan are updated first.

Audit / Evidence / Disclosure Implications

  • No new audit event is required for read-only page rendering unless current page-open audit conventions are extended repo-wide.
  • Evidence/proof should appear as state:
    • operation record available
    • artifact link available
    • evidence linked
    • proof unavailable
    • diagnostics hidden
  • Do not show raw provider payloads, debug metadata, internal exception traces, provider secrets, raw OperationRun payloads, or stack traces by default.
  • If diagnostics disclosure is present, it must be collapsed and capability-aware.

Data / Migration Implications

Expected outcome:

  • No migrations.
  • No seeders.
  • No data backfills.
  • No packages.
  • No env vars.
  • No queues/scheduler/storage changes.
  • No deployment asset changes.
  • No backwards compatibility layer.
  • No legacy tenant query alias support.

If implementation discovers an actual schema need, stop and update spec/plan/tasks/repo-truth-map first. Default decision remains no migration.

Localization / Copy Implications

  • Runtime copy must be concise and operator-safe.
  • Avoid platform-context tenant wording. Use Workspace and Environment for shell/filter/product context.
  • Provider-bound tenant wording may remain only when describing an external Microsoft/Entra tenant identifier or provider payload outside the default decision view.
  • Add EN/DE localization only if the surrounding files already route stable page copy through language files; otherwise keep localized scope as implementation-local and document the decision.

Implementation Phases

Phase 1 - Repo Truth And Current UI Audit

  • Re-read this spec, plan, tasks, and repo-truth-map.md.
  • Inspect current Operations, Blade view, OperationRunResource, TenantlessOperationRunViewer, progress contract, links, policies, and tests.
  • Update repo-truth-map.md before runtime changes if implementation discovers new source truth or gaps.
  • Confirm no migration/package/env/queue/storage/deployment asset need.

Phase 2 - Tests First

  • Add tests for repo truth map existence.
  • Add Feature/Livewire/HTTP tests for decision-first workbench, non-empty attention state, empty/no-attention state, right proof panel, table secondary context, diagnostics hidden, progress/terminal semantics, RBAC action visibility, environment filter, legacy aliases, cross-workspace guard, and tenant-copy guard.

Phase 3 - Layout Productization

  • Refactor the existing page into:
    • header/scope
    • main operations workbench
    • compact execution summary cards
    • right operation/proof panel
    • operations queue/history table
    • collapsed diagnostics disclosure
  • Keep existing tabs/table filters and canonical row links.

Phase 4 - Data Binding

  • Bind workbench and panel to repo-verified sources.
  • Render unavailable states for missing reason, impact, proof, artifact, evidence, or environment data.
  • Do not create synthetic success, health, artifact, or governance claims.

Phase 5 - Progress / Outcome Semantics

  • Use existing progress contract semantics.
  • Show determinate progress only when active counted progress is trustworthy.
  • Show activity/status only for active uncounted runs.
  • Show outcome guidance for terminal failed/blocked/partial/succeeded runs.
  • Do not show terminal progress bars.

Phase 6 - Action Hierarchy And RBAC

  • Show one primary next action for the selected/highest-priority operation.
  • Link only to existing, authorized operation/detail/artifact/evidence/source routes/actions.
  • Keep rare/debug/source actions secondary.
  • Do not introduce destructive actions.

Phase 7 - Scope / Filter Integration

  • Preserve clean workspace-wide entry.
  • Preserve ?environment_id= filter, visible chip, clear filter, reload/back/forward behavior.
  • Preserve legacy alias rejection and cross-workspace guard.

Phase 8 - Browser Smoke And Screenshots

  • Add targeted Browser smoke for clean, filtered, clear/reload, non-empty workbench, empty/no-attention state, right detail/proof panel, diagnostics hidden, table secondary, light mode if feasible, and no platform-context tenant wording.
  • Save screenshots under the spec artifacts path when generated.

Phase 9 - Validation And Close-Out

  • Run targeted Feature/navigation tests, Browser smoke, filtered guard tests, pint --dirty, and git diff --check.
  • Report full suite status honestly if not run.
  • Record no migrations/seeders/packages/env/queues/scheduler/storage/deployment asset/backcompat/legacy alias support.

Testing Strategy

Required tests:

  • it('documents_operations_hub_repo_truth_map')
  • it('renders_operations_hub_decision_first_workbench')
  • it('renders_highest_priority_operation_needing_attention')
  • it('renders_operations_hub_empty_attention_state')
  • it('renders_operations_hub_operation_detail_proof_panel')
  • it('keeps_operations_table_available_as_secondary_context')
  • it('operations_hub_hides_raw_diagnostics_by_default')
  • it('operations_hub_does_not_show_progress_for_terminal_outcomes')
  • it('operations_hub_uses_determinate_progress_only_with_trustworthy_counts')
  • it('operations_hub_supports_canonical_environment_filter')
  • it('operations_hub_rejects_legacy_environment_aliases')
  • it('operations_hub_rejects_cross_workspace_environment_filter')
  • it('operations_hub_does_not_use_tenant_as_platform_context_copy')
  • it('operations_hub_respects_capabilities_for_primary_actions')

Required Browser smoke:

  • tests/Browser/Spec328OperationsHubProductizationSmokeTest.php

Browser flows:

  1. Clean workspace Operations Hub.
  2. Environment-filtered Operations Hub.
  3. Clear filter and reload.
  4. Non-empty highest-priority operation needing attention.
  5. Empty/no-attention state.
  6. Right operation/proof panel visible.
  7. Diagnostics hidden by default.
  8. Operations table/history remains secondary.
  9. No platform-context tenant wording.
  10. Light mode readability if supported.

Rollout Considerations

  • No feature flag expected.
  • No schema rollout.
  • No queue or scheduler rollout.
  • No env vars.
  • No new Filament asset registration expected. If implementation registers assets unexpectedly, deployment must include cd apps/platform && php artisan filament:assets, but the expected path is no asset change.
  • Staging validation should run the targeted feature/navigation/browser lanes before production promotion.

Risk Controls

  • Use repo-truth-map.md as the runtime claim gate.
  • Keep priority derived and feature-local.
  • Keep OperationRun detail/source surfaces as owners of deep diagnostics and mutations.
  • Keep progress semantics delegated to the existing progress contract.
  • Keep environment filtering delegated to existing workspace hub helpers.
  • Keep all raw/support information collapsed and capability-aware.
  • Keep final report explicit about unavailable states and full-suite status.

Implementation Close-Out

  • Implemented a page-local decision workbench in Operations::decisionWorkbench() and operations.blade.php.
  • Follow-up: replaced the custom summary-card Blade loop with a narrow native OperationsWorkbenchStats Filament StatsOverviewWidget using four Stat::make(...) records, descriptions, description icons, semantic colors, disabled polling, and scoped OperationRun queries.
  • Preserved existing route, table, tabs, row links, scope filter, and canonical detail route.
  • Added focused feature coverage and a Spec 328 browser smoke with clean, filtered, clear/reload, and empty/no-attention flows.
  • Adjusted canonical operation detail shell behavior so current/remembered environment context can be displayed as context while the canonical detail return action remains workspace-oriented.
  • No public backend abstraction, persisted state, migration, env var, package, queue, scheduler, storage, deployment asset, or legacy alias support was added.
  • Validation passed:
    • ./vendor/bin/sail artisan test tests/Feature/Monitoring tests/Feature/Operations tests/Feature/Navigation/WorkspaceHubEnvironmentFilterContractTest.php tests/Feature/Navigation/WorkspaceHubClearFilterContractTest.php --compact
    • ./vendor/bin/sail artisan test tests/Browser/Spec328OperationsHubProductizationSmokeTest.php --compact
    • ./vendor/bin/sail artisan test --filter='Operations|OperationRun|WorkspaceHub|EnvironmentFilter|ClearFilter|LegacyTenant|Spec322' --compact
    • ./vendor/bin/sail pint --dirty
    • git diff --check