Implements Spec 115 (Baseline Operability & Alert Integration). Key changes - Baseline compare: safe auto-close of stale baseline findings (gated on successful/complete compares) - Baseline alerts: `baseline_high_drift` + `baseline_compare_failed` with dedupe/cooldown semantics - Workspace settings: baseline severity mapping + minimum severity threshold + auto-close toggle - Baseline Compare UX: shared stats layer + landing/widget consistency Notes - Livewire v4 / Filament v5 compatible. - Destructive-like actions require confirmation (no new destructive actions added here). Tests - `vendor/bin/sail artisan test --compact tests/Feature/Baselines/ tests/Feature/Alerts/` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #140
2.8 KiB
2.8 KiB
Data Model — Baseline Operability & Alert Integration (Spec 115)
This spec extends existing models and introduces no new tables.
Entities
1) Finding (existing: App\Models\Finding)
Baseline compare findings are a subset of drift findings.
Key fields used/extended by this feature:
workspace_id(derived from tenant)tenant_idfinding_type=driftsource=baseline.compare(stable contract)scope_key=baseline_profile:{baseline_profile_id}(stable grouping)fingerprint(stable identifier; used for idempotent upsert + alert dedupe)status(lifecycle):new,reopened, other open states, and terminal statesreopened_at,resolved_at,resolved_reasonseverity(low|medium|high|critical)evidence_jsonb(must include at leastchange_type)current_operation_run_id(the compare run that most recently observed the finding)
Lifecycle rules for baseline compare findings:
- New fingerprint → create finding with
status=new. - Existing finding in terminal state (at least
resolved) observed again → setstatus=reopened,reopened_at=now, clear resolved fields. - Existing open finding observed again → do not override workflow status.
- Stale open findings (not observed in a fully successful compare) → set
status=resolved,resolved_reason=no_longer_drifting,resolved_at=now.
2) OperationRun (existing: App\Models\OperationRun)
Baseline compare runs are represented as:
type = baseline_comparetenant_idrequired (tenant-scoped operation)status/outcomemanaged exclusively viaOperationRunServicesummary_countsused for:- completeness:
processed == total - safety:
failed == 0
- completeness:
Baseline capture runs are represented as:
type = baseline_capture
3) WorkspaceSetting (existing: App\Models\WorkspaceSetting)
New workspace keys (domain baseline):
baseline.severity_mapping(json object)- Keys MUST be exactly:
missing_policy,different_version,unexpected_policy - Values MUST be one of:
low|medium|high|critical
- Keys MUST be exactly:
baseline.alert_min_severity(string)- Allowed:
low|medium|high|critical - Default:
high
- Allowed:
baseline.auto_close_enabled(bool)- Default:
true
- Default:
Effective value rules:
- Consumers read via
SettingsResolver, which merges system defaults with workspace overrides.
Derived/Computed Values
- Baseline finding severity is computed at creation time from
baseline.severity_mapping[change_type]. - Baseline alert eligibility is computed at alert-evaluation time from:
- finding
source+status+ timestamps vswindowStart - finding
severityvsbaseline.alert_min_severity
- finding
Invariants
Finding.source = baseline.compareMUST be stable and queryable.- Auto-close MUST only execute if the compare run is complete (
processed==total) and safe (failed==0) andbaseline.auto_close_enabledis true.