# Implementation Plan: Evidence Temporal Freshness & Review Publication Trust **Branch**: `174-evidence-freshness-publication-trust` | **Date**: 2026-04-04 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/174-evidence-freshness-publication-trust/spec.md` **Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/174-evidence-freshness-publication-trust/spec.md` ## Summary Harden evidence freshness and publication trust across the existing evidence snapshot, tenant review, review pack, evidence overview, and canonical review register surfaces without adding new persistence, a new trust layer, or a new reporting subsystem. The implementation will reuse the source-derived stale semantics and their existing source-defined freshness thresholds, tighten propagation in `ArtifactTruthPresenter`, keep review readiness and publication readiness distinct, preserve the current tenant and canonical routes and action inventory, and close the existing cross-surface gap where stale or partial evidence can still look publishable. Key approach: keep the work inside the current `EvidenceSnapshotService` freshness semantics, `TenantReviewReadinessGate`, `ArtifactTruthPresenter`, tenant-scoped Filament resources, and canonical summary pages. The slice is primarily about better derivation and consistent display, not about new models or new workflows. ## Technical Context **Language/Version**: PHP 8.4, Laravel 12, Filament v5, Livewire v4, Blade **Primary Dependencies**: Filament v5, Livewire v4, Pest v4, Laravel Sail, existing `ArtifactTruthPresenter`, `ArtifactTruthEnvelope`, `TenantReviewReadinessGate`, `EvidenceSnapshotService`, `TenantReviewRegisterService`, and current evidence/review/review-pack resources and pages **Storage**: PostgreSQL with existing `evidence_snapshots`, `evidence_snapshot_items`, `tenant_reviews`, and `review_packs` tables using current summary JSON and timestamps; no schema change planned **Testing**: Pest feature tests and Livewire page tests run via Sail, plus existing governance-artifact fixture helpers **Target Platform**: Laravel web application in Sail locally and containerized Linux deployment in staging and production **Project Type**: Laravel monolith web application **Performance Goals**: Preserve DB-only render behavior on detail and canonical surfaces, avoid any render-time external calls, keep list-row truth derivation lightweight enough for canonical table scans, and keep operator trust signals readable within a 5-10 second scan on summary surfaces **Constraints**: No new tables, no new enum families, no new presenter or resolver subsystem, no route changes, no RBAC drift, no destructive-action placement drift, no global asset changes, and no new global freshness engine if existing source-derived stale semantics are sufficient **Scale/Scope**: Five operator-facing surfaces (`/admin/evidence/overview`, `/admin/reviews`, `/admin/t/{tenant}/evidence/{snapshot}`, `/admin/t/{tenant}/reviews/{review}`, `/admin/t/{tenant}/review-packs/{pack}`), one central truth presenter, existing readiness helpers, and focused regression coverage across fresh, stale, partial, blocked, internal-only, and publishable scenarios ## Constitution Check *GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.* | Principle | Status | Notes | |-----------|--------|-------| | Inventory-first | Pass | Evidence freshness remains derived from the existing snapshot-item and source-evaluation chain; no new snapshot ownership semantics | | Read/write separation | Pass | This slice primarily changes truth derivation and display; existing mutate actions remain unchanged | | Graph contract path | Pass | No new Graph calls or contract-registry changes are introduced | | Deterministic capabilities | Pass | No new capability derivation or role mapping is added | | RBAC-UX planes and 404 vs 403 | Pass | Tenant-scoped resources remain tenant-scoped; canonical `/admin` pages stay workspace- and tenant-entitlement-safe | | Workspace isolation | Pass | Canonical summary pages continue to derive rows only from entitled tenants in the current workspace | | Tenant isolation | Pass | Drill-through links remain tenant-scoped and non-entitled users remain deny-as-not-found | | Destructive confirmation | Pass | Existing destructive actions (`Expire snapshot`, `Archive review`, `Expire pack`) already require confirmation and remain unchanged | | Global search safety | Pass | No global-search behavior is added or broadened; `EvidenceSnapshotResource`, `TenantReviewResource`, and `ReviewPackResource` already have view pages | | Run observability | Pass | Existing evidence, review, and pack generation flows keep their current `OperationRun` types and ownership; no new run type is introduced | | Ops-UX 3-surface feedback | Pass | No toast, progress, or terminal-notification behavior changes | | Ops-UX lifecycle ownership | Pass | No `OperationRun.status` or `outcome` transition logic is touched | | Ops-UX summary counts | Pass | No changes to `summary_counts` contracts are required | | Ops-UX guards | Pass | Existing operation lifecycle guards stay in place; this feature adds truth-surface regression tests instead | | Data minimization | Pass | No new payload exposure or raw-report surface is introduced | | Proportionality (PROP-001) | Pass | The implementation stays inside existing freshness, readiness, and truth layers rather than adding persistence or abstraction | | No premature abstraction (ABSTR-001) | Pass | No new resolver, gate, presenter family, registry, or taxonomy is planned | | Persisted truth (PERSIST-001) | Pass | All new semantics remain derived from existing timestamps, summary state, and linked records | | Behavioral state (STATE-001) | Pass | No new persisted states are introduced; existing stale/partial/publishable/internal-only semantics become stricter | | UI semantics (UI-SEM-001) | Pass | Existing badge and truth primitives are reused; no second interpretation framework is introduced | | V1 explicitness / few layers (V1-EXP-001, LAYER-001) | Pass | One central presenter and existing pages remain the implementation seam | | Badge semantics (BADGE-001) | Pass | Existing freshness, completeness, publication-readiness, and artifact-truth badge domains stay canonical | | Filament-native UI (UI-FIL-001) | Pass | Existing Filament resources, pages, badges, tables, and infolists are reused; no page-local status language is added | | UI/UX surface taxonomy (UI-CONST-001 / UI-SURF-001) | Pass | Evidence snapshot, tenant review, and review pack remain `CRUD / List-first Resource` surfaces with dedicated detail pages, while evidence overview and review register remain `Read-only Registry / Report Surface` surfaces | | UI/UX inspect model (UI-HARD-001) | Pass | Clickable-row inspect remains primary on the affected lists; no redundant view action is introduced | | UI/UX action hierarchy (UI-HARD-001 / UI-EX-001) | Pass | Existing one-inline-safe-shortcut patterns remain; no new row-level destructive actions are added | | UI/UX scope, truth, and naming (UI-HARD-001 / UI-NAMING-001 / OPSURF-001) | Pass | The feature strengthens default-visible trust truth while preserving canonical nouns and existing verbs | | List-surface review checklist (UI-STD-001) | Pass | The affected list and report surfaces will be reviewed against `docs/product/standards/list-surface-review-checklist.md` during implementation and final verification | | Filament Action Surface Contract | Pass | Current surface declarations already match the required list/detail behavior; the feature changes truth semantics, not action topology | | Filament UX-001 | Pass | Existing Infolist and table layouts remain; this slice strengthens the truth surfaces inside them | | Filament v5 / Livewire v4 compliance | Pass | The work remains inside the current Filament v5 + Livewire v4 stack | | Provider registration location | Pass | No panel/provider changes; Laravel 11+ provider registration remains in `bootstrap/providers.php` | | Asset strategy | Pass | No new panel or shared assets are required; deployment `filament:assets` behavior remains unchanged | ## Phase 0 Research Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/174-evidence-freshness-publication-trust/research.md`. Key decisions: - Reuse the existing source-derived stale semantics from evidence providers and `EvidenceCompletenessEvaluator` instead of creating a new global freshness engine. - Tighten `ArtifactTruthPresenter` rather than introducing a new publication-trust resolver or freshness-trust gate. - Degrade tenant review and review pack publication trust when freshness is stale and downgrade partial evidence to `internal_only` unless stronger existing blockers already make the artifact `blocked`. - Make review packs inherit stale and partial burden from their linked review and evidence basis instead of treating pack freshness as `current` whenever the file itself is not expired. - Keep canonical register and overview surfaces aligned by reusing the same truth envelope and next-step language rather than adding page-local taxonomies or ad-hoc columns. - Expand existing Pest coverage and fixture builders rather than creating a new UI test harness. ## Phase 1 Design Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/174-evidence-freshness-publication-trust/`: - `data-model.md`: derived trust-propagation model for evidence snapshots, tenant reviews, review packs, and canonical summary rows - `contracts/evidence-review-trust-surfaces.openapi.yaml`: internal page-contract schema for the affected rendered HTML surfaces and their structured truth payloads - `quickstart.md`: focused verification workflow for manual and automated validation Design decisions: - No schema migration is required; freshness remains derived from existing evidence-source timestamps and summary state. - The primary implementation seam is `ArtifactTruthPresenter`, supported by the current evidence and review readiness services and existing page row builders. - `TenantReviewReadinessGate` remains the publish-blocker authority for required stale or missing sections; this feature tightens how that burden is translated into operator-facing trust and publication surfaces. - `EvidenceOverview` and `ReviewRegister` continue to render read-only summary rows, but must no longer sound calmer than the corresponding tenant-scoped detail surfaces. - Existing destructive actions and capabilities remain unchanged; only truth presentation, next-step guidance, and consistency rules are hardened. ## Project Structure ### Documentation (this feature) ```text specs/174-evidence-freshness-publication-trust/ ├── spec.md ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md ├── contracts/ │ └── evidence-review-trust-surfaces.openapi.yaml ├── checklists/ │ └── requirements.md └── tasks.md ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ ├── Pages/ │ │ ├── Monitoring/ │ │ │ └── EvidenceOverview.php │ │ └── Reviews/ │ │ └── ReviewRegister.php │ └── Resources/ │ ├── EvidenceSnapshotResource.php │ ├── ReviewPackResource.php │ ├── TenantReviewResource.php │ ├── EvidenceSnapshotResource/ │ │ └── Pages/ │ │ └── ViewEvidenceSnapshot.php │ ├── ReviewPackResource/ │ │ └── Pages/ │ │ └── ViewReviewPack.php │ └── TenantReviewResource/ │ └── Pages/ │ └── ViewTenantReview.php ├── Models/ │ ├── EvidenceSnapshot.php │ ├── EvidenceSnapshotItem.php │ ├── ReviewPack.php │ └── TenantReview.php ├── Services/ │ ├── Evidence/ │ │ ├── EvidenceCompletenessEvaluator.php │ │ ├── EvidenceSnapshotService.php │ │ └── Sources/ │ │ ├── BaselineDriftPostureSource.php │ │ ├── EntraAdminRolesSource.php │ │ ├── FindingsSummarySource.php │ │ ├── OperationsSummarySource.php │ │ └── PermissionPostureSource.php │ └── TenantReviews/ │ ├── TenantReviewReadinessGate.php │ └── TenantReviewRegisterService.php └── Support/ └── Ui/ └── GovernanceArtifactTruth/ ├── ArtifactTruthEnvelope.php └── ArtifactTruthPresenter.php resources/ └── views/ └── filament/ ├── infolists/ │ └── entries/ │ └── governance-artifact-truth.blade.php └── pages/ ├── monitoring/ │ └── evidence-overview.blade.php └── reviews/ └── review-register.blade.php routes/ └── web.php tests/ ├── Feature/ │ ├── Concerns/ │ │ └── BuildsGovernanceArtifactTruthFixtures.php │ ├── Evidence/ │ │ ├── EvidenceOverviewPageTest.php │ │ └── EvidenceSnapshotResourceTest.php │ ├── Monitoring/ │ │ └── ArtifactTruthRunDetailTest.php │ ├── ReviewPack/ │ │ └── ReviewPackResourceTest.php │ └── TenantReview/ │ ├── TenantReviewLifecycleTest.php │ └── TenantReviewRegisterTest.php └── Pest.php ``` **Structure Decision**: Standard Laravel monolith. The change is concentrated in one existing truth-presenter seam, current readiness helpers, a small set of existing Filament resources/pages, and focused Pest coverage. No new base directories, services, or presentation frameworks are required. ## Implementation Strategy ### Phase A — Preserve Source-Derived Freshness As The Canonical Input **Goal**: Keep existing provider-level stale semantics as the source of truth and document them clearly in the implementation so the feature does not accidentally invent a second freshness system. | Step | File | Change | |------|------|--------| | A.1 | `app/Services/Evidence/EvidenceCompletenessEvaluator.php` | Confirm that source-level `stale` evaluation and snapshot completeness remain the canonical freshness input used by the UI truth layer | | A.2 | `app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php` | Keep evidence-snapshot truth derived from snapshot status, completeness, and `summary.stale_dimensions` rather than introducing new page-local age logic | | A.3 | `specs/174-evidence-freshness-publication-trust/research.md` and `data-model.md` | Record the source-derived freshness chain so implementation does not drift into a new threshold engine | ### Phase B — Downgrade Tenant Review Publication Trust When Freshness Or Completeness Weakens Confidence **Goal**: Ensure tenant reviews can remain useful internally while no longer appearing publishable when their evidence basis is stale or partial. | Step | File | Change | |------|------|--------| | B.1 | `app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php` | Tighten `buildTenantReviewEnvelope()` so stale freshness and partial evidence degrade publication readiness and next-step guidance appropriately | | B.2 | `app/Services/TenantReviews/TenantReviewReadinessGate.php` | Reuse existing required-section stale and missing blocker semantics; do not create a second publish-blocker system | | B.3 | `app/Filament/Resources/TenantReviewResource.php` and `app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php` | Verify the tightened truth envelope is visible on list and detail surfaces without changing action topology or copy vocabulary | ### Phase C — Propagate Source Review And Evidence Burden Into Review Pack Trust **Goal**: Prevent review packs from appearing calmer than the review or evidence basis they were generated from. | Step | File | Change | |------|------|--------| | C.1 | `app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php` | Tighten `buildReviewPackEnvelope()` so pack freshness and publication readiness inherit stale or partial burden from the source review and evidence resolution | | C.2 | `app/Filament/Resources/ReviewPackResource.php` and `app/Filament/Resources/ReviewPackResource/Pages/ViewReviewPack.php` | Ensure pack list/detail surfaces expose internal-only or cautionary trust and next-step caveats before download or sharing | | C.3 | `resources/views/filament/infolists/entries/governance-artifact-truth.blade.php` | Reuse the existing truth partial to surface freshness and publication dimensions with stronger consistency rather than new local markup | ### Phase D — Align Canonical Overview And Register Rows With Tenant-Scoped Detail Truth **Goal**: Ensure `/admin/evidence/overview` and `/admin/reviews` summarize the same truth direction as the tenant-scoped detail pages. | Step | File | Change | |------|------|--------| | D.1 | `app/Filament/Pages/Monitoring/EvidenceOverview.php` | Keep row truth and next-step guidance sourced from the same envelope semantics used by snapshot detail | | D.2 | `app/Filament/Pages/Reviews/ReviewRegister.php` | Keep artifact truth, publication readiness, and next-step rows aligned with tenant review detail without adding new ad-hoc row taxonomy | | D.3 | `routes/web.php` and current navigation helpers | Preserve existing canonical route shape and tenant-prefilter continuity; no routing change | ### Phase E — Regression Protection And Focused Validation **Goal**: Add the smallest useful test set that protects stale propagation, partial-evidence trust, review/pack consistency, and canonical summary alignment. | Step | File | Change | |------|------|--------| | E.1 | `tests/Feature/Concerns/BuildsGovernanceArtifactTruthFixtures.php` | Add fixture helpers for stale and partial evidence scenarios so tests do not duplicate setup logic | | E.2 | `tests/Feature/Evidence/EvidenceSnapshotResourceTest.php` | Add fresh-vs-stale snapshot truth assertions, including stale-dimension next-step behavior | | E.3 | `tests/Feature/TenantReview/TenantReviewLifecycleTest.php` | Add stale and partial review publication-trust assertions without changing lifecycle behavior | | E.4 | `tests/Feature/ReviewPack/ReviewPackResourceTest.php` | Add pack trust propagation assertions for stale or partial source review/evidence combinations | | E.5 | `tests/Feature/TenantReview/TenantReviewRegisterTest.php` and `tests/Feature/Evidence/EvidenceOverviewPageTest.php` | Add canonical row-alignment assertions so summary pages do not sound calmer than detail | | E.6 | `vendor/bin/sail bin pint --dirty --format agent` and focused Pest runs | Required formatting and targeted verification before task completion | ## Key Design Decisions ### D-001 — Source-specific stale evaluation stays canonical Evidence sources already produce `stale` item states using their own domain-appropriate recency logic, and `EvidenceCompletenessEvaluator` already rolls those into snapshot completeness. The plan reuses that chain instead of inventing a separate global age-policy system. ### D-002 — `ArtifactTruthPresenter` remains the single trust-propagation seam The current code already centralizes evidence snapshot, tenant review, and review pack trust in one presenter. Tightening that presenter is narrower and safer than introducing a new publication-trust resolver or freshness framework. ### D-003 — Publication readiness remains distinct from freshness and completeness The feature must not collapse all trust dimensions into one vague `ready` state. Freshness, completeness, and publication readiness remain separate dimensions, but stale evidence downgrades share safety and partial evidence downgrades publication readiness to `internal_only` unless existing blockers already make the artifact `blocked`. ### D-004 — Canonical summary pages must reuse existing truth, not invent row-local semantics `EvidenceOverview` and `ReviewRegister` already surface artifact truth, publication, and next-step information. The right fix is to align their inputs with the tightened truth envelope, not to add page-specific badges or prose. ### D-005 — No new persistence or reporting subsystem is justified This is a current-release operator-trust problem, but it is still a derived-truth problem. Existing timestamps, summary state, and linked artifacts are enough to solve it without a StoredReport viewer, new export-governance model, or separate publication-trust entity. ## Risk Assessment | Risk | Impact | Likelihood | Mitigation | |------|--------|------------|------------| | Review publication trust becomes too strict and downgrades healthy reviews | Medium | Medium | Base downgrades on existing stale/partial semantics already produced by evidence and review services rather than a new heuristic | | Review pack truth diverges from review truth because pack code and review code evolve separately | High | Medium | Centralize propagation in `ArtifactTruthPresenter` and add explicit review-vs-pack consistency tests | | Canonical summary pages become denser or harder to scan | Medium | Low | Reuse existing columns and next-step fields instead of adding more row furniture | | `fresh` versus non-`fresh` envelope variants diverge across surfaces | Medium | Low | Keep one truth-building path and only use `fresh` variants when cache bypass is genuinely needed | | Implementation accidentally introduces a new freshness policy or new abstraction | Medium | Low | Lock the design to current source-derived stale semantics and reject new persistence or resolver additions in review | ## Test Strategy - Extend the current evidence, tenant review, review pack, and canonical summary Pest tests instead of adding a new testing layer. - Use `BuildsGovernanceArtifactTruthFixtures` and existing `composeTenantReviewForTest()` helpers to build fresh, stale, and partial scenarios consistently. - Add explicit assertions for fresh versus stale evidence snapshots, partial versus complete review evidence, review-pack versus review trust alignment, and canonical row truth alignment. - Preserve existing authorization semantics: non-entitled users remain `404`, in-scope users without manage capability remain `403` for actions, and summary truth remains visible only within entitled scope. - Keep destructive actions and operation-launch semantics unchanged; test additions should focus on trust consequences, not on unrelated lifecycle behavior. - Focused verification targets: `EvidenceSnapshotResourceTest`, `TenantReviewLifecycleTest`, `ReviewPackResourceTest`, `TenantReviewRegisterTest`, `EvidenceOverviewPageTest`, and fixture helpers. ## Complexity Tracking No constitution violations or justified complexity exceptions were identified. ## Proportionality Review Not triggered beyond the already-passed spec review. The plan introduces no new enum/status family, DTO/presenter family, persisted entity, registry, resolver, taxonomy, or cross-domain UI framework.