TenantAtlas/specs/393-evidence-anchor-reconciliation-v1/plan.md
ahmido 77f499b60e feat: add evidence anchor reconciliation contracts and readiness fixes (#464)
Automated PR created by Codex via Gitea API.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #464
2026-06-21 09:39:14 +00:00

22 KiB

Implementation Plan: Spec 393 - Evidence Anchor Reconciliation v1

Branch: feat/393-evidence-anchor-reconciliation-v1 | Date: 2026-06-20 | Spec: specs/393-evidence-anchor-reconciliation-v1/spec.md Input: Feature specification from specs/393-evidence-anchor-reconciliation-v1/spec.md

Summary

Introduce one canonical Evidence Anchor Resolver/result contract and replace product-facing local evidence selectors with that contract. Current dashboard/workspace/environment surfaces must resolve only valid current evidence; released review/report/review-pack output must stay bound to release evidence; Customer Review Workspace must show customer-safe evidence summary without raw evidence links by default; technical evidence detail remains available only through secondary internal/audit paths.

This is a clean-cut correctness fix. Do not preserve legacy fallback-to-latest behavior, old tests expecting partial/superseded evidence, or compatibility aliases.

Technical Context

Language/Version: PHP 8.4.15 Primary Dependencies: Laravel 12.52, Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1 Storage: PostgreSQL; no migration expected by default Testing: Pest 4 Unit, Feature/HTTP, Filament/Livewire, bounded Browser smoke Validation Lanes: fast-feedback, confidence, browser Target Platform: Laravel Sail local; Dokploy container deployment for staging/production Project Type: Laravel monolith under apps/platform Performance Goals: Resolver decisions must be DB-only, deterministic, scoped, and avoid render-time remote calls Constraints: no legacy fallback, no UI expansion, no new customer proof surface, no Graph calls during render, no new persisted truth unless spec/plan are updated first Scale/Scope: existing evidence, dashboard, review, customer workspace, review-pack, stored-report, rendered-report, and management-report provenance surfaces

Technical Approach

  1. Inventory every evidence selector/link/action/output path.
  2. Define a derived EvidenceAnchorResolver contract and result value object/array shape with a non-persisted anchor type/state vocabulary.
  3. Implement current-scope resolution with strict scope, active/complete/non-expired checks, and deterministic ordering.
  4. Implement released-review/review-pack/report resolution from existing release-bound relations.
  5. Implement customer-safe summary resolution that omits target routes by default.
  6. Implement technical-detail resolution with actor permission checks.
  7. Replace local selectors in affected product surfaces.
  8. Remove deprecated local fallback logic and stale test expectations.
  9. Add regression tests and focused browser smoke.

Preferred shape:

Existing evidence/review/report truth
    -> EvidenceAnchorResolver
    -> EvidenceAnchorResult
    -> UI labels, target routes, route/report provenance, tests

Do not create a new evidence lifecycle, proof framework, or persisted readiness model.

Likely Affected Repository Surfaces

Implementation must re-verify exact current code before editing, but likely surfaces are:

  • apps/platform/app/Services/Evidence/EvidenceSnapshotResolver.php
  • new or consolidated resolver under apps/platform/app/Services/Evidence/ or a similarly scoped namespace
  • apps/platform/app/Models/EvidenceSnapshot.php
  • apps/platform/app/Services/EnvironmentReviews/EnvironmentReviewService.php
  • apps/platform/app/Filament/Pages/Monitoring/EvidenceOverview.php
  • apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php
  • apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php
  • apps/platform/app/Filament/Resources/EnvironmentReviewResource.php
  • apps/platform/app/Filament/Resources/ReviewPackResource.php
  • apps/platform/app/Filament/Resources/StoredReportResource.php
  • apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php
  • apps/platform/app/Support/ReviewPacks/ManagementReportPdfPayloadBuilder.php
  • apps/platform/app/Support/ReviewPublicationResolution/ReviewPublicationProofResolver.php
  • apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php
  • apps/platform/app/Support/OperationRunLinks.php
  • apps/platform/app/Support/Navigation/RelatedNavigationResolver.php
  • apps/platform/app/Support/GovernanceDecisions/GovernanceDecisionRegisterBuilder.php
  • review-pack rendered-report/download/report payload code where evidence provenance is displayed
  • dashboard/workspace/environment summary builders that produce evidence CTAs
  • localization files only where labels change
  • focused tests under apps/platform/tests/Unit, apps/platform/tests/Feature, and apps/platform/tests/Browser

Implementation may remove a surface from the touched list if repo truth proves it is not product-facing or already uses the canonical resolver safely.

UI / Surface Guardrail Plan

  • Guardrail scope: existing product-facing evidence labels/links and customer-safe evidence disclosure.
  • Affected routes/pages/actions/states/navigation/panel/provider surfaces: dashboard/workspace/environment evidence CTA, Evidence Overview, Customer Review Workspace, Environment Review detail, Review Pack detail/rendered report, Stored Report/Management Report provenance, Evidence Snapshot technical detail links.
  • No-impact class, if applicable: N/A.
  • Native vs custom classification summary: mixed existing native Filament resources/pages plus existing Blade composition.
  • Shared-family relevance: evidence links, status messaging, dashboard signals, artifact/report viewers, customer-safe disclosure.
  • State layers in scope: page, detail, row URL, route target, report payload/provenance.
  • Audience modes in scope: customer/read-only, operator-MSP, support/internal where authorized.
  • Decision/diagnostic/raw hierarchy plan: product evidence decision first; diagnostics/raw proof secondary or gated.
  • Raw/support gating plan: no raw evidence route by default on Customer Review Workspace; technical detail only through internal/audit action with permission.
  • One-primary-action / duplicate-truth control: default UI shows at most one evidence-related action/state per context.
  • Handling modes by drift class or surface: wrong current evidence is hard-stop; customer raw link leakage is hard-stop; technical/audit link mislabeling is review-mandatory.
  • Repository-signal treatment: related completed specs are context only and must not be rewritten.
  • Special surface test profiles: customer-safe strategic review surface + evidence/artifact detail + dashboard signal.
  • Required tests or manual smoke: Unit resolver tests, Feature/Filament product surface tests, Browser smoke for dashboard/customer/review/evidence flows.
  • Exception path and spread control: no exception expected; any retained page-local selector must be documented as technical/admin-only and proven not product-facing.
  • Active feature PR close-out entry: Guardrail / Smoke Coverage.
  • UI/Productization coverage decision: update existing page-report artifacts if visible behavior materially changes; otherwise document no route/archetype expansion.
  • Coverage artifacts to update: likely existing page reports for Customer Review Workspace, Evidence Overview, Review Pack detail, Environment Review detail, Stored Report detail, and Evidence Snapshot detail only if implementation materially changes default-visible behavior.
  • Explicit no-route/no-archetype expectation: no route inventory, design matrix, strategic surfaces, grouped follow-up, or unresolved-page updates are expected unless implementation changes route reachability or page archetype/count; implementation must document that no-impact decision in the close-out.
  • No-impact rationale: N/A.
  • Navigation / Filament provider-panel handling: no provider registration or panel path change; provider registration remains apps/platform/bootstrap/providers.php.
  • Screenshot or page-report need: focused browser smoke with screenshots if visible link/summary behavior changes; not required for purely route/service changes.

Shared Pattern & System Fit

  • Cross-cutting feature marker: yes.
  • Systems touched: evidence resolver, review/review-pack/report provenance, dashboard/evidence links, customer-safe disclosure, technical/audit detail actions, ArtifactTruthPresenter/GovernanceArtifactTruth, OperationRunLinks, RelatedNavigationResolver, GovernanceDecisionRegisterBuilder, policies.
  • Shared abstractions reused: existing EvidenceSnapshot scopes/relations where correct, existing review/review-pack/report relations, existing policies/capabilities, existing BadgeRenderer/BadgeCatalog, existing ArtifactTruthPresenter/GovernanceArtifactTruth presentation paths, Spec 392 output gate where customer output routes need gate context.
  • New abstraction introduced? why?: one narrow derived Evidence Anchor Resolver/result contract because current product surfaces have multiple real evidence-anchor consumers and current local selectors can produce wrong proof.
  • Why the existing abstraction was sufficient or insufficient: EvidenceSnapshotResolver is dimension/readiness oriented and does not encode product anchor type, customer-safe/no-link behavior, release-bound stability, or technical-only authorization.
  • Bounded deviation / spread control: the new resolver must own evidence anchor decisions only. It must not become a generic proof-currentness, report-readiness, or technical annex framework. Shared link builders may remain technical/internal-only, but any product-facing EvidenceSnapshot link they emit must consume resolver output.

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: no new start/completion/link semantics. Existing OperationRun proof may remain only as technical/internal detail.
  • Central contract reused: existing OperationRun link helpers where technical detail remains.
  • Delegated UX behaviors: N/A.
  • Surface-owned behavior kept local: evidence anchor labels/states only.
  • Queued DB-notification policy: N/A.
  • Terminal notification path: unchanged.
  • Exception path: none.

Provider Boundary & Portability Fit

  • Shared provider/platform boundary touched?: no new provider seam.
  • Provider-owned seams: N/A.
  • Platform-core seams: evidence anchor selection, customer-safe evidence summary, technical evidence detail labels.
  • Neutral platform terms / contracts preserved: workspace, managed environment, evidence, current evidence, review evidence, audit trail, internal evidence details.
  • Retained provider-specific semantics and why: existing raw evidence technical pages may contain provider/source detail; default product surfaces must not.
  • Bounded extraction or follow-up path: none unless implementation finds provider-specific leakage outside technical contexts.

Constitution Check

  • Inventory-first / snapshots-second: no new inventory truth; evidence snapshots remain explicit artifacts.
  • Read/write separation: no destructive action or Graph write introduced.
  • Graph contract path: no Graph calls expected; resolver/render paths must remain DB-only.
  • Deterministic capabilities: existing capability/policy checks reused for target route availability.
  • RBAC-UX: non-member workspace/environment access remains 404; member missing capability remains no technical link/403 on direct route.
  • Workspace/tenant isolation: resolver scopes by workspace and managed environment before selecting anchors.
  • OperationRun UX: no OperationRun start/completion changes; technical OperationRun links remain secondary.
  • Test governance: Unit, Feature/Filament, and Browser proof are explicitly scoped.
  • Proportionality: new resolver abstraction is justified by evidence trust, isolation, auditability, and multiple existing consumers.
  • No premature abstraction: resolver replaces duplicated local selection and is not a generic proof framework.
  • Persisted truth: no new persisted truth expected.
  • Behavioral state: allowed UI states are derived result vocabulary, not persisted lifecycle truth.
  • UI semantics: no new badge framework; use existing badge/status helpers.
  • Shared pattern first: central resolver replaces local selectors; shared link helpers either consume it for product-facing links or are explicitly classified technical/internal-only.
  • Provider boundary: provider-specific internals stay technical.
  • UI/Productization coverage: visible surface changes require existing page-report updates or explicit no-archetype-change note.

Domain And Data Implications

No migration is expected. Existing fields appear sufficient:

  • evidence_snapshots.workspace_id
  • evidence_snapshots.managed_environment_id
  • evidence_snapshots.status
  • evidence_snapshots.completeness_state
  • evidence_snapshots.generated_at
  • evidence_snapshots.expires_at
  • environment_reviews.evidence_snapshot_id
  • environment_reviews.current_export_review_pack_id
  • environment_reviews.status
  • environment_reviews.published_at
  • review_packs.evidence_snapshot_id
  • review_packs.environment_review_id
  • review_packs.status
  • review_packs.expires_at
  • stored_reports.source_environment_review_id
  • stored_reports.source_review_pack_id

If implementation proves an anchor cannot be represented with existing truth, stop and update spec/plan before adding schema. A schema change must be minimal, cleanly named, and pre-production clean-cut with no compatibility shim.

Resolver Design Notes

Expected result fields:

anchor_type: string
state: string
evidence_snapshot_id: int|null
target_route: string|null
is_current: bool
is_release_bound: bool
is_customer_safe: bool
is_technical_only: bool
is_partial: bool
is_superseded: bool
is_expired: bool
can_link: bool
can_view_technical_detail: bool
primary_reason: string
blocking_reasons: list<string>
display_label: string

Current evidence query rules:

where workspace_id = scope workspace
where managed_environment_id = scope environment when present
where managed_environment_id in actor-authorized environment ids when no explicit environment is present and a product link is returned
where status = active
where completeness_state = complete
where expires_at is null or expires_at > now()
order by generated_at desc nulls last, id desc

Queued/generating evidence may be represented as draft/internal/in-progress state but must not be returned as product-facing current evidence.

When environment is null, implementation must not query arbitrary workspace evidence and return a single product-facing target. It must either return a non-link workspace summary state or limit selection to actor-authorized managed environments before returning per-environment/current anchors. Product-facing single-target links should prefer an explicit environment.

Released evidence rules:

  • Environment Review: use environment_reviews.evidence_snapshot_id.
  • Review Pack: use review_packs.evidence_snapshot_id and environment_review_id when release-bound output is in scope.
  • Stored/management report: prefer source review/review-pack provenance when present; otherwise no valid released evidence rather than current fallback.

Customer-safe rules:

  • Return summary state and copy.
  • Do not return raw evidence route by default.
  • Optional internal/audit action must be a separate technical result or secondary route.

Technical detail rules:

  • Return raw EvidenceSnapshot route only if actor can view it and scope matches.
  • Label as internal/audit detail.

Route And Authorization Plan

  • Resolver must not be the only security boundary. Direct routes remain protected by existing policies/controllers.
  • UI target routes are returned only when the actor can view the target.
  • Customer-safe actors get no technical target route.
  • Internal/operator actors can get technical detail only through secondary/internal actions.
  • Wrong-scope evidence direct access remains deny-as-not-found by policy/controller tests.

Filament And Livewire Plan

  • Filament v5 / Livewire v4.0+ compliance is required; the app currently uses Livewire 4.1.4.
  • Panel provider registration remains apps/platform/bootstrap/providers.php; no provider changes are expected.
  • No global search participation should be added or changed. If any touched resource currently participates in global search, verify View/Edit page and scoped search rules; otherwise keep global search disabled.
  • No destructive action is introduced. Existing EvidenceSnapshot/ReviewPack/EnvironmentReview actions remain out of scope and must keep existing confirmation, authorization, audit, notifications, and tests.
  • Labels must be truthful:
    • Current evidence for current valid evidence.
    • Review evidence for review-bound/released evidence.
    • Evidence captured for this review for customer-safe summary.
    • View audit trail or View internal evidence details for technical routes.

Audit And Observability Plan

  • No new OperationRun is expected.
  • No new AuditLog requirement is expected for read-only anchor resolution.
  • Existing audit events for downloads, review publication, evidence generation, and review-pack generation remain unchanged.
  • If implementation adds logging for blocked technical route exposure or direct access, metadata must be safe and stable with no raw payloads/secrets/source keys.

Test Strategy

Unit tests

  • Select newest valid current evidence for workspace/environment.
  • Do not select superseded evidence as current.
  • Do not select partial evidence as current.
  • Do not select expired evidence as current.
  • Do not select queued/generating/failed/stale evidence as current.
  • Do not select wrong-workspace evidence.
  • Do not select wrong-environment evidence, including workspace-wide/no-environment requests where the actor lacks entitlement.
  • Return no valid evidence when only partial/superseded/expired evidence exists.
  • Resolve released review evidence independently from current evidence.
  • Keep released review evidence stable after newer current evidence is created.
  • Resolve draft review evidence as internal/draft, not customer-safe.
  • Resolve customer workspace as customer-safe summary with no raw route by default.
  • Actor without permission receives no technical evidence link.
  • Internal/operator actor may receive technical detail link where appropriate.
  • Deterministic tie-breaker when multiple valid snapshots share timestamp.
  • Workspace-wide current anchor does not select evidence from environments the actor cannot access.

Feature / Filament / HTTP tests

  • Dashboard/evidence overview evidence link targets current evidence.
  • Dashboard/evidence overview does not link to superseded/partial evidence.
  • Customer Review Workspace does not render raw evidence links by default.
  • Review Pack detail uses release-bound evidence.
  • Environment Review detail uses release-bound evidence.
  • Rendered report/Stored Report/Management Report provenance uses released review evidence.
  • Stored report/review output does not switch provenance after new current evidence.
  • Direct wrong-scope evidence route remains blocked by scope authorization.
  • Technical evidence detail requires internal permission.
  • Customer-facing pages do not expose technical evidence terms by default.
  • Affected list/detail paths avoid per-row evidence-link N+1 behavior by using explicit eager-loading or bounded resolver query shape where practical.

Browser smoke

Focused smoke should cover:

  • Environment Dashboard or workspace dashboard evidence CTA.
  • Evidence Overview.
  • Review Pack detail.
  • Customer Review Workspace.
  • Rendered/Stored Report surface if evidence provenance is visible.

Assertions:

  • Current dashboard evidence link opens current evidence, not stale/superseded evidence.
  • Customer Review Workspace has no raw evidence snapshot link by default.
  • Review Pack evidence label is truthful.
  • Technical evidence link, if present, is secondary/internal.
  • No visible Evidence #<id> style product link on customer-safe surface.
  • No 500/Livewire/Filament/console errors in affected flows.
  • Direct wrong/old evidence URL does not become a customer-facing proof path.

Validation Commands

Preferred Sail commands:

cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec393
cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec393EvidenceAnchorReconciliationSmokeTest.php
cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
git diff --check

If Sail/Docker is unavailable, run the equivalent local PHP/Pest commands and document the fallback.

Rollout And Deployment Considerations

  • No env vars expected.
  • No migrations expected.
  • No queue/scheduler/storage changes expected.
  • No Graph scope or provider configuration changes expected.
  • No Filament assets expected.
  • Dokploy/staging validation is still required for the later PR because user-facing /admin surfaces change, but there is no production-data compatibility burden.

Risk Controls

  • Resolver tests must fail if partial/superseded/wrong-scope evidence is selected.
  • Feature/browser tests must fail if customer workspace exposes raw evidence by default.
  • Released review tests must fail if new current evidence changes old released output provenance.
  • Code review must search for remaining local fallback selectors and arbitrary latest evidence ordering in affected product surfaces.

Implementation Phases

  1. Repo truth inventory and local selector map.
  2. Resolver contract and Unit tests.
  3. Current evidence replacement in dashboard/evidence overview.
  4. Released review/report/review-pack provenance replacement.
  5. Customer Review Workspace customer-safe summary replacement.
  6. Technical evidence detail gating and labels.
  7. Deprecated local selector/test cleanup.
  8. Browser smoke and close-out report.

Stop Conditions

  • Stop if implementation requires a new persisted entity/table/status family not justified in this spec.
  • Stop if a route/controller change would create a new customer portal or broad technical annex.
  • Stop if a local selector appears necessary for a product-facing surface; update spec/plan or fold it into the resolver instead.
  • Stop if the only way to keep an old test green is to preserve partial/superseded/latest fallback behavior.