TenantAtlas/specs/117-baseline-drift-engine/plan.md
ahmido f08924525d Spec 117: Baseline Drift Engine + evidence fidelity/provenance (#142)
Implements Spec 117 (Golden Master Baseline Drift Engine):

- Adds provider-chain resolver for current state hashes (content evidence via PolicyVersion, meta evidence via inventory)
- Updates baseline capture + compare jobs to use resolver and persist provenance + fidelity
- Adds evidence_fidelity column/index + Filament UI badge/filter/provenance display for findings
- Adds performance guard test + integration tests for drift, fidelity semantics, provenance, filter behavior
- UX fix: Policies list shows "Sync from Intune" header action only when records exist; empty-state CTA remains and is functional

Tests:
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/PolicySyncCtaPlacementTest.php`
- `vendor/bin/sail artisan test --compact --filter=Baseline`

Checklist:
- specs/117-baseline-drift-engine/checklists/requirements.md ✓

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #142
2026-03-03 07:23:01 +00:00

6.5 KiB
Raw Permalink Blame History

Implementation Plan: Golden Master Baseline Drift — Deep Settings Drift via Provider Chain

Branch: 117-baseline-drift-engine | Date: 2026-03-02 | Spec: specs/117-baseline-drift-engine/spec.md

Summary

Implement a single, batch-oriented “current state hash resolver” for Golden Master baseline capture + compare.

  • For each tenant subject, resolve best available evidence via provider chain (content via PolicyVersion since baseline snapshot captured time; else meta via Inventory meta contract).
  • Compare baseline snapshot item hash vs current resolved hash to emit drift findings.
  • Findings store + display baseline and current evidence provenance (fidelity, source, observed timestamp for each side) and add a fidelity badge + filter.
  • Compare remains read-only (no new external calls during compare) and continues to run via OperationRun.

Technical Context

Language/Version: PHP 8.4 (Laravel 12) Primary Dependencies: Filament v5, Livewire v4, Pest v4 Storage: PostgreSQL (Sail) Testing: Pest (vendor/bin/sail artisan test --compact) Target Platform: Docker containers (Laravel Sail) Project Type: Web application (Laravel + Filament) Performance Goals: Baseline scope ~500 subjects resolves + compares within ~2 minutes (staging target from spec) Constraints:

  • v1.5 compare MUST NOT initiate any upstream/Graph calls; DB-only + existing stored evidence only.
  • Batch resolution (no per-subject query loops; chunk + set-based queries).
  • Baseline snapshot items MUST NOT persist tenant identifiers. Scale/Scope: Per-run: 0500+ subjects; per-tenant: multiple policy types; mixed evidence fidelity expected.

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

  • Inventory-first: PASS — “meta evidence” comes from inventory_items (last observed); snapshot items remain immutable standards.
  • Read/write separation: PASS — compare/capture are operational runs; no new write surfaces; findings are operational artifacts.
  • Graph contract path: PASS — v1.5 compare uses only local DB evidence (no Graph calls).
  • Deterministic capabilities: PASS — no new capabilities introduced.
  • RBAC-UX / workspace+tenant isolation: PASS — use existing tenant-context Filament routes; non-members 404; members lacking capability 403.
  • Run observability: PASS — both capture + compare are queued OperationRuns using OperationRunService.
  • Ops-UX 3-surface feedback: PASS — existing run-start surfaces already enqueue; run detail is canonical.
  • Ops-UX summary counts: PASS — any new detail stays in context; summary keys remain from OperationSummaryKeys::all().
  • Badge semantics: PASS — new badges/filters will follow existing UI patterns (no ad-hoc status mappings).
  • Filament action surface contract: PASS — modifying Finding list UI adds filter + badge only; no new destructive actions.

Project Structure

Documentation (this feature)

specs/117-baseline-drift-engine/
├── spec.md
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
└── contracts/
   └── openapi.yaml

Next: generate specs/117-baseline-drift-engine/tasks.md via /speckit.tasks.

Source Code (repository root)

app/
├── Jobs/
│   ├── CaptureBaselineSnapshotJob.php
│   └── CompareBaselineToTenantJob.php
├── Models/
│   ├── BaselineSnapshot.php
│   ├── BaselineSnapshotItem.php
│   ├── InventoryItem.php
│   ├── Policy.php
│   ├── PolicyVersion.php
│   └── Finding.php
├── Services/
│   ├── Baselines/
│   │   ├── BaselineCompareService.php
│   │   ├── BaselineSnapshotIdentity.php
│   │   └── (new) CurrentStateHashResolver + providers
│   └── Drift/
│       ├── DriftHasher.php
│       └── Normalizers/SettingsNormalizer.php
└── Filament/
    ├── Pages/BaselineCompareLanding.php
    └── Resources/FindingResource.php

database/migrations/
└── (new) add evidence_fidelity to findings (required for filtering)

tests/
└── Feature/ (new/updated Pest tests for resolver + compare + UI filter)

Structure Decision: Implement as an incremental change within existing Baselines/Findings domains (no new modules).

Complexity Tracking

No constitution violations are required for v1.5. (Table intentionally empty.)

Phase 0 — Research (output: research.md)

Goals:

  • Confirm current baseline capture/compare logic and identify the precise extension points.
  • Decide where fidelity/provenance should be stored (JSONB vs columns) to support filtering.
  • Confirm real route URIs/names for contracts (Filament + Monitoring).

Deliverable: specs/117-baseline-drift-engine/research.md

Phase 1 — Design (output: data-model.md + contracts/* + quickstart.md)

Deliverables:

Post-design constitution re-check: PASS (see Phase 1 notes in research/design outputs).

Phase 2 — Implementation Planning (high-level)

  1. Implement CurrentStateHashResolver (provider chain + batch resolution).
  2. Update baseline capture to store best available hash (content if present, else meta) + provenance.
  3. Update baseline compare to:
    • use resolver with since = baseline_snapshots.captured_at
    • record evidence gaps in run context
    • emit findings with baseline+current provenance
  4. Update Findings UI:
    • show fidelity badge
    • add fidelity filter (content/meta)
    • display baseline+current provenance fields
  5. Add migration for findings.evidence_fidelity (required for fast, stable fidelity filtering).
  6. Add Pest tests (resolver behavior, compare integration, UI filter query behavior).
  7. Run vendor/bin/sail bin pint --dirty --format agent and focused tests.

Scope note (v2.0)

  • v2.0 “full content capture mode for Golden Master” is explicitly out of scope for v1.5 implementation tasks.
  • v1.5 remains opportunistic: compare is DB-only and consumes only existing stored evidence.