TenantAtlas/specs/174-evidence-freshness-publication-trust/data-model.md
ahmido 44898a98ac feat: harden evidence freshness publication trust (#205)
## Summary
- harden governance artifact truth propagation so stale or partial evidence downgrades evidence snapshots, tenant reviews, review packs, the canonical evidence overview, and the canonical review register consistently
- add the full Spec 174 artifact set under `specs/174-evidence-freshness-publication-trust/` including spec, plan, research, data model, contracts, quickstart, checklist, and completed tasks
- add focused fixture helpers plus a new browser smoke test for the touched evidence, review, and review-pack trust surfaces

## Testing
- `vendor/bin/sail artisan test --compact tests/Feature/Evidence/EvidenceSnapshotResourceTest.php tests/Feature/Evidence/EvidenceOverviewPageTest.php tests/Feature/TenantReview/TenantReviewLifecycleTest.php tests/Feature/TenantReview/TenantReviewRegisterTest.php tests/Feature/ReviewPack/ReviewPackResourceTest.php tests/Feature/Monitoring/ArtifactTruthRunDetailTest.php tests/Browser/Spec174EvidenceFreshnessPublicationTrustSmokeTest.php`
- manual integrated-browser smoke pass across Evidence Overview, Review Register, tenant review detail, tenant evidence snapshot detail, and review-packs list

## Notes
- Livewire v4 compliance is preserved and no Filament v3/v4 APIs were introduced
- no panel or provider changes were made; Laravel 11+ provider registration remains in `bootstrap/providers.php`
- no new global-search behavior was introduced; existing resource view pages remain the relevant detail endpoints
- destructive actions were not broadened; existing confirmation and authorization behavior remains in place
- no new assets were added, so the current Filament asset strategy and deploy-time `php artisan filament:assets` behavior stay unchanged
- branch `174-evidence-freshness-publication-trust` is pushed at `7f2c82c26dc83bbc09fbf9e732d5644cdd143113` and targets `dev`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #205
2026-04-04 11:31:27 +00:00

268 lines
10 KiB
Markdown

# 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.