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
Summary
Kurz: Implementiert Feature 054 — canonical OperationRun-flow, Monitoring UI, dispatch-safety, notifications, dedupe, plus small UX safety clarifications (RBAC group search delegated; Restore group mapping DB-only).
What Changed
Core service: OperationRun lifecycle, dedupe and dispatch helpers — OperationRunService.php.
Model + migration: OperationRun model and migration — OperationRun.php, 2026_01_16_180642_create_operation_runs_table.php.
Notifications: queued + terminal DB notifications (initiator-only) — OperationRunQueued.php, OperationRunCompleted.php.
Monitoring UI: Filament list/detail + Livewire pieces (DB-only render) — OperationRunResource.php and related pages/views.
Start surfaces / Jobs: instrumented start surfaces, job middleware, and job updates to use canonical runs — multiple app/Jobs/* and app/Filament/* updates (see tests for full coverage).
RBAC + Restore UX clarifications: RBAC group search is delegated-Graph-based and disabled without delegated token; Restore group mapping remains DB-only (directory cache) and helper text always visible — TenantResource.php, RestoreRunResource.php.
Specs / Constitution: updated spec & quickstart and added one-line constitution guideline about Graph usage:
spec.md
quickstart.md
constitution.md
Tests & Verification
Unit / Feature tests added/updated for run lifecycle, notifications, idempotency, and UI guards: see tests/Feature/* (notably OperationRunServiceTest, MonitoringOperationsTest, OperationRunNotificationTest, and various Filament feature tests).
Full test run locally: ./vendor/bin/sail artisan test → 587 passed, 5 skipped.
Migrations
Adds create_operation_runs_table migration; run php artisan migrate in staging after review.
Notes / Rationale
Monitoring pages are explicitly DB-only at render time (no Graph calls). Start surfaces enqueue work only and return a “View run” link.
Delegated Graph access is used only for explicit user actions (RBAC group search); restore mapping intentionally uses cached DB data only to avoid render-time Graph calls.
Dispatch wrapper marks runs failed immediately if background dispatch throws synchronously to avoid misleading “queued” states.
Upgrade / Deploy Considerations
Run migrations: ./vendor/bin/sail artisan migrate.
Background workers should be running to process queued jobs (recommended to monitor queue health during rollout).
No secret or token persistence changes.
PR checklist
Tests updated/added for changed behavior
Specs updated: 054-unify-runs-suitewide docs + quickstart
Constitution note added (.specify)
Pint formatting applied
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local>
Reviewed-on: #63
Summary
This PR introduces Unified Operations Runs + Monitoring Hub (053).
Goal: Standardize how long-running operations are tracked and monitored using the existing tenant-scoped run record (BulkOperationRun) as the canonical “operation run”, and surface it in a single Monitoring → Operations hub (view-only, tenant-scoped, role-aware).
Phase 1 adoption scope (per spec):
• Drift generation (drift.generate)
• Backup Set “Add Policies” (backup_set.add_policies)
Note: This PR does not convert every run type yet (e.g. GroupSyncRuns / InventorySyncRuns remain separate for now). This is intentionally incremental.
⸻
What changed
Monitoring / Operations hub
• Moved/organized run monitoring under Monitoring → Operations
• Added:
• status buckets (queued / running / succeeded / partially succeeded / failed)
• filters (run type, status bucket, time range)
• run detail “Related” links (e.g. Drift findings, Backup Set context)
• All hub pages are DB-only and view-only (no rerun/cancel/delete actions)
Canonical run semantics
• Added canonical helpers on BulkOperationRun:
• runType() (resource.action)
• statusBucket() derived from status + counts (testable semantics)
Drift integration (Phase 1)
• Drift generation start behavior now:
• creates/reuses a BulkOperationRun with drift context payload (scope_key + baseline/current run ids)
• dispatches generation job
• emits DB notifications including “View run” link
• On generation failure: stores sanitized failure entries + sends failure notification
Permissions / tenant isolation
• Monitoring run list/view is tenant-scoped and returns 403 for cross-tenant access
• Readonly can view runs but cannot start drift generation
⸻
Tests
Added/updated Pest coverage:
• BulkOperationRunStatusBucketTest.php
• DriftGenerationDispatchTest.php
• GenerateDriftFindingsJobNotificationTest.php
• RunAuthorizationTenantIsolationTest.php
Validation run locally:
• ./vendor/bin/pint --dirty
• targeted tests from feature quickstart / drift monitoring tests
⸻
Manual QA
1. Go to Monitoring → Operations
• verify filters (run type / status / time range)
• verify run detail shows counts + sanitized failures + “Related” links
2. Open Drift Landing
• with >=2 successful inventory runs for scope: should queue drift generation + show notification with “View run”
• as readonly: should not start generation
3. Run detail
• drift.generate runs show “Drift findings” related link
• failure entries are sanitized (no secrets/tokens/raw payload dumps)
⸻
Notes / Ops
• Queue workers must be restarted after deploy so they load the new code:
• php artisan queue:restart (or Sail equivalent)
• This PR standardizes monitoring for Phase 1 producers only; follow-ups will migrate additional run types into the unified pattern.
⸻
Spec / Docs
• SpecKit artifacts added under specs/053-unify-runs-monitoring/
• Checklists are complete:
• requirements checklist PASS
• writing checklist PASS
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local>
Reviewed-on: #60