TenantAtlas/specs/170-system-operations-surface-alignment/data-model.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

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