From 623171c9046443f2138ad00cbbc4c57ead33d0b8 Mon Sep 17 00:00:00 2001 From: Ahmed Darrazi Date: Thu, 25 Dec 2025 01:37:05 +0100 Subject: [PATCH] spec: align 005 bulk ops docs --- specs/005-bulk-operations/plan.md | 2 +- specs/005-bulk-operations/spec.md | 20 ++++++++++++------- specs/005-bulk-operations/tasks.md | 32 +++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/specs/005-bulk-operations/plan.md b/specs/005-bulk-operations/plan.md index 0a79cf8..2455f5b 100644 --- a/specs/005-bulk-operations/plan.md +++ b/specs/005-bulk-operations/plan.md @@ -88,7 +88,7 @@ ### Documentation (this feature) ├── research.md # Phase 0 output (see below) ├── data-model.md # Phase 1 output (see below) ├── quickstart.md # Phase 1 output (see below) -└── tasks.md # Phase 2 output (/speckit.tasks command - NOT YET CREATED) +└── tasks.md # Phase 2 output (/speckit.tasks command - generated and tracked here) ``` ### Source Code (repository root) diff --git a/specs/005-bulk-operations/spec.md b/specs/005-bulk-operations/spec.md index 1c3cc37..7d578e0 100644 --- a/specs/005-bulk-operations/spec.md +++ b/specs/005-bulk-operations/spec.md @@ -90,16 +90,16 @@ ### User Story 3 - Bulk Delete Policy Versions (Priority: P2) **Acceptance Criteria:** 1. **Given** I select 30 policy versions older than 90 days, - **When** I click "Delete", - **Then** confirmation dialog: "Delete 30 policy versions? This is permanent and cannot be undone." + **When** I click "Prune (Archive)", + **Then** confirmation dialog: "Archive 30 policy versions? Archived versions can be restored until force-deleted." 2. **Given** I confirm, **When** the operation completes, **Then**: - System checks each version: is_current=false + not referenced + age >90 days - - Eligible versions are hard-deleted + - Eligible versions are archived (soft-deleted) - Ineligible versions are skipped with reason (e.g., "Referenced by Backup Set ID 5") - - Success notification: "Deleted 28 policy versions (2 skipped)" + - Success notification: "Archived 28 policy versions (2 skipped)" - Audit log: `policy_versions.bulk_pruned` with version IDs + skip reasons 3. **Given** I lack `policy_versions.prune` permission, @@ -299,15 +299,21 @@ ### Policy Versions Resource | Action | Priority | Destructive | Threshold for Queue | Type-to-Confirm | |--------|----------|-------------|---------------------|-----------------| -| Delete | P2 | Yes | ≥20 | ≥20 | +| Prune (archive) | P2 | Yes (local) | ≥20 | ≥20 | +| Restore (unarchive) | P2 | No | ≥20 | No | +| Force delete (permanent) | P2 | Yes (permanent) | ≥20 | ≥20 | | Export to Backup | P3 | No | ≥20 | No | -**FR-005.20**: Bulk Delete for Policy Versions MUST: +**FR-005.20**: Bulk Prune (Archive) for Policy Versions MUST: - Check eligibility: `is_current = false` AND `created_at < NOW() - 90 days` AND NOT referenced - Referenced = exists in `backup_items.policy_version_id` OR `restore_runs.metadata` OR critical audit logs -- Hard-delete eligible versions +- Archive (soft-delete) eligible versions - Skip ineligible with reason: "Referenced", "Too recent", "Current version" +**FR-005.20a**: System MUST provide bulk restore for archived Policy Versions (restore only if archived). + +**FR-005.20b**: System MUST provide bulk force delete for archived Policy Versions (permanent). + **FR-005.21**: System MUST require `policy_versions.prune` permission (separate from `policy_versions.delete`). ### Backup Sets Resource diff --git a/specs/005-bulk-operations/tasks.md b/specs/005-bulk-operations/tasks.md index 9e5e7b8..94bde21 100644 --- a/specs/005-bulk-operations/tasks.md +++ b/specs/005-bulk-operations/tasks.md @@ -98,6 +98,25 @@ ### Implementation for User Story 2 --- +## Phase 4b: Requirement - Bulk Sync Policies (FR-005.19) + +**Goal**: Enable admins to queue a sync (re-fetch) for selected policies in one action. + +**Independent Test**: Select 25 policies → bulk sync → verify job(s) queued and progress/finish notifications. + +### Tests for Bulk Sync Policies + +- [ ] T035a [P] Write feature test for bulk sync dispatch in tests/Feature/BulkSyncPoliciesTest.php +- [ ] T035b [P] Write permission test for bulk sync action in tests/Unit/BulkActionPermissionTest.php + +### Implementation for Bulk Sync Policies + +- [ ] T035c Add bulk sync action to PolicyResource in app/Filament/Resources/PolicyResource.php +- [ ] T035d Dispatch SyncPoliciesJob for selected policies (choose per-ID or batched IDs) in app/Jobs/SyncPoliciesJob.php (or a new dedicated bulk sync job) +- [ ] T035e Manual QA: bulk sync 25 policies (verify queued processing + notifications) + +**Checkpoint**: Bulk sync action queues work and respects permissions + ## Phase 5: User Story 5 - Type-to-Confirm (Priority: P1) **Goal**: Require typing "DELETE" for destructive operations with ≥20 items @@ -147,6 +166,10 @@ ### Implementation for User Story 6 - [ ] T053 [US6] Test circuit breaker with mock failures (manual QA) - [ ] T054 [US6] Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkProgressNotificationTest.php` +- [ ] T054a [US6] Define/verify polling interval meets NFR-005.3 (≤10s updates) and document where configured +- [ ] T054b [US6] Manual QA: force a catastrophic job failure and verify FR-005.13 notification behavior +- [ ] T054c [US6] Manual QA: verify UI remains responsive during a 100-item queued run (NFR-005.4) + **Checkpoint**: Progress tracking working, polling updates UI, circuit breaker aborts high-failure jobs --- @@ -155,7 +178,7 @@ ## Phase 7: User Story 3 - Bulk Delete Policy Versions (Priority: P2) **Goal**: Enable admins to prune old policy versions that are NOT referenced and meet retention threshold (>90 days) -**Independent Test**: Select 30 old versions → bulk prune → verify eligible deleted, ineligible skipped with reasons +**Independent Test**: Select 30 old versions → bulk prune → verify eligible archived, ineligible skipped with reasons ### Tests for User Story 3 @@ -234,6 +257,13 @@ ### Implementation for Additional Resource - [ ] T084 Test delete with 15 backup sets (manual QA) - [ ] T085 Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkDeleteBackupSetsTest.php` +### Additional: Bulk Archive Backup Sets (FR-005.23) + +- [ ] T085a Verify BackupSet has `archived_at` column; add migration if missing in database/migrations/ +- [ ] T085b Add bulk archive action to BackupSetResource in app/Filament/Resources/BackupSetResource.php +- [ ] T085c [P] Write tests for bulk archive in tests/Feature/BulkArchiveBackupSetsTest.php (and unit test if a job/service is introduced) +- [ ] T085d Manual QA: archive 15 backup sets and verify listing/filter behavior + **Checkpoint**: Backup sets bulk delete working, cascade-delete verified ---