23 KiB
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
EvidenceCompletenessEvaluatorinstead of creating a new global freshness engine. - Tighten
ArtifactTruthPresenterrather 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_onlyunless stronger existing blockers already make the artifactblocked. - Make review packs inherit stale and partial burden from their linked review and evidence basis instead of treating pack freshness as
currentwhenever 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 rowscontracts/evidence-review-trust-surfaces.openapi.yaml: internal page-contract schema for the affected rendered HTML surfaces and their structured truth payloadsquickstart.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. TenantReviewReadinessGateremains 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.EvidenceOverviewandReviewRegistercontinue 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)
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)
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
BuildsGovernanceArtifactTruthFixturesand existingcomposeTenantReviewForTest()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 remain403for 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.