# Implementation Plan: Drift MVP (044) **Branch**: `feat/044-drift-mvp` | **Date**: 2026-01-12 | **Spec**: `specs/044-drift-mvp/spec.md` **Input**: Feature specification from `specs/044-drift-mvp/spec.md` ## Summary Introduce a generic, persisted Finding pipeline and implement Drift as the first generator. - Drift compares Inventory Sync Runs for the same selection scope (`scope_key`). - Baseline run = previous successful run for the same scope; comparison run = latest successful run. - Findings are persisted with deterministic fingerprints and support MVP triage (`new` → `acknowledged`). - UI is DB-only for label/name resolution (no render-time Graph calls). ## Technical Context **Language/Version**: PHP 8.4.x **Framework**: Laravel 12 **Admin UI**: Filament v4 + Livewire v3 **Storage**: PostgreSQL (JSONB) **Testing**: Pest v4 **Target Platform**: Docker (Sail-first local), Dokploy container deployments **Project Type**: Laravel monolith **Performance Goals**: - Drift generation happens async (job), with deterministic output - Drift listing remains filterable and index-backed **Constraints**: - Tenant isolation for all reads/writes - No render-time Graph calls; labels resolved from DB caches - Evidence minimization (sanitized allowlist; no raw payload dumps) **Scale/Scope**: - Tenants may have large inventories; findings must be indexed for typical filtering ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first: Drift is derived from Inventory Sync Runs and Inventory Items (“last observed” state). - Read/write separation: Drift generation is analytical; writes are limited to triage acknowledgement and must be audited + tested. - Graph contract path: Drift UI performs no Graph calls; Graph calls remain isolated in existing Inventory/Graph client layers. - Deterministic capabilities: drift scope derives from existing selection hashing and inventory type registries. - Tenant isolation: all reads/writes tenant-scoped; no cross-tenant leakage. - Automation: drift generation is queued; jobs are deduped/locked per scope+run pair and observable. - Data minimization: store only minimized evidence JSON; logs contain no secrets/tokens. ## Project Structure ### Documentation (this feature) ```text specs/044-drift-mvp/ ├── plan.md # This file (/speckit.plan output) ├── research.md # Phase 0 output ├── data-model.md # Phase 1 output ├── quickstart.md # Phase 1 output ├── contracts/ # Phase 1 output │ └── admin-findings.openapi.yaml └── tasks.md # Phase 2 output (/speckit.tasks) ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ ├── Pages/ │ │ └── DriftLanding.php # drift landing page (summary + generation status) │ └── Resources/ │ └── FindingResource/ # list/detail + acknowledge action (tenant-scoped) ├── Jobs/ │ └── GenerateDriftFindingsJob.php # async generator (on-demand) ├── Models/ │ └── Finding.php # generic finding model └── Services/ └── Drift/ ├── DriftFindingGenerator.php # computes deterministic findings for baseline/current ├── DriftHasher.php # baseline_hash/current_hash helpers └── DriftScopeKey.php # scope_key is InventorySyncRun.selection_hash (single canonical definition) database/migrations/ └── 2026_.._.._create_findings_table.php tests/Feature/Drift/ ├── DriftGenerationDeterminismTest.php ├── DriftTenantIsolationTest.php └── DriftAcknowledgeTest.php ``` **Structure Decision**: Laravel monolith using Filament pages/resources and queued jobs. ## Complexity Tracking > **Fill ONLY if Constitution Check has violations that must be justified** | Violation | Why Needed | Simpler Alternative Rejected Because | |-----------|------------|-------------------------------------| | (none) | | | ## Phase 0 Output (Research) Completed in `specs/044-drift-mvp/research.md`. ## Phase 1 Output (Design) Completed in: - `specs/044-drift-mvp/data-model.md` - `specs/044-drift-mvp/contracts/` - `specs/044-drift-mvp/quickstart.md` ## Phase 2 Planning Notes Next step is expanding `specs/044-drift-mvp/tasks.md` (via `/speckit.tasks`) with phased, test-first implementation tasks.