Data Model: Structured Snapshot Rendering & Type-Agnostic Item Browser
Feature: 130-structured-snapshot-rendering | Date: 2026-03-09
Overview
This feature introduces no database schema changes. It adds a normalized read model over existing workspace-owned baseline snapshot records so the snapshot detail page can render every captured policy type through a shared summary and grouped-browser abstraction.
The design relies on:
- existing persistent snapshot records,
- existing persistent snapshot-item records,
- a new normalized page presentation model,
- renderer-specific enrichment layered on top of a shared fallback contract.
Existing Persistent Entities
BaselineSnapshot
| Attribute |
Type |
Notes |
id |
int |
Snapshot identity shown on the page |
workspace_id |
int |
Workspace isolation boundary |
baseline_profile_id |
int |
Source baseline profile reference |
summary_jsonb |
array/jsonb |
Snapshot-level counts, fidelity, policy-type totals, and gap summaries |
snapshot_identity_hash |
string |
Stable snapshot fingerprint shown as technical metadata |
captured_at |
datetime |
Snapshot capture timestamp |
Relationships:
- belongs to
Workspace
- belongs to
BaselineProfile
- has many
BaselineSnapshotItem
Usage rules:
- The snapshot is immutable and read-only in this feature.
- Snapshot detail can render only within the active workspace scope.
summary_jsonb remains the page’s aggregation source but not the primary raw UI payload.
BaselineSnapshotItem
| Attribute |
Type |
Notes |
id |
int |
Item identity for rendering and ordering |
baseline_snapshot_id |
int |
Parent snapshot reference |
policy_type |
string |
Primary grouping key for the browser |
subject_type |
string |
Stable subject class hint, typically policy |
subject_key |
string |
Stable identity hint for operator inspection |
subject_external_id |
string |
Workspace-safe external identity hint |
baseline_hash |
string |
Captured evidence hash |
meta_jsonb |
array/jsonb |
Best-available display, evidence, version-reference, and optional type-specific metadata |
Usage rules:
- Items are grouped by
policy_type for summary and browser rendering.
- Items must remain visible even when type-specific enrichment is unavailable.
meta_jsonb is the canonical source for fallback rendering.
BaselineProfile
| Attribute |
Type |
Notes |
id |
int |
Reference-only profile link |
workspace_id |
int |
Workspace ownership boundary |
name |
string |
Profile label shown in snapshot metadata |
Usage rules:
- Used only as metadata context in this feature.
- No baseline-profile lifecycle changes are introduced.
Existing Snapshot Metadata Shape
Snapshot summary payload
summary_jsonb is expected to provide enough information for snapshot-level aggregation:
| Key |
Type |
Purpose |
total_items |
int |
Total item count for snapshot-level overview |
policy_type_counts |
map<string,int> |
Count by policy type for summary rows |
fidelity_counts |
object |
Aggregate fidelity counts already tracked at snapshot level |
gaps |
object |
Aggregate gap count and by-reason summaries |
Snapshot item metadata payload
meta_jsonb is expected to provide enough information for the minimum rendering contract:
| Key |
Type |
Purpose |
display_name |
string nullable |
Best available item label |
category |
string nullable |
Optional contextual attribute |
platform |
string nullable |
Optional contextual attribute |
evidence.fidelity |
string |
Item-level fidelity source |
evidence.source |
string |
Capture or reference provenance |
evidence.observed_at |
date-time nullable |
Best available observed timestamp |
identity.strategy |
string nullable |
Identity interpretation hint |
version_reference.policy_version_id |
int nullable |
Source reference hint |
version_reference.capture_purpose |
string nullable |
Optional provenance hint |
rbac.* |
type-specific object |
Optional RBAC enrichment fields |
New Computed Read Models
RenderedSnapshot
Page-level presentation model built from one snapshot and its items.
| Field |
Type |
Description |
snapshot |
SnapshotMeta |
Top-of-page metadata summary |
summaryRows |
list |
One row per policy type |
groups |
list |
Grouped item browser content |
technicalDetail |
RenderedTechnicalDetail |
Secondary disclosure payload |
hasItems |
bool |
Empty-state signal |
SnapshotMeta
| Field |
Type |
Description |
snapshotId |
int |
Visible snapshot identifier |
baselineProfileName |
string nullable |
Visible baseline label |
capturedAt |
date-time nullable |
Capture timestamp |
snapshotIdentityHash |
string nullable |
Technical identity hint |
overallFidelity |
FidelityState |
Overall fidelity status for the page |
overallGapCount |
int |
Total known gaps |
RenderedSnapshotSummaryRow
| Field |
Type |
Description |
policyType |
string |
Canonical type key |
label |
string |
Human-readable type label |
itemCount |
int |
Number of items in this group |
fidelity |
FidelityState |
Group-level fidelity summary |
gapCount |
int |
Group-level gap count |
capturedAt |
date-time nullable |
Most relevant timing summary for the group |
coverageHint |
string nullable |
Optional summary hint |
RenderedSnapshotGroup
| Field |
Type |
Description |
policyType |
string |
Canonical type key |
label |
string |
Group heading |
itemCount |
int |
Count shown in group header |
fidelity |
FidelityState |
Group-level fidelity badge state |
gapSummary |
GapSummary |
Group-level degraded-state explanation |
initiallyCollapsed |
bool |
Default UI state |
items |
list |
Visible item rows |
renderingError |
string nullable |
Per-group error message when renderer fails |
RenderedSnapshotItem
| Field |
Type |
Description |
label |
string |
Best available human-readable title |
typeLabel |
string |
Human-readable policy type label |
identityHint |
string |
Stable inspection identity |
referenceStatus |
string |
Capture or reference status label |
fidelity |
FidelityState |
Item-level fidelity state |
gapSummary |
GapSummary |
Item-level degraded-state summary |
observedAt |
date-time nullable |
Best available timestamp |
sourceReference |
string nullable |
PolicyVersion or equivalent reference hint |
structuredAttributes |
list |
Shared and type-specific key-value attributes |
RenderedAttribute
| Field |
Type |
Description |
label |
string |
Operator-readable field label |
value |
scalar or string |
Display value |
priority |
string enum |
primary or secondary |
FidelityState
| Value |
Meaning |
full |
Structured rendering is complete and content-backed |
partial |
Structured rendering exists but some expected detail is missing |
reference_only |
Rendering is based on metadata or reference-only evidence |
unsupported |
Only the minimum fallback path is available |
GapSummary
| Field |
Type |
Description |
count |
int |
Number of known gaps |
hasGaps |
bool |
Shortcut for UI conditions |
messages |
list |
Human-readable explanations or translated reason labels |
RenderedTechnicalDetail
| Field |
Type |
Description |
defaultCollapsed |
bool |
Always true for initial render |
summaryPayload |
array |
Raw summary payload for debugging |
groupPayloads |
map<string,mixed> |
Optional renderer debug payloads where safe |
Relationships and Aggregation Rules
Snapshot to group aggregation
BaselineSnapshot
-> many BaselineSnapshotItem
-> grouped by policy_type
-> one RenderedSnapshotSummaryRow per group
-> one RenderedSnapshotGroup per group
Group derivation rules
policy_type group
-> item count = number of items in the group
-> fidelity = worst effective fidelity across item set or unsupported if fallback only
-> gap count = derived from item gaps plus any renderer-level degraded-state signals
-> captured/observed timing = most relevant available timing summary
Renderer resolution rules
Known supported type with specific renderer
-> render shared item contract + type-specific enrichments
Known type with no specific renderer
-> fallback renderer
Unknown type
-> fallback renderer
Specific renderer throws or returns invalid data
-> group-level rendering error + fallback group shell
Validation Rules
| Rule |
Result |
| Every captured policy type yields a summary row |
Required |
| Every captured policy type yields a grouped browser section |
Required |
| Every item yields at least the minimum rendering contract |
Required |
| Unknown types never disappear from the page |
Required |
| Technical payload is secondary and collapsed by default |
Required |
| One renderer failure cannot break the rest of the snapshot page |
Required |
Schema Impact
No schema migration is expected for this feature.