feat/005-bulk-operations #5

Merged
ahmido merged 25 commits from feat/005-bulk-operations into dev 2025-12-25 13:32:37 +00:00
3 changed files with 45 additions and 9 deletions
Showing only changes of commit e00a00cd11 - Show all commits

View File

@ -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)

View File

@ -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

View File

@ -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
---