TenantAtlas/specs/170-system-operations-surface-alignment/plan.md
ahmido fdd3a85b64 feat: align system operations surfaces (#201)
## Summary
- align the system-panel Operations, Failed operations, and Stuck operations pages to the read-only registry contract by removing inline row triage and keeping row-click inspection
- keep retry, cancel, and mark-investigated behavior on the canonical system operation detail page while adding the explicit `Show all operations` return path and updated `Operations / Operation` copy
- add and update focused Pest and Livewire coverage for list CTA behavior, detail-owned triage, and view-only versus manage-capable platform access
- add Spec 170 implementation artifacts plus the follow-on Spec 171 and Spec 172 packages

## Testing
- `vendor/bin/sail artisan test --compact tests/Feature/System/Spec114/OpsTriageActionsTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/System/Spec114/OpsFailuresViewTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/System/Spec114/OpsStuckViewTest.php`
- integrated browser smoke on `/system/ops/runs`, `/system/ops/failures`, `/system/ops/stuck`, empty states via search filter, and detail-page retry confirmation visibility

## Notes
- branch pushed from `170-system-operations-surface-alignment`
- latest commit: `64b4d741 feat: align system operations surfaces`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #201
2026-03-30 19:08:56 +00:00

128 lines
9.3 KiB
Markdown

# Implementation Plan: System Operations Surface Alignment
**Branch**: `170-system-operations-surface-alignment` | **Date**: 2026-03-30 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/170-system-operations-surface-alignment/spec.md`
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/170-system-operations-surface-alignment/spec.md`
## Summary
Align the system-panel Operations, Failed operations, and Stuck operations pages to their declared `ReadOnlyRegistryReport` surface semantics by removing inline triage from the list rows, preserving full-row navigation to the canonical system operation detail page, standardizing visible naming to `Operations` / `Operation`, and adding the required list CTA and detail return-path behavior while keeping retry/cancel/mark-investigated ownership on the existing `ViewRun` page. The implementation stays narrow: no schema, new capability, or service-model changes; only Filament page behavior, visible operator copy, and the associated Pest/Livewire guard coverage are updated.
## Technical Context
**Language/Version**: PHP 8.4, Laravel 12, Livewire v4, Filament v5
**Primary Dependencies**: `laravel/framework`, `filament/filament`, `livewire/livewire`, `pestphp/pest`
**Storage**: PostgreSQL with existing `operation_runs` and `audit_logs` tables; no schema changes
**Testing**: Pest feature tests with Livewire component assertions, executed through Laravel Sail
**Target Platform**: Laravel web application running in Sail locally and containerized Linux environments in staging/production
**Project Type**: Laravel monolith with Filament panels
**Performance Goals**: Preserve current DB-only list rendering, eager loading of `tenant` and `workspace`, and existing pagination/sort behavior with no extra remote calls
**Constraints**: Platform plane only; no new pages/capabilities/persistence; visible naming must align to `Operations` / `Operation`; destructive triage stays confirmation-gated; existing queued-toast and audit behavior must remain intact
**Scale/Scope**: Four existing system-panel pages, one existing detail Blade view, one existing triage service, and the focused feature/guard tests that encode current row-action behavior
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
- `PASS` Inventory-first / snapshots-second: the feature does not change inventory, backups, or snapshot truth.
- `PASS` Read/write separation: no new writes are introduced; existing retry/cancel/mark-investigated flows remain explicit operator actions with confirmation where required.
- `PASS` Graph contract path: no Microsoft Graph call path is touched.
- `PASS` Deterministic capabilities: existing `PlatformCapabilities::OPERATIONS_VIEW` and `PlatformCapabilities::OPERATIONS_MANAGE` remain the canonical gates.
- `PASS` RBAC-UX plane separation: the slice is limited to `/system` surfaces and existing platform guard semantics.
- `PASS` Destructive confirmation standard: `cancel` remains `->requiresConfirmation()` on the detail header.
- `PASS` Ops-UX 3-surface feedback: retry continues to use `OperationUxPresenter::queuedToast(...)`; cancel and mark-investigated remain local terminal confirmations without adding queued/running notifications.
- `PASS` Ops lifecycle ownership: status/outcome mutation continues to flow through `OperationRunService` inside `OperationRunTriageService`; no new lifecycle path is introduced.
- `PASS` Proportionality / bloat: the feature removes duplicated interaction semantics and adds no new persistence, abstraction, state family, or taxonomy.
- `PASS` Badge semantics: list/detail badge rendering stays on the shared badge catalog and renderer.
- `PASS` Filament-native UI: the change stays inside existing Filament pages, row navigation, header actions, and confirmations.
- `PASS` UI surface taxonomy: Runs, Failures, and Stuck remain `ReadOnlyRegistryReport`; `ViewRun` remains the detail-first operational surface.
- `PASS` UI inspect model: each list will expose exactly one primary inspect model, `recordUrl()` row click.
- `PASS` UI action hierarchy: registry lists will have no inline triage; detail header remains the single triage owner.
- `PASS` UI naming scope: the changed system surfaces standardize visible copy to `Operations` / `Operation` while keeping internal route stability explicit.
- `PASS` Empty-state CTA rule: each changed list surface will define exactly one page-appropriate CTA and matching header action.
- `PASS` Placeholder/empty-group ban: no empty groups are introduced; bulk actions remain absent because there is no real bulk use case.
- `PASS` OPSURF page contract: the governing spec already defines persona, operator question, default truth, mutation scope, and dangerous actions.
- `PASS` Testing truth: implementation will update behavior guards, not just declarations.
## Project Structure
### Documentation (this feature)
```text
specs/170-system-operations-surface-alignment/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── system-ops-surface-contract.yaml
└── tasks.md
```
### Source Code (repository root)
```text
app/
├── Filament/
│ └── System/
│ └── Pages/
│ └── Ops/
│ ├── Runs.php
│ ├── Failures.php
│ ├── Stuck.php
│ └── ViewRun.php
├── Services/
│ └── SystemConsole/
│ └── OperationRunTriageService.php
├── resources/
│ └── views/
│ └── filament/
│ └── system/
│ └── pages/
│ └── ops/
│ └── view-run.blade.php
└── Support/
└── System/
└── SystemOperationRunLinks.php
tests/
└── Feature/
├── Guards/
│ └── ActionSurfaceContractTest.php
└── System/
└── Spec114/
├── OpsTriageActionsTest.php
├── OpsFailuresViewTest.php
└── OpsStuckViewTest.php
```
**Structure Decision**: This is a single Laravel application. The implementation is confined to existing system-panel Filament pages and existing Pest feature/guard tests. No new application layer or directory is needed.
## Complexity Tracking
No constitution waiver is expected. This slice reduces surface complexity instead of introducing a new layer.
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| None | Not applicable | Not applicable |
## Proportionality Review
- **Current operator problem**: the three system list pages are declared as read-only registry surfaces but still expose direct triage actions, leave empty-state navigation underdefined, and continue to present `Runs` as a competing visible noun beside the canonical `Operations` vocabulary.
- **Existing structure is insufficient because**: the current hybrid model forces operators to choose between acting in-row and opening the richer detail page, while the constitution requires one primary inspect model, stable nouns, and explicit CTA behavior for changed list surfaces.
- **Narrowest correct implementation**: remove list row triage actions, keep `recordUrl()` row-click navigation, standardize visible copy to `Operations` / `Operation`, add one clear list CTA per changed surface, add a `Show all operations` return path on the detail page, and update the existing tests to assert the aligned behavior.
- **Ownership cost created**: low. The change requires focused updates to Filament page classes and the behavior guards that currently encode list-level triage.
- **Alternative intentionally rejected**: reclassifying the list pages as queue/review surfaces or adding new exception types was rejected because these pages are scan-first registries, not context-preserving decision queues.
- **Release truth**: current-release truth. The canonical detail page and triage service already exist today; the feature removes duplication rather than preparing speculative future structure.
## Post-Design Constitution Re-check
- `PASS` `UI-CONST-001` / `UI-SURF-001`: the artifacts keep list pages in the registry class and the detail page as the triage owner.
- `PASS` `UI-HARD-001`: the target design leaves each system list with exactly one primary inspect model and zero inline destructive actions.
- `PASS` `UI-EX-001`: no new exception type or exemption is needed for this slice.
- `PASS` `OPSURF-001`: list pages stay scan-first, while the detail page remains the context-rich operational surface.
- `PASS` `RBAC-UX-001` to `RBAC-UX-005`: view/manage separation, server-side enforcement, and destructive confirmation rules remain unchanged.
- `PASS` `UI-NAMING-001`: visible system-surface nomenclature now aligns to `Operations` / `Operation`.
- `PASS` Empty-state CTA requirement: the design now defines a primary CTA for each changed list surface and a return path on the detail page.
- `PASS` `BLOAT-001`: no new persistence, abstraction, state family, or taxonomy was introduced during design.
- `PASS` Filament v5 / Livewire v4 guardrails: the plan keeps changes inside existing Filament pages and does not require provider or asset registration changes.