## 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
110 lines
5.2 KiB
Markdown
110 lines
5.2 KiB
Markdown
# Data Model: System Operations Surface Alignment
|
|
|
|
## Overview
|
|
|
|
This feature introduces no new persisted entity, no new table, and no new status family. It reuses existing `OperationRun` truth and existing platform capability checks, while narrowing where triage actions are exposed in the UI.
|
|
|
|
## Entity: OperationRun
|
|
|
|
- **Type**: Existing persisted model
|
|
- **Purpose in this feature**: Canonical record shown on the three system list pages and on the system run detail page.
|
|
|
|
### Relevant Fields
|
|
|
|
| Field | Type | Notes |
|
|
|-------|------|-------|
|
|
| `id` | integer | Displayed as `Operation #<id>` and used in canonical detail routing. |
|
|
| `workspace_id` | integer | Required for platform-wide run context. |
|
|
| `tenant_id` | integer nullable | Nullable for tenantless/platform runs; still shown on system lists and detail. |
|
|
| `initiator_name` | string nullable | Default-visible operator truth on the all-runs list. |
|
|
| `type` | string | Rendered through `OperationCatalog::label(...)`. |
|
|
| `status` | string | Badge-rendered lifecycle dimension. |
|
|
| `outcome` | string | Badge-rendered execution-outcome dimension. |
|
|
| `context` | array/json | Stores triage metadata such as retry, cancel, and investigation context. |
|
|
| `created_at` | timestamp | Used for default-visible list activity time and recency on all three lists. |
|
|
| `started_at` | timestamp nullable | Supports stuck classification and detail timing. |
|
|
| `completed_at` | timestamp nullable | Preserved for completed/failed runs and detail history. |
|
|
|
|
### Relationships
|
|
|
|
| Relationship | Target | Purpose |
|
|
|--------------|--------|---------|
|
|
| `workspace` | `Workspace` | Default-visible context on all system lists and on the detail page. |
|
|
| `tenant` | `Tenant` | Default-visible context on all system lists and on the detail page. |
|
|
|
|
### Feature-Specific Invariants
|
|
|
|
- All three system lists eager-load `tenant` and `workspace`.
|
|
- `Runs` shows the full platform-wide run set.
|
|
- `Failures` filters to `status=completed` and `outcome=failed`.
|
|
- `Stuck` filters through `StuckRunClassifier` and exposes a derived `stuck_class` label.
|
|
- List inspection always resolves to `SystemOperationRunLinks::view($run)`.
|
|
|
|
### State Transitions Used By This Feature
|
|
|
|
| Transition | Preconditions | Result |
|
|
|------------|---------------|--------|
|
|
| Inspect list row | Operator has `platform.operations.view` | No state change; opens canonical detail page. |
|
|
| Retry run | Run is completed, failed, and retryable | Creates a new queued `OperationRun` with `context.triage.retry_of_run_id` and audit action `platform.system_console.retry`. |
|
|
| Cancel run | Run is queued or running and cancelable | Updates the current run to completed/failed through `OperationRunService` and logs `platform.system_console.cancel`. |
|
|
| Mark investigated | Operator has manage capability and supplies a valid reason | Updates `context.triage.investigated` on the current run and logs `platform.system_console.mark_investigated`. |
|
|
|
|
## Entity: PlatformUser Capability Gate
|
|
|
|
- **Type**: Existing persisted/authenticated actor model
|
|
- **Purpose in this feature**: Separates inspection access from triage access on system-panel surfaces.
|
|
|
|
### Relevant Capability Fields
|
|
|
|
| Capability | Purpose |
|
|
|------------|---------|
|
|
| `platform.access_system_panel` | Required to enter the system panel. |
|
|
| `platform.operations.view` | Required to access the system runs/failures/stuck/detail surfaces. |
|
|
| `platform.operations.manage` | Required to see and execute triage actions on the detail page. |
|
|
|
|
### Feature-Specific Invariants
|
|
|
|
- View-only users can load list and detail pages but cannot see triage actions.
|
|
- Manage-capable users retain retry/cancel/mark-investigated on the detail header.
|
|
- No new capability is introduced.
|
|
|
|
## Derived UI Contract: System Operations Lists
|
|
|
|
- **Type**: Derived UI surface, not persisted
|
|
- **Routes**:
|
|
- `/system/ops/runs`
|
|
- `/system/ops/failures`
|
|
- `/system/ops/stuck`
|
|
- **Surface Type**: `ReadOnlyRegistryReport`
|
|
- **Primary Question**: Which operation should I open next?
|
|
|
|
### Contract Rules
|
|
|
|
- Primary inspect affordance is full-row click only.
|
|
- Row actions are empty.
|
|
- Bulk actions are empty.
|
|
- Visible collection naming uses `Operations` and visible singular naming uses `Operation`.
|
|
- `/system/ops/runs` uses `Go to runbooks` as its single header and empty-state CTA.
|
|
- `/system/ops/failures` and `/system/ops/stuck` use `Show all operations` as their single header and empty-state CTA.
|
|
|
|
## Derived UI Contract: System Run Detail
|
|
|
|
- **Type**: Derived UI surface, not persisted
|
|
- **Route**: `/system/ops/runs/{run}`
|
|
- **Surface Type**: Detail-first operational surface
|
|
- **Primary Question**: What happened on this operation, and what follow-up is appropriate?
|
|
|
|
### Contract Rules
|
|
|
|
- Header actions remain the only triage location for retry, cancel, and mark investigated.
|
|
- The detail surface exposes `Show all operations` as the canonical return path and keeps `Go to runbooks` available as secondary navigation.
|
|
- `cancel` remains destructive and confirmation-gated.
|
|
- `mark investigated` retains the `reason` validation rule: required, minimum 5 characters, maximum 500 characters.
|
|
- No new page, modal surface, or alternate triage route is introduced.
|
|
|
|
## Persistence Impact
|
|
|
|
- **Schema changes**: None
|
|
- **Data migration**: None
|
|
- **New indexes**: None
|
|
- **Retention impact**: None |