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
209 lines
13 KiB
Markdown
209 lines
13 KiB
Markdown
---
|
||
|
||
description: "Task list for Ops-UX Constitution Rollout (v1.3.0 Alignment) (055)"
|
||
---
|
||
|
||
# Tasks: Ops-UX Constitution Rollout (v1.3.0 Alignment) (055)
|
||
|
||
**Input**: Design documents from `specs/055-ops-ux-rollout/`
|
||
|
||
**Tests**: REQUIRED (Pest) — runtime behavior + UX contract enforcement.
|
||
|
||
## Phase 1: Setup (Shared Infrastructure)
|
||
|
||
**Purpose**: Create a clean workspace for implementing and testing this migration.
|
||
|
||
- [x] T001 Create Ops UX test folder structure in `tests/Feature/OpsUx/`
|
||
- [x] T002 [P] Add a dedicated test file stub in `tests/Feature/OpsUx/OpsUxSmokeTest.php`
|
||
- [x] T003 [P] Add a shared test helper (factory/state helpers) in `tests/Support/OpsUxTestSupport.php`
|
||
|
||
---
|
||
|
||
## Phase 2: Foundational (Blocking Prerequisites)
|
||
|
||
**Purpose**: Shared primitives (catalog/links/presenter/normalization) that every user story depends on.
|
||
|
||
- [x] T004 Update runtime unknown-type label behavior in `app/Support/OperationCatalog.php` (render `Unknown operation`, never raw type)
|
||
- [x] T005 [P] Add shared presenter for toast/widget/notification copy in `app/Support/OpsUx/OperationUxPresenter.php`
|
||
- [x] T059 Implement a single status normalization function for Ops-UX rendering
|
||
- Map legacy completed/outcome values to canonical terminal statuses (`succeeded|partial|failed`)
|
||
- Ensure widget and notifications consume normalized status
|
||
- [x] T006 [P] Add summary_counts normalizer + whitelist enforcement in `app/Support/OpsUx/SummaryCountsNormalizer.php`
|
||
- [x] T060 Consolidate allowed summary keys into one code constant/source (no duplicated lists)
|
||
- Example shape: `OperationSummaryKeys::all()` (or similar)
|
||
- Normalizer MUST reference that source
|
||
- Catalog (if it references keys) MUST reference the same source
|
||
- Add one guard test asserting the list matches spec.md canonical list
|
||
- [x] T007 [P] Add canonical “View run” URL helper wrapper in `app/Support/OpsUx/OperationRunUrl.php` (delegates to `app/Support/OperationRunLinks.php`)
|
||
- [x] T008 Update summary key whitelist consumption in `app/Support/OperationCatalog.php` to reference the consolidated source (see T060)
|
||
- [x] T009 Update summary sanitization to use shared normalizer in `app/Services/OperationRunService.php`
|
||
- [x] T010 Update OperationRun completed notification to use shared presenter + normalizer in `app/Notifications/OperationRunCompleted.php`
|
||
- [x] T011 Disable queued DB notification emission by default in `app/Services/OperationRunService.php` (align with FR-010c)
|
||
- [x] T012 Deprecate/stop using queued DB notification class in `app/Notifications/OperationRunQueued.php` (keep class but ensure no producers call it)
|
||
- [x] T013 Ensure all “View run” actions inside operation notifications use canonical URL helper in `app/Notifications/OperationRunCompleted.php`
|
||
|
||
**Checkpoint**: Shared contracts available; user story work can proceed.
|
||
|
||
---
|
||
|
||
## Phase 3: User Story 1 — Consistent “I started it” feedback (Priority: P1) 🎯 MVP
|
||
|
||
**Goal**: Starting any operation shows queued-only intent feedback with canonical “View run”.
|
||
|
||
**Independent Test**: Trigger an operation start from a Filament action; observe a queued-only toast (`{OperationLabel} queued` / `Running in the background.`) and verify no queued DB notification is created.
|
||
|
||
### Tests for User Story 1
|
||
|
||
- [x] T014 [P] [US1] Add test ensuring no queued DB notifications are emitted in `tests/Feature/OpsUx/NoQueuedDbNotificationsTest.php`
|
||
- [x] T015 [P] [US1] Add test for canonical queued toast copy builder in `tests/Feature/OpsUx/QueuedToastCopyTest.php`
|
||
- [x] T057 [US1] Enforce toast auto-dismiss duration (3–5 seconds) for queued intent feedback (set duration explicitly, e.g. 4000ms)
|
||
- [x] T058 [P] [US1] (Optional guard) Centralize toast duration in `OperationUxPresenter` and add a small unit test to keep it within 3000–5000ms
|
||
|
||
### Implementation for User Story 1
|
||
|
||
- [x] T016 [P] [US1] Migrate queued toast copy for policy operations in `app/Filament/Resources/PolicyResource.php` (use `OperationUxPresenter`)
|
||
- [x] T017 [P] [US1] Migrate queued toast copy for policy version operations in `app/Filament/Resources/PolicyVersionResource.php` (use `OperationUxPresenter`)
|
||
- [x] T018 [P] [US1] Migrate queued toast copy for restore run operations in `app/Filament/Resources/RestoreRunResource.php` (use `OperationUxPresenter`)
|
||
- [x] T019 [P] [US1] Migrate queued toast copy for backup schedule operations in `app/Filament/Resources/BackupScheduleResource.php` (use `OperationUxPresenter`)
|
||
- [x] T020 [P] [US1] Migrate queued toast copy for backup set operations in `app/Filament/Resources/BackupSetResource.php` (use `OperationUxPresenter`)
|
||
- [x] T021 [P] [US1] Migrate queued toast copy for tenant sync operations in `app/Filament/Resources/TenantResource.php` (use `OperationUxPresenter`)
|
||
- [x] T022 [P] [US1] Migrate queued toast copy for policy view page operations in `app/Filament/Resources/PolicyResource/Pages/ViewPolicy.php` (use `OperationUxPresenter`)
|
||
- [x] T023 [P] [US1] Migrate queued toast copy for inventory landing operations in `app/Filament/Pages/InventoryLanding.php` (use `OperationUxPresenter`)
|
||
- [x] T024 [P] [US1] Migrate queued toast copy for drift landing operations in `app/Filament/Pages/DriftLanding.php` (use `OperationUxPresenter`)
|
||
- [x] T025 [P] [US1] Migrate queued toast copy for backup-set policy picker operations in `app/Livewire/BackupSetPolicyPickerTable.php` (use `OperationUxPresenter`)
|
||
|
||
**Checkpoint**: A user can start operations and get consistent queued intent feedback.
|
||
|
||
---
|
||
|
||
## Phase 4: User Story 2 — Live awareness of active operations (Priority: P2)
|
||
|
||
**Goal**: A single global widget shows only tenant-scoped queued/running runs with strict copy and canonical links.
|
||
|
||
**Independent Test**: Create active runs in the DB; the widget shows max 5 rows, each row has `Queued`/`Running` only, and terminal runs never render.
|
||
|
||
### Tests for User Story 2
|
||
|
||
- [x] T026 [P] [US2] Add widget filtering test (never show terminal) in `tests/Feature/OpsUx/ProgressWidgetFiltersTest.php`
|
||
- [x] T027 [P] [US2] Add widget max-5 + overflow link test in `tests/Feature/OpsUx/ProgressWidgetOverflowTest.php`
|
||
- [x] T062 [US2] Add restore execution → OperationRun sync regression test in `tests/Feature/OpsUx/RestoreExecutionOperationRunSyncTest.php`
|
||
|
||
### Implementation for User Story 2
|
||
|
||
- [x] T028 [US2] Migrate widget query from BulkOperationRun to OperationRun in `app/Livewire/BulkOperationProgress.php`
|
||
- [x] T029 [US2] Enforce tenant-wide scope + Monitoring access guard in `app/Livewire/BulkOperationProgress.php`
|
||
- [x] T030 [US2] Update widget UI strings + strict status text in `resources/views/livewire/bulk-operation-progress.blade.php`
|
||
- [x] T031 [US2] Implement max-5 + overflow link behavior in `resources/views/livewire/bulk-operation-progress.blade.php`
|
||
- [x] T032 [US2] Use canonical “View run” URLs in widget rows in `resources/views/livewire/bulk-operation-progress.blade.php` (via `OperationRunUrl` / `OperationRunLinks`)
|
||
- [x] T033 [US2] No % in widget; widget may show elapsed time only
|
||
- [x] T034 [US2] Implement calm polling schedule + pause rules in `resources/views/livewire/bulk-operation-progress.blade.php`
|
||
- [x] T063 [US2] Dispatch `ops-ux:run-enqueued` browser event after successful enqueue so the widget refreshes immediately
|
||
- Producers: `app/Filament/Pages/InventoryLanding.php`, `app/Filament/Pages/DriftLanding.php`, `app/Filament/Resources/BackupScheduleResource.php`, `app/Filament/Resources/PolicyResource.php`, `app/Filament/Resources/PolicyResource/Pages/ListPolicies.php`, `app/Filament/Resources/RestoreRunResource.php`, `app/Filament/Resources/TenantResource.php`, `app/Livewire/BackupSetPolicyPickerTable.php`, `app/Filament/Resources/BackupSetResource/RelationManagers/BackupItemsRelationManager.php`
|
||
- [x] T035 [US2] Confirm widget injection remains global and consistent in `app/Providers/Filament/AdminPanelProvider.php`
|
||
|
||
### Run detail polling (missing coverage for FR-013)
|
||
|
||
- [x] T053 [US2] Add run-detail polling controller/hook that applies calm polling while status is active (`queued|running`) (only poll when run detail is visible; stop immediately on terminal; backoff 1s (first 10s) → 5s → 10s (after 60s))
|
||
- [x] T054 [US2] Pause run-detail polling when a modal is open (global modal flag) and resume when closed (no network update spam while confirm dialogs/modals are open)
|
||
- [x] T055 [US2] Pause run-detail polling when browser tab is hidden (Page Visibility API) and resume when visible (no polling when `document.hidden = true`)
|
||
- [x] T056 [P] [US2] Add a small guard test/component test that run-detail polling is disabled once the run becomes terminal
|
||
- [x] T061 [US2] Surface elapsed time + expected duration + stuck guidance in run detail
|
||
|
||
**Checkpoint**: Widget is constitution-compliant and becomes the single active-ops surface.
|
||
|
||
---
|
||
|
||
## Phase 5: User Story 3 — Audit + outcome without spam (Priority: P3)
|
||
|
||
**Goal**: Exactly one terminal DB notification per run (initiator-only) with canonical copy, canonical link, safe summary.
|
||
|
||
**Independent Test**: Transition a run to terminal multiple times (or call completion twice); verify only one DB notification exists and it contains only whitelisted numeric summary keys.
|
||
|
||
### Tests for User Story 3
|
||
|
||
- [x] T036 [P] [US3] Add terminal notification idempotency test in `tests/Feature/OpsUx/TerminalNotificationIdempotencyTest.php`
|
||
- [x] T037 [P] [US3] Add summary whitelist + numeric-only test in `tests/Feature/OpsUx/SummaryCountsWhitelistTest.php`
|
||
- [x] T038 [P] [US3] Add canonical “View run” action test for notifications in `tests/Feature/OpsUx/NotificationViewRunLinkTest.php`
|
||
|
||
### Implementation for User Story 3
|
||
|
||
- [x] T039 [US3] Refactor terminal notification copy/title/body to use presenter in `app/Notifications/OperationRunCompleted.php`
|
||
- [x] T040 [US3] Ensure initiator-only delivery is enforced in `app/Services/OperationRunService.php`
|
||
- [x] T041 [US3] Ensure terminal notification is emitted exactly once per run in `app/Services/OperationRunService.php`
|
||
- [x] T042 [US3] Ensure notification summary renders only normalized `summary_counts` in `app/Notifications/OperationRunCompleted.php`
|
||
- [x] T043 [US3] Ensure failure message suffix is sanitized + short in `app/Notifications/OperationRunCompleted.php`
|
||
|
||
**Checkpoint**: Terminal outcomes are auditable without spam.
|
||
|
||
---
|
||
|
||
## Phase 6: User Story 4 — Regression-safe by default (Priority: P4)
|
||
|
||
**Goal**: Guards prevent drift (catalog coverage, canonical links, surface rules, summary rules).
|
||
|
||
**Independent Test**: Introduce a fake operation type in code and confirm tests fail; confirm “View run” always resolves to the canonical Monitoring run-detail destination.
|
||
|
||
### Tests for User Story 4
|
||
|
||
- [x] T044 [P] [US4] Add catalog coverage guard test in `tests/Feature/OpsUx/OperationCatalogCoverageTest.php`
|
||
- [x] T045 [P] [US4] Add canonical “View run” helper usage guard test in `tests/Feature/OpsUx/CanonicalViewRunLinksTest.php`
|
||
- [x] T046 [P] [US4] Add unknown-type runtime label test in `tests/Feature/OpsUx/UnknownOperationTypeLabelTest.php`
|
||
|
||
### Implementation for User Story 4
|
||
|
||
- [x] T047 [US4] Ensure OperationRunResource type label rendering never shows raw type in `app/Filament/Resources/OperationRunResource.php`
|
||
- [x] T048 [US4] Ensure Monitoring Operations page type labels never show raw type in `app/Filament/Pages/Monitoring/Operations.php`
|
||
- [x] T049 [US4] Ensure any remaining “View run” links use canonical helper in `app/Support/OperationRunLinks.php`
|
||
|
||
**Checkpoint**: Drift prevention is enforced in CI.
|
||
|
||
---
|
||
|
||
## Phase 7: Polish & Cross-Cutting Concerns
|
||
|
||
- [x] T050 [P] Run Pint autofix for touched files via `app/` and `tests/` (validate against `composer.json` scripts)
|
||
- [x] T051 Run targeted test suite for Ops UX via `tests/Feature/OpsUx/` (document exact filter in `specs/055-ops-ux-rollout/quickstart.md`)
|
||
- [x] T052 [P] Remove or update any stale queued-notification references in `app/Services/OperationRunService.php`
|
||
|
||
---
|
||
|
||
## Dependencies & Execution Order
|
||
|
||
### User Story Dependencies
|
||
|
||
- **US1 (P1)** depends on Phase 2 (Foundational) tasks T004–T013.
|
||
- **US2 (P2)** depends on Phase 2 (Foundational) tasks T004–T013.
|
||
- **US3 (P3)** depends on Phase 2 (Foundational) tasks T004–T013.
|
||
- **US4 (P4)** depends on completion of US1–US3 (guards should reflect final behavior).
|
||
|
||
### Recommended completion order
|
||
|
||
1. Phase 2 (Foundational)
|
||
2. US1 (queued toast + no queued DB notifications)
|
||
3. US3 (terminal notification contract)
|
||
4. US2 (widget)
|
||
5. US4 (guards)
|
||
|
||
## Parallel Opportunities
|
||
|
||
- Within Phase 2: T005–T007 can be done in parallel.
|
||
- US1 migration tasks T016–T025 are parallelizable (different files).
|
||
- US4 tests T044–T046 can be written in parallel.
|
||
|
||
## Parallel Example: User Story 1
|
||
|
||
- Task: T016 (PolicyResource) + T017 (PolicyVersionResource) + T018 (RestoreRunResource) can run in parallel.
|
||
- Task: T019 (BackupScheduleResource) + T020 (BackupSetResource) can run in parallel.
|
||
|
||
## Implementation Strategy
|
||
|
||
### MVP scope
|
||
|
||
Ship US1 + the minimum foundational primitives (Phase 2) to guarantee:
|
||
|
||
- queued-only toast copy is consistent
|
||
- queued DB notifications are banned
|
||
- canonical “View run” destination is available
|
||
|
||
Then layer US3 (terminal notification) before US2 (widget) to ensure audit outcomes are reliable early.
|