# Data Model: Evidence Temporal Freshness & Review Publication Trust ## Overview This feature does not add or modify persisted domain entities. It strengthens the derived trust-propagation model that transforms existing evidence, review, and pack records into operator-facing truth across tenant-scoped detail pages and canonical summary pages. The key design constraint is that freshness and publication trust remain derived from existing fields and relationships: - evidence-source freshness signals - evidence snapshot completeness and summary state - tenant review completeness and publish blockers - review pack linkage back to a source review and source evidence snapshot - the existing `ArtifactTruthEnvelope` dimensions ## Existing Persistent Entities ### 1. EvidenceSnapshot - Purpose: Immutable tenant-scoped evidence basis assembled from multiple evidence dimensions. - Key persisted fields used by this feature: - `id` - `workspace_id` - `tenant_id` - `status` - `completeness_state` - `summary` - `generated_at` - `expires_at` - `operation_run_id` - `fingerprint` - Key summary fields used by this feature: - `dimension_count` - `missing_dimensions` - `stale_dimensions` - `dimensions[]` - `finding_count` - `report_count` - `operation_count` - Relationships used by this feature: - `items` - `tenantReviews` - `reviewPacks` - `operationRun` - `tenant` ### 2. EvidenceSnapshotItem - Purpose: Dimension-level evidence record inside one snapshot. - Key persisted fields used by this feature: - `evidence_snapshot_id` - `tenant_id` - `dimension_key` - `state` - `required` - `measured_at` - `freshness_at` - `source_kind` - `source_record_type` - `source_record_id` - `summary_payload` - `sort_order` - Relationships used by this feature: - `snapshot` - `tenant` ### 3. TenantReview - Purpose: Tenant-scoped review artifact anchored to one evidence snapshot. - Key persisted fields used by this feature: - `id` - `workspace_id` - `tenant_id` - `evidence_snapshot_id` - `status` - `completeness_state` - `summary` - `generated_at` - `published_at` - `archived_at` - `current_export_review_pack_id` - `operation_run_id` - `fingerprint` - Key summary fields used by this feature: - `publish_blockers[]` - `section_state_counts.complete` - `section_state_counts.partial` - `section_state_counts.missing` - `section_state_counts.stale` - `section_count` - `finding_count` - `report_count` - `operation_count` - Relationships used by this feature: - `evidenceSnapshot` - `sections` - `currentExportReviewPack` - `reviewPacks` - `operationRun` - `tenant` ### 4. ReviewPack - Purpose: Tenant-scoped export artifact derived from a review and evidence basis. - Key persisted fields used by this feature: - `id` - `workspace_id` - `tenant_id` - `tenant_review_id` - `evidence_snapshot_id` - `status` - `summary` - `generated_at` - `expires_at` - `file_disk` - `file_path` - `file_size` - `operation_run_id` - `fingerprint` - Key summary fields used by this feature: - `review_status` - `review_completeness_state` - `evidence_resolution.outcome` - `evidence_resolution.snapshot_id` - `evidence_resolution.snapshot_fingerprint` - `evidence_resolution.completeness_state` - `finding_count` - `report_count` - `operation_count` - Relationships used by this feature: - `tenantReview` - `evidenceSnapshot` - `operationRun` - `tenant` ## Existing Derived State Chain ### A. Evidence Freshness Derivation Evidence freshness is already determined in the evidence domain before any UI surface is rendered. 1. Each evidence source provider returns a dimension payload with: - `state` - `required` - `measured_at` - `freshness_at` 2. `EvidenceCompletenessEvaluator` rolls required dimension states into snapshot completeness: - `missing` wins first - then `stale` - then `partial` - otherwise `complete` 3. `EvidenceSnapshotService` persists: - `completeness_state` - `summary.missing_dimensions` - `summary.stale_dimensions` - per-dimension summary state This feature must reuse that chain instead of replacing it. ### B. Review Readiness Derivation Tenant review readiness is already derived from section completeness and blockers. 1. `TenantReviewSectionFactory` and related composition logic produce section completeness states. 2. `TenantReviewReadinessGate` derives: - `blockersForSections()` - `completenessForSections()` - `statusForSections()` 3. `TenantReview.summary` persists: - `publish_blockers[]` - `section_state_counts.*` This feature must reuse those publish blockers and section-state counts rather than adding a parallel publish-readiness source. ## Derived View Models ### 1. ArtifactTruthPropagationModel This is the conceptual chain, not a new class. | Stage | Inputs | Derived outputs | |---|---|---| | Evidence source item | source-specific timestamps and source-record state | per-dimension `state`, `freshness_at`, `required` | | Evidence snapshot | item states, snapshot status, summary counts | `artifactExistence`, `contentState`, `freshnessState`, `actionability` | | Tenant review | review status, review completeness, section-state counts, publish blockers, linked snapshot | `artifactExistence`, `contentState`, `freshnessState`, `publicationReadiness`, `actionability` | | Review pack | pack status, evidence resolution, linked review trust burden, linked snapshot burden | `artifactExistence`, `contentState`, `freshnessState`, `publicationReadiness`, `actionability` | | Canonical summary row | tenant label, record timestamps, derived artifact truth envelope | row-level artifact truth, publication signal, freshness signal, next step | ### 2. SnapshotTruthModel Derived from `EvidenceSnapshot` plus `ArtifactTruthPresenter::buildEvidenceSnapshotEnvelope()`. | Field | Meaning | Source | |---|---|---| | `artifactExistence` | whether a current or historical snapshot exists | snapshot `status` | | `contentState` | whether the evidence basis is trusted, partial, missing, or empty | snapshot `completeness_state`, `summary.dimension_count` | | `freshnessState` | whether the evidence basis is current or stale | snapshot `completeness_state`, `summary.stale_dimensions`, historical status | | `actionability` | whether the operator must act, may optionally act, or can do nothing | derived from freshness and completeness | | `nextStepText` | operator-facing refresh or wait guidance | existing presenter logic | ### 3. ReviewTruthModel Derived from `TenantReview` plus `ArtifactTruthPresenter::buildTenantReviewEnvelope()`. | Field | Meaning | Source | |---|---|---| | `artifactExistence` | whether the review is current, failed, or historical | review status | | `contentState` | whether the review body is complete enough or partial | review completeness | | `freshnessState` | whether the review evidence basis is stale | review completeness and `summary.section_state_counts.stale` | | `publicationReadiness` | whether the review is blocked, internal-only, or publishable | review status, publish blockers, and this feature's stricter freshness/partiality propagation | | `actionability` | whether the operator must resolve blockers, should refresh, or can leave the review alone | derived from publication and freshness burden | | `nextStepText` | resolve blockers, complete work, refresh evidence, or no action needed | existing presenter logic tightened by this feature | ### 4. PackTruthModel Derived from `ReviewPack` plus `ArtifactTruthPresenter::buildReviewPackEnvelope()`. | Field | Meaning | Source | |---|---|---| | `artifactExistence` | whether a current, failed, or historical pack exists | pack status | | `contentState` | whether the pack has a trustworthy source basis | evidence resolution and source review burden | | `freshnessState` | whether the pack should be treated as current or stale for operator trust | pack expiration plus propagated source review/evidence staleness | | `publicationReadiness` | whether the pack is blocked, internal-only, or publishable | pack status plus propagated review and evidence burden | | `actionability` | whether the operator must revisit the review or simply note caution | derived from the trust posture | | `nextStepText` | open source review, refresh evidence, or no action needed | existing presenter logic tightened by this feature | ### 5. CanonicalSummaryRowModel Used conceptually by both `EvidenceOverview` and `ReviewRegister`. | Field | Type | Purpose | |---|---|---| | `tenantName` | string | Maintain tenant context in canonical pages | | `recordId` | int | Link the summary row back to the tenant-scoped detail page | | `artifactTruth` | label + badge spec + explanation | Primary trust summary shown in the row | | `freshness` | badge spec | Evidence overview freshness summary | | `publication` | badge spec | Review register publication summary | | `nextStep` | string | Operator-facing follow-up guidance that matches detail surfaces | | `viewUrl` | string | Drill-through to the tenant-scoped detail page | Rules: - Canonical rows must never appear calmer than the corresponding detail pages. - `nextStep` may be shorter than detail guidance, but not contradictory. - Canonical rows must stay derived from the same truth envelope rather than page-local heuristics. ## Validation Rules - A snapshot can be structurally complete and still stale; the derived truth must preserve that distinction. - A review can be internally useful while not being publishable; the derived truth must preserve that distinction. - A pack must not be calmer than its source review or source evidence basis. - Canonical overview and register rows must not contradict the tenant-scoped detail view for the same artifact. - Freshness, completeness, and publication readiness remain separate dimensions even when they jointly influence the primary label. ## State Notes This feature introduces no new persisted state. Existing state and badge families that remain canonical: - `EvidenceCompletenessState` - `EvidenceSnapshotStatus` - `TenantReviewCompletenessState` - `TenantReviewStatus` - `ReviewPackStatus` - `BadgeDomain::GovernanceArtifactFreshness` - `BadgeDomain::GovernanceArtifactPublicationReadiness` The feature only changes how these existing states combine into operator-facing trust across multiple related surfaces.