Kurzbeschreibung Versteckt die Rerun-Row-Action für archivierte (soft-deleted) RestoreRuns und verhindert damit fehlerhafte Neu-Starts aus dem Archiv; ergänzt einen Regressionstest. Änderungen Code: RestoreRunResource.php — Sichtbarkeit der rerun-Action geprüft auf ! $record->trashed() und defensive Abbruchprüfung im Action-Handler. Tests: RestoreRunRerunTest.php — neuer Test rerun action is hidden for archived restore runs. Warum Archivierte RestoreRuns durften nicht neu gestartet werden; UI zeigte trotzdem die Option. Das führte zu verwirrendem Verhalten und möglichen Fehlern beim Enqueueing. Verifikation / QA Unit/Feature: ./vendor/bin/sail artisan test tests/Feature/RestoreRunRerunTest.php Stil/format: ./vendor/bin/pint --dirty Manuell (UI): Als Tenant-Admin Filament → Restore Runs öffnen. Filter Archived aktivieren (oder Trashed filter auswählen). Sicherstellen, dass für archivierte Einträge die Rerun-Action nicht sichtbar ist. Auf einem aktiven (nicht-archivierten) Run prüfen, dass Rerun sichtbar bleibt und wie erwartet eine neue RestoreRun erzeugt. Wichtige Hinweise Kein DB-Migration required. Diese PR enthält nur den UI-/Filament-Fix; die zuvor gemachten operative Fixes für Queue/adapter-Reconciliation bleiben ebenfalls auf dem Branch (z. B. frühere commits während der Debugging-Session). T055 (Schema squash) wurde bewusst zurückgestellt und ist nicht Teil dieses PRs. Merge-Checklist Tests lokal laufen (RestoreRunRerunTest grünt) Pint läuft ohne ungepatchte Fehler Branch gepusht: 056-remove-legacy-bulkops (PR-URL: https://git.cloudarix.de/ahmido/TenantAtlas/compare/dev...056-remove-legacy-bulkops) Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #65
7.2 KiB
Implementation Plan: Remove Legacy BulkOperationRun & Canonicalize Operations (v1.0)
Branch: 056-remove-legacy-bulkops | Date: 2026-01-18 | Spec: specs/056-remove-legacy-bulkops/spec.md
Input: Feature specification from /specs/056-remove-legacy-bulkops/spec.md
Note: This template is filled in by the /speckit.plan command. See .specify/scripts/ for helper scripts.
Summary
Unify all bulk/operational work onto OperationRun (canonical run model + Monitoring surface) by migrating all legacy BulkOperationRun workflows to OperationRun-backed orchestration, removing the legacy stack (model/service/table/UI), and adding guardrails that prevent reintroduction.
Technical Context
Language/Version: PHP 8.4.x
Primary Dependencies: Laravel 12, Filament v4, Livewire v3
Storage: PostgreSQL (JSONB in operation_runs.context, operation_runs.summary_counts)
Testing: Pest (PHPUnit 12)
Target Platform: Docker via Laravel Sail (local); Dokploy (staging/prod)
Project Type: Web application (Laravel monolith)
Performance Goals: Calm polling UX for Monitoring; bulk orchestration chunked and resilient to throttling; per-scope concurrency default=1
Constraints: Tenant isolation; no secrets in run failures/notifications; no remote work during UI render; Monitoring is DB-only
Scale/Scope: Bulk actions may target large selections; orchestration must remain idempotent and debounced by run identity
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
- Inventory-first: N/A (this feature is operations plumbing; no inventory semantics change)
- Read/write separation: PASS (bulk actions remain enqueue-only; write paths are job-backed and auditable)
- Graph contract path: PASS (no new render-side Graph calls; any remote work stays behind queue + existing Graph client boundary)
- Deterministic capabilities: PASS (no capability derivation changes)
- Tenant isolation: PASS (OperationRun is tenant-scoped; bulk dedupe is tenant-wide; selection identity is deterministic)
- Run observability: PASS (bulk is always OperationRun-backed; DB-only <2s actions remain audit-only)
- Automation: PASS (locks + idempotency required; per-target concurrency is config-driven default=1)
- Data minimization: PASS (failure summaries stay sanitized; no secrets in run records)
Project Structure
Documentation (this feature)
specs/056-remove-legacy-bulkops/
├── plan.md # This file (/speckit.plan command output)
├── research.md # Phase 0 output (/speckit.plan command)
├── data-model.md # Phase 1 output (/speckit.plan command)
├── quickstart.md # Phase 1 output (/speckit.plan command)
├── contracts/ # Phase 1 output (/speckit.plan command)
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
Source Code (repository root)
app/
├── Filament/
│ ├── Resources/
│ └── Pages/
├── Jobs/
├── Models/
├── Notifications/
├── Services/
└── Support/
config/
├── tenantpilot.php
└── graph_contracts.php
database/
├── migrations/
└── factories/
resources/
└── views/
routes/
└── web.php
tests/
├── Feature/
└── Unit/
Structure Decision: Laravel web application (monolith). Feature changes are expected primarily under app/ (runs, jobs, Filament actions), database/migrations/ (dropping legacy tables), and tests/ (Pest guardrails).
Complexity Tracking
Fill ONLY if Constitution Check has violations that must be justified
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| None | N/A | N/A |
Constitution Check (Post-Design)
Re-check after Phase 1 outputs are complete.
- Monitoring remains DB-only at render time.
- Start surfaces remain enqueue-only.
- Bulk work is always OperationRun-backed.
- Per-target scope concurrency is config-driven (default=1).
- Bulk idempotency uses hybrid selection identity.
Phase 0 — Outline & Research (output: research.md)
Discovery signals (repo sweep)
Legacy bulk-run usage exists and must be migrated/removed:
- Jobs using legacy run/service include:
app/Jobs/BulkPolicySyncJob.phpapp/Jobs/BulkPolicyDeleteJob.phpapp/Jobs/BulkBackupSetDeleteJob.phpapp/Jobs/BulkPolicyVersionPruneJob.phpapp/Jobs/BulkPolicyVersionForceDeleteJob.phpapp/Jobs/BulkRestoreRunDeleteJob.phpapp/Jobs/BulkTenantSyncJob.phpapp/Jobs/CapturePolicySnapshotJob.phpapp/Jobs/GenerateDriftFindingsJob.php(mixed: legacy + OperationRun)
Legacy data layer present:
- Model:
app/Models/BulkOperationRun.php - Service:
app/Services/BulkOperationService.php - Migrations:
database/migrations/*_create_bulk_operation_runs_table.php,*_add_idempotency_key_to_bulk_operation_runs_table.php,*_increase_bulk_operation_runs_status_length.php - Factory/Seeder:
database/factories/BulkOperationRunFactory.php,database/seeders/BulkOperationsTestSeeder.php
Existing canonical run patterns to reuse:
app/Services/OperationRunService.phpprovides tenant-wide active-run dedupe and safe dispatch semantics.app/Support/OperationCatalog.phpcentralizes labels/durations and allowed summary keys.app/Support/OpsUx/OperationSummaryKeys.php+SummaryCountsNormalizerenforce summary_counts contract.
Concurrency/idempotency patterns already exist and should be adapted:
app/Services/Inventory/InventoryConcurrencyLimiter.phpuses per-scope cache locks with config-driven defaults.app/Services/Inventory/InventorySyncService.phpuses selection hashing + selection locks to prevent duplicate work.
Research outputs (decisions)
- Per-target scope concurrency is configuration-driven with default=1.
- Bulk selection identity is hybrid (IDs-hash when explicit IDs; query-hash when “select all via filter/query”).
- Legacy bulk-run history is not imported into OperationRun (default path).
Phase 1 — Design & Contracts (outputs: data-model.md, contracts/*, quickstart.md)
Design topics
- Define the canonical bulk orchestration shape around OperationRun (orchestrator + workers) while preserving the constitution feedback surfaces.
- Define the minimal run context contract for directory-targeted runs (target scope fields + idempotency fingerprint fields).
- Extend operation type catalog for newly migrated bulk operations.
Contract artifacts
- JSON schema for
operation_runs.contextfor bulk operations (target scope + selection identity + idempotency). - OpenAPI sketch for internal operation-triggering endpoints (if applicable) as a stable contract for “enqueue-only” start surfaces.
Phase 2 — Planning (implementation outline; detailed tasks live in tasks.md)
- Perform required discovery sweep and create a migration report.
- Migrate each legacy bulk workflow to OperationRun-backed orchestration.
- Remove legacy model/service/table/UI surfaces.
- Add hard guardrails (CI/test) to forbid legacy references and verify run-backed behavior.
- Add targeted Pest tests for bulk actions, per-scope throttling default=1, and summary key normalization.