Implements Spec 116 baseline drift engine v1 (meta fidelity) with coverage guard, stable finding identity, and Filament UI surfaces. Highlights - Baseline capture/compare jobs and supporting services (meta contract hashing via InventoryMetaContract + DriftHasher) - Coverage proof parsing + compare partial outcome behavior - Filament pages/resources/widgets for baseline compare + drift landing improvements - Pest tests for capture/compare/coverage guard and UI start surfaces - Research report: docs/research/golden-master-baseline-drift-deep-analysis.md Validation - `vendor/bin/sail bin pint --dirty` - `vendor/bin/sail artisan test --compact --filter="Baseline"` Notes - No destructive user actions added; compare/capture remain queued jobs. - Provider registration unchanged (Laravel 11+/12 uses bootstrap/providers.php for panel providers; not touched here). Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #141
4.3 KiB
Phase 1 — Data Model (Baseline Drift Engine)
This document identifies the data/entities involved in Spec 116 and the minimal schema/config changes needed to implement it in this repository.
Existing Entities (Confirmed)
BaselineProfile
Represents a baseline definition.
- Fields (confirmed in migrations):
id,workspace_id,name,description,version_label,status,scope_jsonb(jsonb),active_snapshot_id,created_by_user_id, timestamps - Relationships: has many snapshots; assigned to tenants via
BaselineTenantAssignment
BaselineSnapshot
Immutable capture of baseline state at a point in time.
- Fields (confirmed in migrations):
id,workspace_id,baseline_profile_id,snapshot_identity_hash,captured_at,summary_jsonb(jsonb), timestamps - Relationships: has many items; belongs to baseline profile
BaselineSnapshotItem
One item in a baseline snapshot.
- Fields (confirmed in migrations):
id,baseline_snapshot_idsubject_typesubject_external_idpolicy_typebaseline_hash(string)meta_jsonb(jsonb)- timestamps
Finding
Generic drift finding storage.
- Fields (confirmed by usage):
tenant_id,fingerprint(unique with tenant),recurrence_key(nullable),scope_key, lifecycle fields (first_seen_at,last_seen_at,times_seen), evidence (jsonb)
OperationRun
Tracks long-running operations.
- Fields (by convention):
type,status/outcome,summary_counts(numeric map),context(jsonb)
New / Adjusted Data Requirements
1) Inventory sync coverage context
Goal: Baseline compare must know which policy types were actually processed successfully by inventory sync.
Where: operation_runs.context for the latest inventory sync run.
Shape (proposed):
{
"inventory": {
"coverage": {
"policy_types": {
"deviceConfigurations": {"status": "succeeded", "item_count": 123},
"compliancePolicies": {"status": "failed", "error": "..."}
},
"foundation_types": {
"securityBaselines": {"status": "succeeded", "item_count": 4}
}
}
}
}
Notes:
- Only
summary_countsmust remain numeric; detailed coverage lists live incontext. - For Spec 116 v1, it’s sufficient to store
policy_typescoverage; addingfoundation_typescoverage at the same time keeps parity with scope rules.
2) Baseline scope schema
Goal: Support both policy and foundation scope with correct defaults.
Current: policy_types only.
Target:
{
"policy_types": ["deviceConfigurations", "compliancePolicies"],
"foundation_types": ["securityBaselines"]
}
Default semantics:
- Empty
policy_typesmeans “all supported policy types excluding foundations”. - Empty
foundation_typesmeans “none”.
3) Findings recurrence strategy
Goal: Stable identity per snapshot and per subject.
findings.recurrence_key: populated for baseline compare findings.findings.fingerprint: set to the same recurrence key (to satisfy existing uniqueness constraint).
Recurrence key inputs:
tenant_idbaseline_snapshot_idpolicy_typesubject_external_idchange_type
Grouping (scope_key):
- Keep
findings.scope_key = baseline_profile:{baselineProfileId}for baseline compare findings.
4) Inventory meta contract
Goal: Explicitly define what is hashed for v1 comparisons.
- Implemented as a dedicated builder class (no schema change required).
- Used by baseline capture to compute
baseline_hashand by compare to computecurrent_hash. - Persist the exact contract payload used for hashing to
baseline_snapshot_items.meta_jsonb.meta_contract(versioned) for auditability/reproducibility.
Potential Migrations (Likely)
- If
baseline_profiles.scopeis not jsonb or does not include foundation types → migration to adjust structure (jsonb stays the same, but add support in code; DB change may be optional). - If coverage context needs persistence beyond operation run context → avoid adding tables unless proven necessary; context-based is sufficient for v1.
Index / Performance Notes
- Findings queries commonly filter by
tenant_id+scope_key; ensure there is an index on(tenant_id, scope_key). - Baseline snapshot items must be efficiently loaded by
(baseline_snapshot_id, policy_type).