8.1 KiB
Data Model: Governance Artifact Truthful Outcomes & Fidelity Semantics
Overview
This feature introduces a shared read-model for operator-facing artifact truth across existing governance artifacts. The first slice does not require a new primary table. Instead, it standardizes how existing persisted artifact records are projected into one truth envelope.
Entities
ArtifactTruthEnvelope
Operator-facing read model derived from one governance artifact or artifact-targeted run.
Fields:
artifactFamily(enum):baseline_snapshot,evidence_snapshot,tenant_review,review_pack,artifact_runartifactKey(string): stable identifier in the form{family}:{id}workspaceId(int)tenantId(int|null):nullfor workspace-owned baseline snapshots and workspace-level runsexecutionOutcome(enum|null):pending,succeeded,partially_succeeded,blocked,failedartifactExistence(enum):not_created,historical_only,created,created_but_not_usablecontentState(enum):trusted,partial,missing_input,metadata_only,reference_only,empty,unsupportedfreshnessState(enum):current,stale,unknownpublicationReadiness(enum|null):not_applicable,internal_only,publishable,blockedsupportState(enum):normal,limited_supportactionability(enum):none,optional,requiredprimaryReasonCode(string|null)primaryLabel(string): top-level operator-facing state summaryprimaryExplanation(string|null): concise explanation of the main degraded dimensiondiagnosticLabel(string|null): renderer or implementation-oriented label shown only secondarilynextActionLabel(string|null)nextActionUrl(string|null)relatedRunId(int|null)relatedArtifactUrl(string|null)
Validation rules:
artifactExistence = not_createdMUST NOT coexist withcontentState = trusted.publicationReadinessMAY be non-null only for review and review-pack families.supportState = limited_supportMUST NOT be used as the primary failure dimension if another truth dimension explains operator impact.actionability = requiredMUST include eithernextActionLabelor a stable reason explanation.
ArtifactTruthDimension
Normalized dimension entry for badges, helper text, summaries, and canonical filter values.
Fields:
axis(enum):execution_outcome,artifact_existence,content_fidelity,data_freshness,publication_readiness,support_maturity,operator_actionabilitystate(string)label(string)classification(enum):primary,secondary,diagnosticbadgeDomain(string|null)badgeState(string|null)
Validation rules:
- At most one
primarydimension may drive the top-level alert state at a time. - Diagnostic dimensions MUST still be preserved for detail pages even when not rendered on list pages.
ArtifactTruthCause
Stable explanation payload for degraded states.
Fields:
reasonCode(string|null)translationArtifact(string|null):provider_reason_codes,execution_denial_reason_code,tenant_operability_reason_code,rbac_reason, or a bounded baseline/review artifactoperatorLabel(string|null)shortExplanation(string|null)diagnosticCode(string|null)nextSteps(list)
Validation rules:
- If
reasonCodeis translated,operatorLabelSHOULD come from the centralized translator. - Unknown codes MAY fall back to persisted message text, but raw codes remain diagnostics-only.
Source Projections
BaselineSnapshotProjection
Existing workspace-owned source record: BaselineSnapshot.
Source fields used:
id,workspace_id,captured_atsummary_jsonb.fidelity_countssummary_jsonb.gaps- derived fidelity from
FidelityState::fromSummary(...)
Derived truth rules:
- Full artifact trust requires usable captured content and no misleading gap interpretation.
unsupportedfidelity remains diagnostic-only unless it also implies that no trustworthy comparison artifact exists.- Zero-subject or unusable-upstream cases should be explained from related run context where available.
EvidenceSnapshotProjection
Existing tenant-owned source record: EvidenceSnapshot.
Source fields used:
id,workspace_id,tenant_id,status,completeness_state,generated_at,expires_atsummary.missing_dimensions,summary.stale_dimensions- child
items.state,items.source_kind,items.freshness_at operation_run_id
Derived truth rules:
statusmodels lifecycle;completeness_statemodels coverage/freshness and must not be collapsed into lifecycle.missing_dimensions > 0indicates incomplete coverage, not run failure.stale_dimensions > 0indicates freshness follow-up, not absence.
TenantReviewProjection
Existing tenant-owned source record: TenantReview.
Source fields used:
id,workspace_id,tenant_id,status,completeness_state,generated_at,published_at,archived_atsummary.publish_blockerssummary.section_state_countsevidence_snapshot_id,current_export_review_pack_id,operation_run_id- child
sections.completeness_state,sections.measured_at
Derived truth rules:
statusanswers lifecycle (draft,ready,published, etc.), not evidence completeness by itself.- Publish blockers control
publicationReadiness = blockedeven when the review artifact exists. - A review may be internally useful while still not publishable.
ReviewPackProjection
Existing tenant-owned source record: ReviewPack.
Source fields used:
id,workspace_id,tenant_id,status,generated_at,expires_at,file_sizesummary.review_statussummary.evidence_resolution.*tenant_review_id,evidence_snapshot_id,operation_run_id
Derived truth rules:
status = readymeans a file exists, not necessarily that the source review is still publishable.- Provenance must consider linked review state and evidence completeness at generation time.
expiredis historical-only rather than a runtime failure.
ArtifactRunProjection
Existing source record: OperationRun limited to artifact-targeted families.
Source fields used:
id,workspace_id,tenant_id,type,status,outcome,summary_counts,failure_summary,context- translated reason via
ReasonPresenter - related links via
OperationRunLinks
Derived truth rules:
- Run lifecycle and run outcome remain distinct from whether an artifact was actually produced.
- Artifact-targeted families in this slice:
baseline_capture,tenant.evidence.snapshot.generate,tenant.review.compose,tenant.review_pack.generate - The run truth section may reuse persisted
contextor summary enrichment to state whether the intended artifact exists and is usable.
State Transitions
Truth-envelope transitions
These are read-model transitions, not persistence transitions:
not_created→created- Trigger: artifact record becomes available and usable.
created→created_but_not_usable- Trigger: artifact exists but content, freshness, or readiness makes it unsafe for the primary operator task.
createdorcreated_but_not_usable→historical_only- Trigger: artifact remains intelligible for history, but is expired, superseded, or no longer current for primary use.
publicationReadiness = blocked→publishable- Trigger: review blockers clear or a derived pack is generated from a publishable review.
Existing persisted lifecycle references
EvidenceSnapshot.status:queued→generating→active→superseded|expired|failedTenantReview.status:draft→ready→published|archived|superseded|failedReviewPack.status:queued→generating→ready|failed|expiredOperationRun.status/outcome: service-owned lifecycle that remains unchanged by this feature
No New Primary Persistence in First Slice
- No new top-level table is required.
- Backward-compatible enrichment of existing JSON payloads is allowed if a family cannot otherwise satisfy truthful artifact provenance.
- Any enrichment must remain optional for historical records and degrade gracefully when absent.