TenantAtlas/specs/044-drift-mvp/tasks.md
ahmido a449ecec5b feat/044-drift-mvp (#58)
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)
2026-01-14 23:16:10 +00:00

9.5 KiB

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.

  • T001 Create/update constitution gate checklist in specs/044-drift-mvp/checklists/requirements.md
  • 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}
  • T003 Add Drift landing page shell in app/Filament/Pages/DriftLanding.php
  • 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.

  • 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)
  • T006 Create Finding model in app/Models/Finding.php (casts for evidence_jsonb, enums/constants for finding_type/severity/status, acknowledged_at handling)
  • T007 [P] Add FindingFactory in database/factories/FindingFactory.php
  • T008 Ensure InventorySyncRunFactory exists (or add it) in database/factories/InventorySyncRunFactory.php
  • T009 Add authorization policy in app/Policies/FindingPolicy.php and wire it in app/Providers/AuthServiceProvider.php (or project equivalent)
  • T010 Add Drift permissions in config/intune_permissions.php (view + acknowledge) and wire them into Filament navigation/actions
  • T011 Enforce tenant scoping for Finding queries in app/Models/Finding.php and/or app/Filament/Resources/FindingResource.php
  • T012 Implement fingerprint helper in app/Services/Drift/DriftHasher.php (sha256 per spec)
  • T013 Pin scope_key = InventorySyncRun.selection_hash in app/Services/Drift/DriftScopeKey.php (single canonical definition)
  • 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)

  • T015 [P] [US1] Baseline selection tests in tests/Feature/Drift/DriftBaselineSelectionTest.php
  • T016 [P] [US1] Generation dispatch tests in tests/Feature/Drift/DriftGenerationDispatchTest.php
  • T017 [P] [US1] Tenant isolation tests in tests/Feature/Drift/DriftTenantIsolationTest.php
  • T018 [P] [US1] Assignment drift detection test (targets + intent changes per FR2b) in tests/Feature/Drift/DriftAssignmentDriftDetectionTest.php

Implementation

  • T019 [US1] Implement run selection service in app/Services/Drift/DriftRunSelector.php
  • T021 [US1] Implement generator service in app/Services/Drift/DriftFindingGenerator.php (idempotent)
  • T020 [US1] Implement generator job in app/Jobs/GenerateDriftFindingsJob.php (dedupe/lock by tenant+scope+baseline+current)
  • T022 [US1] Implement landing behavior (dispatch + status UI) in app/Filament/Pages/DriftLanding.php
  • 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)

  • T024 [P] [US2] Finding detail test in tests/Feature/Drift/DriftFindingDetailTest.php
  • T025 [P] [US2] Evidence minimization test in tests/Feature/Drift/DriftEvidenceMinimizationTest.php
  • T041 [P] [US2] Finding detail shows normalized settings diff (DB-only) in tests/Feature/Drift/DriftFindingDetailShowsSettingsDiffTest.php
  • T042 [P] [US2] Finding detail shows assignments diff + cached group labels (DB-only) in tests/Feature/Drift/DriftFindingDetailShowsAssignmentsDiffTest.php

Implementation

  • T026 [US2] Implement list UI in app/Filament/Resources/FindingResource.php (filters: status, scope_key, run)
  • T027 [US2] Implement detail UI in app/Filament/Resources/FindingResource/Pages/ViewFinding.php
  • T028 [US2] Implement DB-only name resolution in app/Filament/Resources/FindingResource.php (inventory/foundations caches)
  • 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)

  • T029 [P] [US3] Acknowledge action test in tests/Feature/Drift/DriftAcknowledgeTest.php
  • T030 [P] [US3] Acknowledge authorization test in tests/Feature/Drift/DriftAcknowledgeAuthorizationTest.php

Implementation

  • T031 [US3] Add acknowledge actions in app/Filament/Resources/FindingResource.php
  • T032 [US3] Implement acknowledge() domain method in app/Models/Finding.php
  • 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)

  • T048 [P] [US3] Bulk acknowledge selected test in tests/Feature/Drift/DriftBulkAcknowledgeTest.php
  • T049 [P] [US3] Acknowledge all matching current filters test in tests/Feature/Drift/DriftBulkAcknowledgeAllMatchingTest.php
  • T050 [P] [US3] Acknowledge all matching requires type-to-confirm when >100 in tests/Feature/Drift/DriftBulkAcknowledgeAllMatchingConfirmationTest.php
  • T051 [P] [US3] Bulk acknowledge authorization test in tests/Feature/Drift/DriftBulkAcknowledgeAuthorizationTest.php

Implementation

  • 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

  • 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)
  • T035 [P] Add determinism test in tests/Feature/Drift/DriftGenerationDeterminismTest.php (same baseline/current => same fingerprints)
  • T036 Add job observability logs in app/Jobs/GenerateDriftFindingsJob.php (no secrets)
  • T037 Add idempotency/upsert strategy in app/Services/Drift/DriftFindingGenerator.php
  • T038 Ensure volatile fields excluded from hashing in app/Services/Drift/DriftHasher.php and cover in tests/Feature/Drift/DriftHasherTest.php
  • T039 Validate and update specs/044-drift-mvp/quickstart.md after implementation
  • 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)

  • T044 [P] [US1] Scope-tag drift detection test in tests/Feature/Drift/DriftScopeTagDriftDetectionTest.php
  • T045 [P] [US2] Finding detail shows scope-tags diff (DB-only) in tests/Feature/Drift/DriftFindingDetailShowsScopeTagsDiffTest.php

Implementation

  • T046 [US1] Implement scope-tag drift detection in app/Services/Drift/DriftFindingGenerator.php (deterministic hashing; kind=policy_scope_tags)
  • 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