## 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
268 lines
10 KiB
Markdown
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. |