## Summary - add baseline compare evidence gap detail modeling and a dedicated Livewire table surface - extend baseline compare landing and operation run detail surfaces to expose evidence gap details and stats - add spec artifacts for feature 162 and expand feature coverage with focused Filament and baseline tests ## Notes - branch: `162-baseline-gap-details` - commit: `a92dd812` - working tree was clean after push ## Validation - tests were not run in this step Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #192
5.0 KiB
5.0 KiB
Data Model: Enterprise Evidence Gap Details for Baseline Compare
Overview
This feature does not introduce new database tables. It extends the tenant-owned OperationRun JSONB context for baseline_compare runs and defines a derived operator-facing row model for evidence-gap detail rendering.
Entity: OperationRun
- Ownership: Tenant-owned operational artifact with
workspace_idandtenant_id - Storage: Existing
operation_runstable - Relevant relationships:
- Belongs to
Tenant - Belongs to
Workspace - Belongs to initiating
User
- Belongs to
- Relevant invariant:
statusandoutcomeremain service-owned throughOperationRunServicecontextmay be enriched by the compare job without changing lifecycle semantics
Subdocument: baseline_compare
Stored under OperationRun.context['baseline_compare'].
Fields
| Field | Type | Required | Description |
|---|---|---|---|
inventory_sync_run_id |
integer | no | Source inventory sync run used for coverage and freshness context |
subjects_total |
integer | no | Total compare subjects considered for the run |
evidence_capture |
object | no | Capture stats such as requested, succeeded, skipped, failed, throttled |
coverage |
object | no | Coverage proof and covered/uncovered policy types |
fidelity |
string | no | Compare fidelity, typically meta or content |
reason_code |
string | no | Top-level compare reason code used by the explanation layer |
resume_token |
string or null | no | Resume state for incomplete content capture |
evidence_gaps |
object | no | Aggregate and subject-level evidence-gap contract |
Subdocument: baseline_compare.evidence_gaps
Fields
| Field | Type | Required | Description |
|---|---|---|---|
count |
integer | no | Total evidence-gap count across all reasons |
by_reason |
object<string,int> | no | Aggregate counts keyed by evidence-gap reason code |
subjects |
object<string,list> | no | Bounded reason-grouped list of concrete subject keys |
Validation Rules
countmust be a non-negative integer.- Each
by_reasonvalue must be a non-negative integer. - Each
subjectskey must be a non-empty reason code string. - Each
subjects[reason]list item must be a non-empty string inpolicy_type|subject_keyformat. - Subject lists are deduplicated per reason.
- Subject lists are capped at the compare job limit, currently 50 items per reason.
Derived Entity: EvidenceGapDetailRow
This is not stored separately. It is derived from baseline_compare.evidence_gaps.subjects for rendering and filtering.
Fields
| Field | Type | Source | Description |
|---|---|---|---|
reason_code |
string | map key | Stable reason identifier such as ambiguous_match or policy_not_found |
reason_label |
string | derived | Operator-facing label from reason_code |
policy_type |
string | parsed from subject string | Policy family segment before the first pipe |
subject_key |
string | parsed from subject string | Subject identity segment after the first pipe |
search_text |
string | derived | Lowercased concatenation of reason, policy type, and subject key for local filtering |
Validation Rules
policy_typemust be non-empty.subject_keymay be human-readable text, GUID-like values, or workspace-safe identifiers, but must be non-empty once persisted.search_textmust be deterministic and derived only from persisted row values.
Derived Entity: EvidenceGapReasonBucket
Groups detail rows for rendering.
Fields
| Field | Type | Description |
|---|---|---|
reason_code |
string | Stable bucket key |
reason_label |
string | Operator-facing label |
count |
integer | Number of visible persisted subjects in the bucket |
rows |
list | Rows shown for the reason |
State Model
Run detail evidence-gap states
-
NoGapsevidence_gaps.countis absent or0- No evidence-gap detail section is required
-
GapsWithRecordedSubjectsevidence_gaps.count > 0evidence_gaps.subjectsexists with at least one non-empty reason bucket- Render searchable grouped rows
-
GapsWithoutRecordedSubjectsevidence_gaps.count > 0evidence_gaps.subjectsis absent or empty- Render explicit fallback copy indicating detail was not recorded for that run
Example Payload
{
"baseline_compare": {
"subjects_total": 50,
"fidelity": "meta",
"reason_code": "evidence_capture_incomplete",
"evidence_capture": {
"requested": 50,
"succeeded": 47,
"skipped": 0,
"failed": 3,
"throttled": 0
},
"evidence_gaps": {
"count": 5,
"by_reason": {
"ambiguous_match": 3,
"policy_not_found": 2
},
"subjects": {
"ambiguous_match": [
"deviceConfiguration|WiFi-Corp-Profile",
"deviceConfiguration|VPN-Always-On"
],
"policy_not_found": [
"deviceConfiguration|Deleted-Policy-ABC"
]
}
}
}
}