175 lines
8.1 KiB
Markdown
175 lines
8.1 KiB
Markdown
# 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_run`
|
|
- `artifactKey` (string): stable identifier in the form `{family}:{id}`
|
|
- `workspaceId` (int)
|
|
- `tenantId` (int|null): `null` for workspace-owned baseline snapshots and workspace-level runs
|
|
- `executionOutcome` (enum|null): `pending`, `succeeded`, `partially_succeeded`, `blocked`, `failed`
|
|
- `artifactExistence` (enum): `not_created`, `historical_only`, `created`, `created_but_not_usable`
|
|
- `contentState` (enum): `trusted`, `partial`, `missing_input`, `metadata_only`, `reference_only`, `empty`, `unsupported`
|
|
- `freshnessState` (enum): `current`, `stale`, `unknown`
|
|
- `publicationReadiness` (enum|null): `not_applicable`, `internal_only`, `publishable`, `blocked`
|
|
- `supportState` (enum): `normal`, `limited_support`
|
|
- `actionability` (enum): `none`, `optional`, `required`
|
|
- `primaryReasonCode` (string|null)
|
|
- `primaryLabel` (string): top-level operator-facing state summary
|
|
- `primaryExplanation` (string|null): concise explanation of the main degraded dimension
|
|
- `diagnosticLabel` (string|null): renderer or implementation-oriented label shown only secondarily
|
|
- `nextActionLabel` (string|null)
|
|
- `nextActionUrl` (string|null)
|
|
- `relatedRunId` (int|null)
|
|
- `relatedArtifactUrl` (string|null)
|
|
|
|
**Validation rules**:
|
|
- `artifactExistence = not_created` MUST NOT coexist with `contentState = trusted`.
|
|
- `publicationReadiness` MAY be non-null only for review and review-pack families.
|
|
- `supportState = limited_support` MUST NOT be used as the primary failure dimension if another truth dimension explains operator impact.
|
|
- `actionability = required` MUST include either `nextActionLabel` or 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_actionability`
|
|
- `state` (string)
|
|
- `label` (string)
|
|
- `classification` (enum): `primary`, `secondary`, `diagnostic`
|
|
- `badgeDomain` (string|null)
|
|
- `badgeState` (string|null)
|
|
|
|
**Validation rules**:
|
|
- At most one `primary` dimension 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 artifact
|
|
- `operatorLabel` (string|null)
|
|
- `shortExplanation` (string|null)
|
|
- `diagnosticCode` (string|null)
|
|
- `nextSteps` (list<string>)
|
|
|
|
**Validation rules**:
|
|
- If `reasonCode` is translated, `operatorLabel` SHOULD 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_at`
|
|
- `summary_jsonb.fidelity_counts`
|
|
- `summary_jsonb.gaps`
|
|
- derived fidelity from `FidelityState::fromSummary(...)`
|
|
|
|
**Derived truth rules**:
|
|
- Full artifact trust requires usable captured content and no misleading gap interpretation.
|
|
- `unsupported` fidelity 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_at`
|
|
- `summary.missing_dimensions`, `summary.stale_dimensions`
|
|
- child `items.state`, `items.source_kind`, `items.freshness_at`
|
|
- `operation_run_id`
|
|
|
|
**Derived truth rules**:
|
|
- `status` models lifecycle; `completeness_state` models coverage/freshness and must not be collapsed into lifecycle.
|
|
- `missing_dimensions > 0` indicates incomplete coverage, not run failure.
|
|
- `stale_dimensions > 0` indicates 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_at`
|
|
- `summary.publish_blockers`
|
|
- `summary.section_state_counts`
|
|
- `evidence_snapshot_id`, `current_export_review_pack_id`, `operation_run_id`
|
|
- child `sections.completeness_state`, `sections.measured_at`
|
|
|
|
**Derived truth rules**:
|
|
- `status` answers lifecycle (`draft`, `ready`, `published`, etc.), not evidence completeness by itself.
|
|
- Publish blockers control `publicationReadiness = blocked` even 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_size`
|
|
- `summary.review_status`
|
|
- `summary.evidence_resolution.*`
|
|
- `tenant_review_id`, `evidence_snapshot_id`, `operation_run_id`
|
|
|
|
**Derived truth rules**:
|
|
- `status = ready` means a file exists, not necessarily that the source review is still publishable.
|
|
- Provenance must consider linked review state and evidence completeness at generation time.
|
|
- `expired` is 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 `context` or 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:
|
|
|
|
1. `not_created` → `created`
|
|
- Trigger: artifact record becomes available and usable.
|
|
2. `created` → `created_but_not_usable`
|
|
- Trigger: artifact exists but content, freshness, or readiness makes it unsafe for the primary operator task.
|
|
3. `created` or `created_but_not_usable` → `historical_only`
|
|
- Trigger: artifact remains intelligible for history, but is expired, superseded, or no longer current for primary use.
|
|
4. `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|failed`
|
|
- `TenantReview.status`: `draft` → `ready` → `published|archived|superseded|failed`
|
|
- `ReviewPack.status`: `queued` → `generating` → `ready|failed|expired`
|
|
- `OperationRun.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. |