Kurzbeschreibung Implementiert Feature 055 — Ops‑UX Constitution Rollout v1.3.0. Behebt: globales BulkOperationProgress-Widget benötigt keinen manuellen Refresh mehr; ETA/Elapsed aktualisieren korrekt; Widget verschwindet automatisch. Verbesserungen: zuverlässiges polling (Alpine factory + Livewire fallback), sofortiger Enqueue‑Signal-Dispatch, Failure‑Message‑Sanitization, neue Guard‑ und Regressionstests, Specs/Tasks aktualisiert. Was geändert wurde (Auszug) InventoryLanding.php bulk-operation-progress.blade.php OperationUxPresenter.php SyncRestoreRunToOperationRun.php PolicyResource.php PolicyVersionResource.php RestoreRunResource.php tests/Feature/OpsUx/* (PollerRegistration, TerminalNotificationFailureMessageTest, CanonicalViewRunLinksTest, OperationCatalogCoverageTest, UnknownOperationTypeLabelTest) InventorySyncButtonTest.php tasks.md Tests Neue Tests hinzugefügt; php artisan test --group=ops-ux lokal grün (alle relevanten Tests laufen). How to verify manually Auf Branch wechseln: 055-ops-ux-rollout In Filament: Inventory → Sync (oder relevante Bulk‑Aktion) auslösen. Beobachten: Progress‑Widget erscheint sofort, ETA/Elapsed aktualisiert, Widget verschwindet nach Fertigstellung ohne Browser‑Refresh. Optional: ./vendor/bin/sail exec app php artisan test --filter=OpsUx oder php artisan test --group=ops-ux Besonderheiten / Hinweise Einzelne, synchrone Policy‑Actions (ignore/restore/PolicyVersion single archive/restore/forceDelete) sind absichtlich inline und erzeugen kein OperationRun. Bulk‑Aktionen und restore.execute werden als Runs modelliert. Wenn gewünscht, kann ich die inline‑Actions auf OperationRunService umstellen, damit sie in Monitoring → Operations sichtbar werden. Remote: Branch ist bereits gepusht (origin/055-ops-ux-rollout). PR kann in Gitea erstellt werden. Links Specs & tasks: tasks.md Monitoring page: Operations.php Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #64
105 lines
3.4 KiB
Markdown
105 lines
3.4 KiB
Markdown
# Phase 1 Data Model: Ops-UX Constitution Rollout (v1.3.0 Alignment) (055)
|
|
|
|
**Date**: 2026-01-18
|
|
|
|
This feature is a migration: it standardizes how existing `operation_runs` records are presented via three UX surfaces.
|
|
|
|
## Entities
|
|
|
|
### 1) OperationRun (existing)
|
|
|
|
**Source**: `operation_runs` table
|
|
|
|
**Fields (relevant to this feature)**
|
|
|
|
- `id` (int)
|
|
- `tenant_id` (int)
|
|
- `user_id` (int|null) — initiator user
|
|
- `initiator_name` (string)
|
|
- `type` (string) — operation type identifier
|
|
- `status` (string) — active: `queued|running`, terminal: `completed`
|
|
- `outcome` (string) — `pending|succeeded|partially_succeeded|failed|cancelled` (existing vocabulary)
|
|
- `started_at` (timestamp|null)
|
|
- `completed_at` (timestamp|null)
|
|
- `summary_counts` (jsonb) — canonical “metrics” source for this rollout
|
|
- `failure_summary` (jsonb) — array of failures with sanitized messages
|
|
- `context` (jsonb) — structured context used for related links
|
|
|
|
### Status / Outcome (UX-canonical)
|
|
|
|
The Ops-UX surfaces (toast/widget/db notifications) use the canonical statuses:
|
|
|
|
- active: `queued` | `running`
|
|
- terminal: `succeeded` | `partial` | `failed`
|
|
|
|
### Legacy / compatibility mapping (if older records exist)
|
|
|
|
Some existing records may use legacy fields/values (for example `status=completed` with an `outcome`).
|
|
These MUST be normalized for UX rendering as follows:
|
|
|
|
Normalization rules:
|
|
|
|
- `status=completed` AND `outcome=succeeded` -> `terminal=succeeded`
|
|
- `status=completed` AND `outcome=partially_succeeded` -> `terminal=partial`
|
|
- `status=failed` OR `outcome=failed` -> `terminal=failed`
|
|
|
|
Notes:
|
|
|
|
- The Monitoring UI MUST remain usable if legacy values exist.
|
|
- Normalization is a presentation concern for Ops-UX; storage may remain unchanged during rollout.
|
|
|
|
### 2) OperationCatalog (new/standardized)
|
|
|
|
**Purpose**: single source of truth for operation labels.
|
|
|
|
**Fields**
|
|
|
|
- `operation_type` (string) → `label` (string)
|
|
|
|
**Rules**
|
|
|
|
- Any code-produced operation type must be registered (CI guard).
|
|
- Unknown types from historical data render as `Unknown operation`.
|
|
|
|
### 3) OperationRunUrl (new helper)
|
|
|
|
**Purpose**: canonical URL generator for “View run”.
|
|
|
|
**Rule**: all “View run” links must route to Monitoring → Operations → Run Detail.
|
|
|
|
### 4) OperationUxPresenter (new presenter/builder)
|
|
|
|
**Purpose**: centralized presentation for all three surfaces.
|
|
|
|
**Responsibilities**
|
|
|
|
- Toast copy for queued intent
|
|
- Progress widget row presentation (label, status text, optional progress)
|
|
- Terminal DB notification title/body/status and optional summary rendering
|
|
|
|
## Validation rules
|
|
|
|
### Summary counts (`operation_runs.summary_counts`)
|
|
|
|
- Must be a flat object/dictionary.
|
|
- Allowed keys only:
|
|
- `total, processed, succeeded, failed, skipped, created, updated, deleted, items, tenants`
|
|
- Values must be numeric and normalized to integers.
|
|
- Invalid keys/values are ignored; if nothing valid remains, no summary is rendered.
|
|
|
|
### Failure messages
|
|
|
|
- Short, sanitized, no secrets/tokens, no payload dumps.
|
|
- Used only for terminal failure notification body as optional suffix.
|
|
|
|
## Relationships
|
|
|
|
- `OperationRun` belongs to `Tenant`
|
|
- `OperationRun` belongs to `User` (initiator) (nullable)
|
|
|
|
## Derived fields for presentation
|
|
|
|
- `OperationLabel` = `OperationCatalog::label(type)` (or `Unknown operation`)
|
|
- `UxStatus` = `Queued|Running|Completed|Partial|Failed` (derived)
|
|
- `ProgressPercent` (optional) = `processed / total` only when both exist and are valid
|