Implemented report evidence reconciliation. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #432
224 lines
15 KiB
Markdown
224 lines
15 KiB
Markdown
# 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.php`
|
|
- `apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php`
|
|
- `apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php`
|
|
- `apps/platform/app/Filament/Resources/ReviewPackResource.php`
|
|
- **No-impact class, if applicable**: N/A
|
|
- **Native vs custom classification summary**: native Filament surfaces with shared `OperationRun` and artifact-truth helpers
|
|
- **Shared-family relevance**: `OperationRun` monitoring 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\AdapterRunReconciler`
|
|
- `App\Services\OperationRunService`
|
|
- `App\Support\Operations\Reconciliation\OperationRunReconciliationRegistry`
|
|
- `App\Support\OperationRunLinks`
|
|
- `App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter`
|
|
- `App\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 `StoredReport` causality 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. `OperationRun` remains 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.php`
|
|
- `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/ReviewPack/Spec347ReviewPackOutputContractTest.php`
|
|
- `cd 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 `StoredReport` families stay unsupported in Spec 361, that adapters never mutate artifacts, that `context.reconciliation` stays 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.php`
|
|
- `apps/platform/app/Services/OperationRunService.php`
|
|
- `apps/platform/app/Models/OperationRun.php`
|
|
- `apps/platform/app/Models/EvidenceSnapshot.php`
|
|
- `apps/platform/app/Models/ReviewPack.php`
|
|
- `apps/platform/app/Models/StoredReport.php` (context only unless proof is stronger than expected)
|
|
- `apps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationRegistry.php`
|
|
- `apps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationAdapter.php`
|
|
- `apps/platform/app/Support/OperationRunLinks.php`
|
|
- `apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php`
|
|
- `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php`
|
|
- `apps/platform/app/Support/OperationCatalog.php`
|
|
- `apps/platform/app/Support/OperationRunType.php`
|
|
- `apps/platform/app/Services/Evidence/EvidenceSnapshotService.php`
|
|
- `apps/platform/app/Services/ReviewPackService.php`
|
|
- `apps/platform/app/Filament/Pages/Monitoring/Operations.php`
|
|
- `apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php`
|
|
- `apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php`
|
|
- `apps/platform/app/Filament/Resources/ReviewPackResource.php`
|
|
- `apps/platform/tests/Feature/Operations/*`
|
|
- `apps/platform/tests/Feature/Evidence/*`
|
|
- `apps/platform/tests/Feature/ReviewPack/*`
|
|
- `apps/platform/tests/Browser/Spec360OperationRunCanonicalCutoverSmokeTest.php` and new Spec 361 smoke coverage as needed
|
|
|
|
## Technical Approach
|
|
|
|
1. Verify the exact current repo-real operation types, artifact models, and status/fingerprint/scope fields before runtime edits.
|
|
2. Reuse the current reconciliation registry and service-owned write seam.
|
|
3. Add bounded, read-only adapters for `EvidenceSnapshot` and `ReviewPack` only.
|
|
4. Keep generic `StoredReport` families fail-closed in Spec 361 and record any future direct-proof need as a separate follow-up spec instead of widening this package.
|
|
5. 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.generate` or 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)
|
|
|
|
```text
|
|
specs/361-report-evidence-reconciliation/
|
|
├── spec.md
|
|
├── plan.md
|
|
├── tasks.md
|
|
└── checklists/requirements.md
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
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.dispatch` seam remain in `platform-dev`.
|
|
- `EvidenceSnapshot` and `ReviewPack` retain 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.
|