Implemented report evidence reconciliation. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #432
15 KiB
Implementation Plan: Spec 361 - Report and Evidence Reconciliation Adapters
Branch: 361-report-evidence-reconciliation | Date: 2026-06-06 | Spec: /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/361-report-evidence-reconciliation/spec.md
Input: Feature specification from /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/361-report-evidence-reconciliation/spec.md
Note: This plan is repo-aware and preparation-only. No application implementation is performed in this step.
Summary
Extend the current OperationRun reconciliation registry with artifact-backed, read-only adapters for EvidenceSnapshot and ReviewPack, so queued/running/stale runs can finalize only when current repo-real artifact truth already proves success. Keep generic StoredReport families fail-closed and explicitly deferred; Spec 361 does not allow any StoredReport-backed success path.
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 16 (operation_runs, evidence_snapshots, review_packs, stored_reports)
Testing: Pest Unit + Feature + one bounded Browser smoke
Validation Lanes: fast-feedback, confidence, browser
Target Platform: Laravel monolith in Sail / Dokploy container workflow
Project Type: single web application (apps/platform)
Performance Goals: no new polling or background family; reconciliation stays bounded to current stale/queued scan paths
Constraints: no new schema, no new operation type, no new panel/provider, no new Filament asset strategy, no generic stored-report heuristics
Scale/Scope: narrow OperationRun artifact reconciliation extension over two existing artifact families plus explicit unsupported-family handling
UI / Surface Guardrail Plan
- Guardrail scope: changed surfaces
- Affected routes/pages/actions/states/navigation/panel/provider surfaces:
apps/platform/app/Filament/Pages/Monitoring/Operations.phpapps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.phpapps/platform/app/Filament/Resources/EvidenceSnapshotResource.phpapps/platform/app/Filament/Resources/ReviewPackResource.php
- No-impact class, if applicable: N/A
- Native vs custom classification summary: native Filament surfaces with shared
OperationRunand artifact-truth helpers - Shared-family relevance:
OperationRunmonitoring family plus artifact-truth detail family - State layers in scope: page, detail, URL-query
- Audience modes in scope: operator-MSP, support-platform
- Decision/diagnostic/raw hierarchy plan: decision-first on operations surfaces, diagnostics-second on run detail, artifact proof on demand through existing detail pages
- Raw/support gating plan: raw context stays in existing diagnostic sections only
- One-primary-action / duplicate-truth control: keep current inspect/open paths; do not add a second success summary on artifact pages
- Handling modes by drift class or surface: review-mandatory
- Repository-signal treatment: review-mandatory for any attempt to widen scope into generic stored-report success or new artifact lifecycle semantics
- Special surface test profiles: monitoring-state-page
- Required tests or manual smoke: functional-core plus one bounded browser smoke
- Exception path and spread control: none
- Active feature PR close-out entry: Guardrail / Smoke Coverage
- UI/Productization coverage decision: no new coverage artifact required; existing monitoring and artifact page families remain sufficient
- Coverage artifacts to update: none by default
- No-impact rationale: existing reachable surfaces only; no new route family or navigation entry
- Navigation / Filament provider-panel handling: no panel or navigation change
- Screenshot or page-report need: no by default; use bounded browser smoke unless implementation proves a material hierarchy shift
Shared Pattern & System Fit
- Cross-cutting feature marker: yes
- Systems touched:
App\Services\AdapterRunReconcilerApp\Services\OperationRunServiceApp\Support\Operations\Reconciliation\OperationRunReconciliationRegistryApp\Support\OperationRunLinksApp\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenterApp\Support\OpsUx\GovernanceRunDiagnosticSummaryBuilder
- Shared abstractions reused: current adapter contract, current service-owned reconciliation metadata, current monitoring/detail presenters, current artifact-truth presenters and links
- New abstraction introduced? why?: at most one small proof/helper path if duplicated scope/completeness checks across Evidence Snapshot and Review Pack become noisy; no generic report framework is allowed
- Why the existing abstraction was sufficient or insufficient: the write seam and presenters already exist, but the registry lacks artifact-backed success for evidence and review-pack runs
- Bounded deviation / spread control: keep proof logic local to
App\Support\Operations\Reconciliation\; do not add new persistence or a generalized artifact orchestration engine
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes
- Central contract reused: current
OperationRunService, registry-backed reconciliation,OperationRunLinks, and existing monitoring/detail presenters - Delegated UX behaviors: existing queued toast, run link, artifact link, run-enqueued browser event, and terminal notification paths remain unchanged
- Surface-owned behavior kept local: wording and placement only
- Queued DB-notification policy: unchanged
- Terminal notification path: unchanged central lifecycle mechanism
- Exception path: none
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: no
- Provider-owned seams: N/A
- Platform-core seams:
OperationRun, artifact truth, current scope-safe links - Neutral platform terms / contracts preserved:
operation,artifact,review pack,evidence snapshot,reconciliation - Retained provider-specific semantics and why: none
- Bounded extraction or follow-up path: generic
StoredReportcausality remains a separate future follow-up if ever needed
Constitution Check
GATE: Must pass before implementation starts. Re-check if scope changes.
- Inventory-first: PASS. The slice reads current artifact truth; it does not create new snapshot truth.
- Read/write separation: PASS. Adapters read artifacts only and finalize runs only through
OperationRunService. - Graph contract path: PASS. No Graph surface change is planned.
- Deterministic capabilities: PASS. No new capability derivation is introduced.
- Workspace and tenant isolation: PASS. Adapters must use run-owned workspace/environment scope and existing resource policies.
- Run observability: PASS.
OperationRunremains the only lifecycle owner; no shadow truth is introduced. - TEST-GOV-001: PASS. Unit + Feature + bounded Browser are the narrowest honest proof.
- PROP-001 / ABSTR-001: PASS only if any new helper stays bounded to the two in-scope artifact families and does not become a generic report framework.
- PERSIST-001 / STATE-001: PASS. No new persisted truth or lifecycle family is planned.
- XCUT-001 / LAYER-001: PASS. Extend current registry and presenters; do not create parallel operator language.
- UI-SEM-001 / UI-FIL-001 / UI-COV-001: PASS. Existing native surfaces only; no new page family or asset strategy.
- BADGE-001: PASS. Existing badge and artifact-truth semantics remain authoritative.
Test Governance Check
- Test purpose / classification by changed surface: Unit for adapter resolution, proof logic, reconciliation-metadata shape, and idempotency; Feature for run finalization, scope-safe links, and disclosure-layer behavior; Browser for existing Operations or artifact surface wording if it materially changes
- Affected validation lanes: fast-feedback, confidence, browser
- Why this lane mix is the narrowest sufficient proof: the feature is primarily service and model coordination with a small amount of operator-visible copy and link fallout; no PGSQL-only schema behavior is introduced
- Narrowest proving command(s):
cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Unit/Support/Operations/Reconciliation tests/Feature/Operations/Spec361*cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Feature/Evidence/GenerateEvidenceSnapshotJobTest.php tests/Feature/Evidence/EvidenceSnapshotResourceTest.phpcd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/ReviewPack/Spec347ReviewPackOutputContractTest.phpcd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec361ArtifactReconciliationSmokeTest.php
- Fixture / helper / factory / seed / context cost risks: existing workspace/environment and artifact factories only; no new global defaults should be introduced
- Expensive defaults or shared helper growth introduced?: no
- Heavy-family additions, promotions, or visibility changes: one explicit browser smoke only
- Surface-class relief / special coverage rule: monitoring-state-page
- Closing validation and reviewer handoff: reviewers should verify that
StoredReportfamilies stay unsupported in Spec 361, that adapters never mutate artifacts, thatcontext.reconciliationstays canonical and idempotent, and that no new operation type or asset strategy slips into scope - Budget / baseline / trend follow-up: none expected
- Review-stop questions: does the feature overclaim generic report success, add persistence, or invent a new artifact lifecycle model?
- Escalation path: document-in-feature if stored-report proof remains insufficient; reject-or-split if implementation tries to widen scope
- Active feature PR close-out entry: Guardrail / Smoke Coverage
- Why no dedicated follow-up spec is needed: Evidence Snapshot and Review Pack already have strong repo-real proof surfaces. Only generic stored-report causality is deferred explicitly to a future follow-up spec if the repo ever gains a direct proof contract.
Repo-Verified Runtime Surfaces Likely Affected
apps/platform/app/Services/AdapterRunReconciler.phpapps/platform/app/Services/OperationRunService.phpapps/platform/app/Models/OperationRun.phpapps/platform/app/Models/EvidenceSnapshot.phpapps/platform/app/Models/ReviewPack.phpapps/platform/app/Models/StoredReport.php(context only unless proof is stronger than expected)apps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationRegistry.phpapps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationAdapter.phpapps/platform/app/Support/OperationRunLinks.phpapps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.phpapps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.phpapps/platform/app/Support/OperationCatalog.phpapps/platform/app/Support/OperationRunType.phpapps/platform/app/Services/Evidence/EvidenceSnapshotService.phpapps/platform/app/Services/ReviewPackService.phpapps/platform/app/Filament/Pages/Monitoring/Operations.phpapps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.phpapps/platform/app/Filament/Resources/EvidenceSnapshotResource.phpapps/platform/app/Filament/Resources/ReviewPackResource.phpapps/platform/tests/Feature/Operations/*apps/platform/tests/Feature/Evidence/*apps/platform/tests/Feature/ReviewPack/*apps/platform/tests/Browser/Spec360OperationRunCanonicalCutoverSmokeTest.phpand new Spec 361 smoke coverage as needed
Technical Approach
- Verify the exact current repo-real operation types, artifact models, and status/fingerprint/scope fields before runtime edits.
- Reuse the current reconciliation registry and service-owned write seam.
- Add bounded, read-only adapters for
EvidenceSnapshotandReviewPackonly. - Keep generic
StoredReportfamilies fail-closed in Spec 361 and record any future direct-proof need as a separate follow-up spec instead of widening this package. - Reuse current operations and artifact-truth presentation seams for operator-facing fallout.
Risk Controls
- Fail closed on ambiguous, expired, partial, missing, or cross-scope artifacts.
- No adapter may write to artifact models or regenerate output.
- No new
stored_report.generateor similar operation type may be introduced. - If generic stored-report proof is still insufficient, the implementation must record an explicit defer note instead of widening scope.
- No new panel/provider, global search, asset registration, or destructive action may be added in this slice.
Implementation Phases
Phase 1: Baseline and Repo-Truth Inventory
Confirm current operation types, adapter seams, and artifact models. Explicitly verify that StoredReport is still weaker than EvidenceSnapshot and ReviewPack.
Phase 2: Canonical Evidence Snapshot Reconciliation
Add the evidence adapter, bounded proof checks, and focused operations/evidence tests.
Phase 3: Canonical Review Pack Reconciliation
Add the review-pack adapter, bounded proof checks, current operations/detail fallout, and focused review-pack tests.
Phase 4: Unsupported Generic Report-Family Handling
Keep permission.posture.check and entra.admin_roles.scan honest and diagnostic-first. Record defer/follow-up instead of inventing new truth.
Phase 5: Validation and Close-Out
Run scoped Pest and Browser validation, confirm no migration/assets/panel drift, and record which artifact families were reconciled versus explicitly deferred.
Project Structure
Documentation (this feature)
specs/361-report-evidence-reconciliation/
├── spec.md
├── plan.md
├── tasks.md
└── checklists/requirements.md
Source Code (repository root)
apps/platform/app/Services/
apps/platform/app/Support/Operations/Reconciliation/
apps/platform/app/Support/OpsUx/
apps/platform/app/Support/Ui/GovernanceArtifactTruth/
apps/platform/app/Filament/Pages/
apps/platform/app/Filament/Resources/
apps/platform/tests/Unit/
apps/platform/tests/Feature/
apps/platform/tests/Browser/
Assumptions
- The merged Spec 359 baseline and current
context.dispatchseam remain inplatform-dev. EvidenceSnapshotandReviewPackretain their current status, fingerprint, and scope semantics.- No production-compatibility requirement exists that would justify weak generic stored-report heuristics.
Open Preparation Decision
Generic StoredReport reconciliation is intentionally excluded from the initial safe implementation slice because the current model lacks direct operation_run_id and readiness truth. This is not a blocker: the spec is explicitly narrowed around EvidenceSnapshot and ReviewPack, and unsupported report families must remain fail-closed.