Beschreibung Implementiert das Drift MVP Feature (Spec: 044-drift-mvp) mit Fokus auf automatische Drift-Erkennung zwischen Inventory Sync Runs und Bulk-Triage für Findings. Was wurde implementiert? Drift-Erkennung: Vergleicht Policy-Snapshots, Assignments und Scope Tags zwischen Baseline- und Current-Runs. Deterministische Fingerprints verhindern Duplikate. Findings UI: Neue Filament Resource für Findings mit Listen- und Detail-Ansicht. DB-only Diffs (keine Graph-Calls zur Laufzeit). Bulk Acknowledge: "Acknowledge selected" (Bulk-Action auf der Liste) "Acknowledge all matching" (Header-Action, respektiert aktuelle Filter; Type-to-Confirm bei >100 Findings) Scope Tag Fix: Behebt False Positives bei Legacy-Daten ohne scope_tags.ids (inferiert Default-Werte). Authorization: Tenant-isoliert, Rollen-basiert (Owner/Manager/Operator können acknowledge). Tests: Vollständige Pest-Coverage (28 Tests, 347 Assertions) für Drift-Logik, UI und Bulk-Actions. Warum diese Änderungen? Problem: Keine automatisierte Drift-Erkennung; manuelle Triage bei vielen Findings ist mühsam. Lösung: Async Drift-Generierung mit persistenter Findings-Tabelle. Safe Bulk-Tools für Massen-Triage ohne Deletes. Konformität: Folgt AGENTS.md Workflow, Spec-Kit (Tasks + Checklists abgehakt), Laravel/Filament Best Practices. Technische Details Neue Dateien: ~40 (Models, Services, Tests, Views, Migrations) Änderungen: Filament Resources, Jobs, Policies DB: Neue findings Tabelle (JSONB für Evidence, Indexes für Performance) Tests: ./vendor/bin/sail artisan test tests/Feature/Drift --parallel → 28 passed Migration: ./vendor/bin/sail artisan migrate (neue Tabelle + Indexes) Screenshots / Links Spec: spec.md Tasks: tasks.md (alle abgehakt) UI: Findings-Liste mit Bulk-Actions; Detail-View mit Diffs Checklist Tests passieren (parallel + serial) Code formatiert (./vendor/bin/pint --dirty) Migration reversibel Tenant-Isolation enforced No Graph-Calls in Views Authorization checks Spec + Tasks aligned Deployment Notes Neue Migration: create_findings_table Neue Permissions: drift.view, drift.acknowledge Queue-Job: GenerateDriftFindingsJob (async, deduped)
186 lines
9.5 KiB
Markdown
186 lines
9.5 KiB
Markdown
---
|
|
|
|
description: "Task list for feature 044 drift MVP"
|
|
|
|
---
|
|
|
|
# Tasks: Drift MVP (044)
|
|
|
|
**Input**: Design documents from `specs/044-drift-mvp/`
|
|
**Prerequisites**: `plan.md` (required), `spec.md` (required), plus `research.md`, `data-model.md`, `contracts/`, `quickstart.md`
|
|
|
|
**Tests**: REQUIRED (Pest) - feature introduces runtime behavior + new persistence.
|
|
|
|
**Organization**: Tasks are grouped by user story (Scenario 1/2/3 in spec).
|
|
|
|
## Format: `[ID] [P?] [Story] Description`
|
|
|
|
- **[P]**: Can run in parallel (different files, no dependencies)
|
|
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
|
- Include exact file paths in descriptions
|
|
|
|
---
|
|
|
|
## Phase 1: Setup (Shared Infrastructure)
|
|
|
|
**Purpose**: Project wiring for Drift MVP.
|
|
|
|
- [x] T001 Create/update constitution gate checklist in `specs/044-drift-mvp/checklists/requirements.md`
|
|
- [x] T002 Confirm spec/plan artifacts are current in `specs/044-drift-mvp/{plan.md,spec.md,research.md,data-model.md,quickstart.md,contracts/admin-findings.openapi.yaml}`
|
|
- [x] T003 Add Drift landing page shell in `app/Filament/Pages/DriftLanding.php`
|
|
- [x] T004 [P] Add Finding resource shells in `app/Filament/Resources/FindingResource.php` and `app/Filament/Resources/FindingResource/Pages/`
|
|
|
|
---
|
|
|
|
## Phase 2: Foundational (Blocking Prerequisites)
|
|
|
|
**Purpose**: Persistence + authorization + deterministic IDs that all stories depend on.
|
|
|
|
**Checkpoint**: DB schema exists, tenant scoping enforced, and tests can create Finding rows.
|
|
|
|
- [x] T005 Create `findings` migration in `database/migrations/*_create_findings_table.php` with Finding fields aligned to `specs/044-drift-mvp/spec.md`:
|
|
(tenant_id, finding_type, scope_key, baseline_run_id, current_run_id, subject_type, subject_external_id, severity, status, fingerprint unique, evidence_jsonb, acknowledged_at, acknowledged_by_user_id)
|
|
- [x] T006 Create `Finding` model in `app/Models/Finding.php` (casts for `evidence_jsonb`, enums/constants for `finding_type`/`severity`/`status`, `acknowledged_at` handling)
|
|
- [x] T007 [P] Add `FindingFactory` in `database/factories/FindingFactory.php`
|
|
- [x] T008 Ensure `InventorySyncRunFactory` exists (or add it) in `database/factories/InventorySyncRunFactory.php`
|
|
- [x] T009 Add authorization policy in `app/Policies/FindingPolicy.php` and wire it in `app/Providers/AuthServiceProvider.php` (or project equivalent)
|
|
- [x] T010 Add Drift permissions in `config/intune_permissions.php` (view + acknowledge) and wire them into Filament navigation/actions
|
|
- [x] T011 Enforce tenant scoping for Finding queries in `app/Models/Finding.php` and/or `app/Filament/Resources/FindingResource.php`
|
|
- [x] T012 Implement fingerprint helper in `app/Services/Drift/DriftHasher.php` (sha256 per spec)
|
|
- [x] T013 Pin `scope_key = InventorySyncRun.selection_hash` in `app/Services/Drift/DriftScopeKey.php` (single canonical definition)
|
|
- [x] T014 Implement evidence allowlist builder in `app/Services/Drift/DriftEvidence.php` (new file)
|
|
|
|
---
|
|
|
|
## Phase 3: User Story 1 - View drift summary (Priority: P1) MVP
|
|
|
|
**Goal**: Opening Drift generates (async) and displays a summary of new drift findings for the latest scope.
|
|
|
|
**Independent Test**: With 2 successful inventory runs for the same selection hash, opening Drift dispatches generation if missing and then shows summary counts.
|
|
|
|
### Tests (write first)
|
|
|
|
- [x] T015 [P] [US1] Baseline selection tests in `tests/Feature/Drift/DriftBaselineSelectionTest.php`
|
|
- [x] T016 [P] [US1] Generation dispatch tests in `tests/Feature/Drift/DriftGenerationDispatchTest.php`
|
|
- [x] T017 [P] [US1] Tenant isolation tests in `tests/Feature/Drift/DriftTenantIsolationTest.php`
|
|
- [x] T018 [P] [US1] Assignment drift detection test (targets + intent changes per FR2b) in `tests/Feature/Drift/DriftAssignmentDriftDetectionTest.php`
|
|
|
|
### Implementation
|
|
|
|
- [x] T019 [US1] Implement run selection service in `app/Services/Drift/DriftRunSelector.php`
|
|
- [x] T021 [US1] Implement generator service in `app/Services/Drift/DriftFindingGenerator.php` (idempotent)
|
|
- [x] T020 [US1] Implement generator job in `app/Jobs/GenerateDriftFindingsJob.php` (dedupe/lock by tenant+scope+baseline+current)
|
|
- [x] T022 [US1] Implement landing behavior (dispatch + status UI) in `app/Filament/Pages/DriftLanding.php`
|
|
- [x] T023 [US1] Implement summary queries/widgets in `app/Filament/Pages/DriftLanding.php`
|
|
|
|
---
|
|
|
|
## Phase 4: User Story 2 - Drill into a drift finding (Priority: P2)
|
|
|
|
**Goal**: Admin can view a finding and see sanitized evidence + run references (DB-only label resolution).
|
|
|
|
**Independent Test**: A persisted finding renders details without Graph calls.
|
|
|
|
### Tests (write first)
|
|
|
|
- [x] T024 [P] [US2] Finding detail test in `tests/Feature/Drift/DriftFindingDetailTest.php`
|
|
- [x] T025 [P] [US2] Evidence minimization test in `tests/Feature/Drift/DriftEvidenceMinimizationTest.php`
|
|
- [x] T041 [P] [US2] Finding detail shows normalized settings diff (DB-only) in `tests/Feature/Drift/DriftFindingDetailShowsSettingsDiffTest.php`
|
|
- [x] T042 [P] [US2] Finding detail shows assignments diff + cached group labels (DB-only) in `tests/Feature/Drift/DriftFindingDetailShowsAssignmentsDiffTest.php`
|
|
|
|
### Implementation
|
|
|
|
- [x] T026 [US2] Implement list UI in `app/Filament/Resources/FindingResource.php` (filters: status, scope_key, run)
|
|
- [x] T027 [US2] Implement detail UI in `app/Filament/Resources/FindingResource/Pages/ViewFinding.php`
|
|
- [x] T028 [US2] Implement DB-only name resolution in `app/Filament/Resources/FindingResource.php` (inventory/foundations caches)
|
|
- [x] T043 [US2] Add real diffs to Finding detail (settings + assignments) in `app/Filament/Resources/FindingResource.php`, `app/Services/Drift/*`, and `resources/views/filament/infolists/entries/assignments-diff.blade.php`
|
|
|
|
---
|
|
|
|
## Phase 5: User Story 3 - Acknowledge/triage (Priority: P3)
|
|
|
|
**Goal**: Admin can acknowledge findings; new lists hide acknowledged but records remain auditable.
|
|
|
|
**Independent Test**: Acknowledging sets `acknowledged_at` + `acknowledged_by_user_id` and flips status.
|
|
|
|
### Tests (write first)
|
|
|
|
- [x] T029 [P] [US3] Acknowledge action test in `tests/Feature/Drift/DriftAcknowledgeTest.php`
|
|
- [x] T030 [P] [US3] Acknowledge authorization test in `tests/Feature/Drift/DriftAcknowledgeAuthorizationTest.php`
|
|
|
|
### Implementation
|
|
|
|
- [x] T031 [US3] Add acknowledge actions in `app/Filament/Resources/FindingResource.php`
|
|
- [x] T032 [US3] Implement `acknowledge()` domain method in `app/Models/Finding.php`
|
|
- [x] T033 [US3] Ensure Drift summary excludes acknowledged by default in `app/Filament/Pages/DriftLanding.php`
|
|
|
|
### Bulk triage (post-MVP UX)
|
|
|
|
**Goal**: Admin can acknowledge many findings safely and quickly.
|
|
|
|
### Tests (write first)
|
|
|
|
- [x] T048 [P] [US3] Bulk acknowledge selected test in `tests/Feature/Drift/DriftBulkAcknowledgeTest.php`
|
|
- [x] T049 [P] [US3] Acknowledge all matching current filters test in `tests/Feature/Drift/DriftBulkAcknowledgeAllMatchingTest.php`
|
|
- [x] T050 [P] [US3] Acknowledge all matching requires type-to-confirm when >100 in `tests/Feature/Drift/DriftBulkAcknowledgeAllMatchingConfirmationTest.php`
|
|
- [x] T051 [P] [US3] Bulk acknowledge authorization test in `tests/Feature/Drift/DriftBulkAcknowledgeAuthorizationTest.php`
|
|
|
|
### Implementation
|
|
|
|
- [x] T052 [US3] Add bulk triage actions to Findings list in `app/Filament/Resources/FindingResource.php` and `app/Filament/Resources/FindingResource/Pages/ListFindings.php`
|
|
|
|
---
|
|
|
|
## Phase 6: Polish & Cross-Cutting Concerns
|
|
|
|
- [x] T034 Add DB indexes in `database/migrations/*_create_findings_table.php` (tenant_id+status, tenant_id+scope_key, tenant_id+baseline_run_id, tenant_id+current_run_id)
|
|
- [x] T035 [P] Add determinism test in `tests/Feature/Drift/DriftGenerationDeterminismTest.php` (same baseline/current => same fingerprints)
|
|
- [x] T036 Add job observability logs in `app/Jobs/GenerateDriftFindingsJob.php` (no secrets)
|
|
- [x] T037 Add idempotency/upsert strategy in `app/Services/Drift/DriftFindingGenerator.php`
|
|
- [x] T038 Ensure volatile fields excluded from hashing in `app/Services/Drift/DriftHasher.php` and cover in `tests/Feature/Drift/DriftHasherTest.php`
|
|
- [x] T039 Validate and update `specs/044-drift-mvp/quickstart.md` after implementation
|
|
- [x] T040 Fix drift evidence summary shape in `app/Services/Drift/DriftFindingGenerator.php` and cover in `tests/Feature/Drift/DriftPolicySnapshotDriftDetectionTest.php` (snapshot_hash vs assignments_hash)
|
|
|
|
---
|
|
|
|
## Phase 7: Scope Tags Drift (Post-MVP Fix)
|
|
|
|
**Goal**: Detect and display drift caused by `roleScopeTagIds` changes on a policy version.
|
|
|
|
### Tests (write first)
|
|
|
|
- [x] T044 [P] [US1] Scope-tag drift detection test in `tests/Feature/Drift/DriftScopeTagDriftDetectionTest.php`
|
|
- [x] T045 [P] [US2] Finding detail shows scope-tags diff (DB-only) in `tests/Feature/Drift/DriftFindingDetailShowsScopeTagsDiffTest.php`
|
|
|
|
### Implementation
|
|
|
|
- [x] T046 [US1] Implement scope-tag drift detection in `app/Services/Drift/DriftFindingGenerator.php` (deterministic hashing; kind=`policy_scope_tags`)
|
|
- [x] T047 [US2] Implement scope-tags diff builder + UI in `app/Services/Drift/DriftFindingDiffBuilder.php`, `app/Filament/Resources/FindingResource.php`, and `resources/views/filament/infolists/entries/scope-tags-diff.blade.php`
|
|
|
|
---
|
|
|
|
## Dependencies & Execution Order
|
|
|
|
- Setup (Phase 1) -> Foundational (Phase 2) -> US1 -> US2 -> US3 -> Polish
|
|
|
|
### Parallel execution examples
|
|
|
|
- Foundational: T007, T008, T012, T013, T014
|
|
- US1 tests: T015, T016, T017, T018
|
|
- US2 tests: T024, T025
|
|
- US3 tests: T029, T030
|
|
|
|
---
|
|
|
|
## Implementation Strategy
|
|
|
|
### MVP scope
|
|
|
|
- MVP = Phase 1 + Phase 2 + US1.
|
|
|
|
### Format validation
|
|
|
|
- All tasks use `- [ ] T###` format
|
|
- Story tasks include `[US1]`/`[US2]`/`[US3]`
|
|
- All tasks include file paths
|