Implemented report evidence reconciliation. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #432
39 KiB
Feature Specification: Spec 361 - Report and Evidence Reconciliation Adapters
Feature Branch: 361-report-evidence-reconciliation
Created: 2026-06-06
Status: Draft
Input: User-provided Spec 361 draft from /Users/ahmeddarrazi/.codex/attachments/a0817e2c-be58-40c1-9108-1e1880e423d4/pasted-text.txt, reconciled against current repo truth
Spec Candidate Check (mandatory - SPEC-GATE-001)
- Problem: current
OperationRunmonitoring can still leave report-family or evidence-family generation runs queued, running, or stale even after the repo already has a scope-safe artifact that proves the intended output exists. - Today's failure: operators can be forced to compare Operations, Review Pack, Evidence Snapshot, and report surfaces manually to decide whether a run is genuinely unfinished or whether the artifact already exists and the run is now ghost state.
- User-visible improvement: existing operations surfaces, related-artifact links, and current artifact truth surfaces will show one honest execution story: reconcile only when a safe artifact already proves success, otherwise stay pending or attention-required without false calm.
- Smallest enterprise-capable version: extend the current
OperationRunreconciliation registry for repo-verifiable artifact families only:tenant.evidence.snapshot.generateandenvironment.review_pack.generate. Keep genericStoredReportreconciliation fail-closed unless current repo truth already proves direct causal linkage without new persistence. - Explicit non-goals: no new table, no new
OperationRunstatus column, no new queue family, no new report renderer, no new PDF/HTML work, no newstored_report.generateoperation type, no sync/backup/restore adapter expansion, no customer portal work, no destructive action changes, and no legacy compatibility layer. - Permanent complexity imported: two bounded reconciliation adapters, at most one small derived proof/helper path, focused Unit/Feature/Browser tests, and small operator-facing copy or link adjustments on existing monitoring and artifact surfaces.
- Why now: Spec 359 merged the review-compose adapter baseline, and current
platform-devalready contains the shared registry,context.reconciliation, andcontext.dispatchseams. The next repo-real trust gap is artifact-backed reconciliation for evidence and review-pack outputs. - Why not local: fixing one banner, one presenter, or one detail page would not repair the shared run lifecycle truth across Operations, run detail, Review Pack, and Evidence Snapshot surfaces.
- Approval class: Core Enterprise
- Red flags triggered: new abstraction/helper pressure and shared operator-facing status semantics. Defense: the repo already has real adapter-backed reconciliation consumers (
restore.execute,environment.review.compose), and queue correctness plus audit-visible truth justify a bounded extension instead of more special cases. - Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 1 | Wiederverwendung: 2 | Gesamt: 10/12
- Decision: approve
Repo Truth Reconciliation
The user draft is directionally correct, but current repo truth narrows the safe implementation slice:
docs/product/spec-candidates.mdstill recordsno safe automatic next-best-prep target. This package is therefore an explicit manual promotion from the user-provided draft, not an auto-selected queue item.platform-devalready contains the merged Spec 359 runtime baseline at3a750726 feat: implement review compose reconciliation adapter (spec 359) (#430), plus the sharedOperationRunReconciliationRegistry,OperationRunCorrelationResolver, andcontext.dispatchwrite path inOperationRunService.EvidenceSnapshotandReviewPackare safe primary artifact families for this slice because they already carry workspace/environment scope, lifecycle status, fingerprint data, and directoperation_run_idlinkage.- Generic
StoredReporttruth is weaker than the draft assumes: the model has no directoperation_run_id, no status enum, and no canonical readiness lifecycle. Spec 361 therefore treats generic report reconciliation forpermission.posture.checkandentra.admin_roles.scanas explicitly unsupported. This package must not add anyStoredReport-backed success path; any future direct report-artifact proof contract belongs in a separate follow-up spec. - Existing review-pack productization and report-output semantics from Specs 347, 349, 351, 356, and 357 are context only. This spec must reuse those seams and must not reopen rendered-report or disclosure-policy scope.
- Related existing specs are context only and must not be rewritten:
- Spec 358 - generic queue-truth baseline
- Spec 359 - merged review-compose adapter baseline
- Spec 360 - canonical cutover follow-through context
- Specs 347/349/351/356/357 - review-pack and rendered-report productization context
Spec Scope Fields (mandatory)
- Scope: workspace, tenant, canonical-view
- Primary Routes:
/admin/workspaces/{workspace}/operations/admin/workspaces/{workspace}/operations/{run}- existing environment-scoped Evidence Snapshot routes via
App\Filament\Resources\EvidenceSnapshotResource - existing environment-scoped Review Pack routes via
App\Filament\Resources\ReviewPackResource
- Data Ownership:
operation_runsremain the only execution and reconciliation truthevidence_snapshotsremain the only persisted evidence-generation truthreview_packsremain the only persisted review-pack output truthstored_reportsremain supporting artifact context only unless current repo truth proves safe direct reconciliation without new persistence
- RBAC:
- existing workspace-first
OperationRunaccess rules remain authoritative - existing environment-scoped
EvidenceSnapshotandReviewPackpolicies remain authoritative - non-members and out-of-scope actors remain
404 - no new capability strings are introduced
- existing workspace-first
For canonical-view specs, the spec MUST define:
- Default filter behavior when tenant-context is active: the Operations hub remains workspace-scoped with explicit environment filters; adapter decisions must rely on the run's recorded workspace/environment scope and never on remembered environment state or current page filters.
- Explicit entitlement checks preventing cross-tenant leakage: no adapter may reconcile to an artifact outside the run's workspace and managed environment, and any related-artifact link must resolve only through current-scope canonical routes.
UI Surface Impact (mandatory - UI-COV-001)
Does this spec add, remove, rename, or materially change any reachable UI surface?
- No UI surface impact
- Existing page changed
- New page/route added
- Navigation changed
- Filament panel/provider surface changed
- New modal/drawer/wizard/action added
- New table/form/state added
- Customer-facing surface changed
- Dangerous action changed
- Status/evidence/review presentation changed
- Workspace/environment context presentation changed
UI/Productization Coverage (mandatory when UI Surface Impact is not "No UI surface impact")
- Route/page/surface:
- workspace operations hub (
App\Filament\Pages\Monitoring\Operations) - canonical run detail (
App\Filament\Pages\Operations\TenantlessOperationRunViewer) - existing Evidence Snapshot related-context and detail surfaces
- existing Review Pack related-context and detail surfaces
- workspace operations hub (
- Current or new page archetype: existing monitoring/detail family plus existing governance-artifact detail family
- Design depth: Domain Pattern Surface
- Repo-truth level: repo-verified
- Existing pattern reused: current
OperationRunmonitoring family, current artifact-truth/detail family, current related-artifact link conventions - New pattern required: none; this is a run-truth follow-through inside existing pattern families
- Screenshot required: no; one bounded browser smoke is sufficient unless implementation produces a materially new visible hierarchy
- Page audit required: no new page-report identity is required; existing monitoring and artifact page reports remain the anchors
- Customer-safe review required: no; touched copy remains operator-facing and diagnostic
- Dangerous-action review required: no; this spec adds no new mutation surface and no destructive action
- Coverage files updated or explicitly not needed:
docs/ui-ux-enterprise-audit/route-inventory.mddocs/ui-ux-enterprise-audit/design-coverage-matrix.mddocs/ui-ux-enterprise-audit/page-reports/...docs/ui-ux-enterprise-audit/strategic-surfaces.mddocs/ui-ux-enterprise-audit/grouped-follow-up-candidates.mddocs/ui-ux-enterprise-audit/unresolved-pages.mdN/A - existing monitoring and artifact page families already cover these reachable surfaces
- No-impact rationale when applicable: no new page family, route family, or navigation entry is added; the slice stays inside existing operations, review-pack, and evidence artifact surfaces
Cross-Cutting / Shared Pattern Reuse (mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write N/A - no shared interaction family touched)
- Cross-cutting feature?: yes
- Interaction class(es): status messaging, action links, evidence/report viewers, related-artifact diagnostics
- Systems touched:
App\Services\AdapterRunReconcilerApp\Services\OperationRunServiceApp\Support\Operations\Reconciliation\OperationRunReconciliationRegistryApp\Support\OperationRunLinksApp\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenterApp\Support\OpsUx\GovernanceRunDiagnosticSummaryBuilder- existing Review Pack and Evidence Snapshot resource/detail surfaces
- Existing pattern(s) to extend: existing reconciliation metadata path, existing operations monitoring/detail language, current artifact-truth/detail family, and current canonical artifact links
- Shared contract / presenter / builder / renderer to reuse:
OperationRunService::updateRunWithReconciliation(),OperationRun::reconciliation(),OperationRunLinks,ArtifactTruthPresenter,GovernanceRunDiagnosticSummaryBuilder, and current Evidence Snapshot / Review Pack resources - Why the existing shared path is sufficient or insufficient: the repo already has the right write seam and related-artifact presentation family, but the registry does not yet cover repo-verifiable artifact-backed success for evidence or review-pack outputs.
- Allowed deviation and why: one bounded helper or proof object is allowed only if it removes duplicated scope/completeness checks across the two in-scope adapters. It must stay derived-only and local to current reconciliation work.
- Consistency impact: reconciled evidence or review-pack outcomes must read consistently across start feedback, operations list/detail, and related-artifact views, while unsupported generic stored-report families must stay attention-first instead of silently appearing successful.
- Review focus: no second reconciliation write path, no new stored-report lifecycle model, no artifact mutation from adapters, and no false success from "latest artifact exists" heuristics alone.
OperationRun UX Impact (mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an OperationRun; otherwise write N/A - no OperationRun start or link semantics touched)
- Touches OperationRun start/completion/link UX?: yes, reuse-only
- Shared OperationRun UX contract/layer reused: current
OperationRunService,OperationRunLinks, registry-backed reconciliation, and existing operations monitoring/detail presenters - Delegated start/completion UX behaviors: existing queued toasts, canonical run links, canonical artifact links, current run-enqueued browser events, and current terminal notification path remain unchanged
- Local surface-owned behavior that remains: placement and explanation text only
- Queued DB-notification policy: unchanged
- Terminal notification path: unchanged central lifecycle mechanism
- Exception required?: none
Provider Boundary / Platform Core Check (mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write N/A - no shared provider/platform boundary touched)
- Shared provider/platform boundary touched?: no
- Boundary classification: N/A
- Seams affected: N/A
- Neutral platform terms preserved or introduced:
operation,artifact,review pack,evidence snapshot,reconciliation - Provider-specific semantics retained and why: none
- Why this does not deepen provider coupling accidentally: the slice uses platform-owned artifact and operation truth only
- Follow-up path: none
UI / Surface Guardrail Impact (mandatory when operator-facing surfaces are changed; otherwise write N/A)
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / N/A Note |
|---|---|---|---|---|---|---|
| Operations hub reconciliation copy and related-artifact state | yes | Native Filament + shared presenters | OperationRun monitoring family |
page, detail, URL-query | no | no new action hierarchy |
| Run detail reconciliation diagnostics and related links | yes | Native Filament + shared presenters | OperationRun monitoring family |
detail | no | existing link model stays canonical |
| Evidence Snapshot / Review Pack related-artifact surfaces | yes | Native Filament + shared artifact-truth helpers | artifact detail family | detail | no | no new route family or mutation |
Decision-First Surface Role (mandatory when operator-facing surfaces are changed)
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Operations hub | Primary Decision Surface | Decide whether a run still needs follow-up | lifecycle, outcome, safe related-artifact state, next action | raw failures, reconciliation evidence, artifact details | primary because operators decide whether to wait, inspect, or move on here | stays aligned to monitoring workflow | removes manual cross-checking between run and artifact lists |
| Run detail | Secondary Context Surface | Verify why a run was reconciled or left pending | reconciled reason, related artifact, scope-safe link | full context payload, existing diagnostic sections | secondary because it confirms a decision already hinted in the hub | stays aligned to detail workflow | keeps proof in one canonical place |
| Evidence Snapshot / Review Pack detail | Tertiary Evidence / Diagnostics | Inspect the artifact that justified or blocked reconciliation | current artifact state | payloads, summary metadata, existing artifact diagnostics | tertiary because artifact pages prove evidence after the run decision | stays aligned to current artifact detail workflow | avoids duplicating full artifact truth on the run list |
Audience-Aware Disclosure (mandatory when operator-facing surfaces are changed)
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Operations hub | operator-MSP, support-platform | run status, honest reconciliation state, safe related artifact, next action | failures, related metadata, timestamps after explicit reveal by an actor already entitled to view the run | raw context.reconciliation evidence remains secondary and stays limited to the existing support/platform diagnostics path on the run host |
Open operation or related artifact link |
raw context stays diagnostic-only and is never default-visible | the hub states the outcome once; later sections add proof only |
| Run detail | operator-MSP, support-platform | reconciled or not reconciled state with safe reason | full reconciliation metadata and existing failure detail after explicit reveal by an actor already entitled to view the run | raw payload inspection stays secondary and remains available only through the existing support/platform diagnostics path on the run host | Open related artifact when safe |
low-level payloads remain subordinate and capability-gated where the host already distinguishes support/platform access | no second "success" summary beyond the canonical outcome |
| Evidence Snapshot / Review Pack detail | operator-MSP, support-platform | current artifact state, scope-safe relation to the run, and concise artifact outcome summary | existing artifact diagnostics and related run context after explicit reveal by an actor already entitled to view the artifact | raw/support artifact evidence remains behind the existing host-specific diagnostics or payload affordance and never becomes the default first-read layer | Open related operation when safe |
payloads, fingerprints, and raw evidence stay secondary and host-gated | artifact pages prove or explain one outcome only; they do not restate a competing default-visible success summary |
Layer unlocks for changed surfaces:
- Decision content: any actor who already passes the current workspace/environment and run/artifact view entitlement for the host surface.
- Operator diagnostics: the same entitled actor, but only after an explicit reveal affordance on the host surface.
- Support / raw evidence: only the existing support/platform diagnostics path on the current host surface; this spec introduces no new capability string and no widened raw-evidence audience.
UI/UX Surface Classification (mandatory when operator-facing surfaces are changed)
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Operations hub | Monitoring / Queue / Workbench | Read-only Registry / Report Surface | Open the run or its proven artifact | row click to run detail | required | existing filters and contextual links only | unchanged | /admin/workspaces/{workspace}/operations |
/admin/workspaces/{workspace}/operations/{run} |
workspace route plus explicit environment filter | Operations / Operation | honest lifecycle plus safe artifact state | none |
| Run detail | Record / Detail / Edit | Detail-first Operational Surface | Inspect related artifact proof | canonical detail page | N/A | existing navigation and related links only | unchanged | /admin/workspaces/{workspace}/operations |
/admin/workspaces/{workspace}/operations/{run} |
run-owned workspace/environment scope | Operation | reconciliation outcome and reason | none |
| Evidence Snapshot / Review Pack detail | Record / Detail / Edit | Detail-first Operational Surface | Inspect the artifact proof and, if needed, follow the safe link back to the operation | canonical detail page | N/A | existing related links and host-owned secondary actions only | unchanged | existing Evidence Snapshot / Review Pack collection routes | existing Evidence Snapshot / Review Pack detail routes | artifact-owned workspace/environment scope plus current host context | Evidence Snapshot / Review Pack | current artifact truth and safe relation to the reconciled run | none |
Operator Surface Contract (mandatory when operator-facing surfaces are changed)
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Operations hub | MSP operator | Decide whether the run still needs attention | list/workbench | Is the artifact already proven, or is this run still unfinished? | lifecycle state, reconciled outcome, safe artifact state, next step | raw failures, detailed metadata, timestamps | lifecycle, artifact completeness, scope safety | none | existing inspect/open actions only | none |
| Run detail | MSP operator or support | Confirm why the run reconciled or stayed pending | detail | What exact artifact truth did the run resolve against? | reconciled reason, related artifact, summary counts | raw context.reconciliation, raw context payload, deep diagnostic sections |
lifecycle, artifact completeness, support state | none | open related artifact when safe | none |
| Evidence Snapshot / Review Pack detail | MSP operator or support | Confirm whether the artifact really justifies or blocks reconciliation | detail | Does this artifact safely prove the run outcome for the current scope? | artifact readiness, scope-safe linkage, concise supporting summary | payloads, fingerprints, deeper host diagnostics, and related run context | artifact readiness, completeness/expiration, scope safety | none | open related operation when safe | none |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no
- New persisted entity/table/artifact?: no
- New abstraction?: yes, bounded adapter classes and at most one small derived proof/helper path
- New enum/state/reason family?: no new family; only current reconciliation reason semantics may be reused or narrowly extended if behaviorally required
- New cross-domain UI framework/taxonomy?: no
- Current operator problem: artifact-producing runs can remain queued/running/stale even after the repo already has a safe artifact, forcing manual cross-checks and risking false calm or false alarm.
- Existing structure is insufficient because: the current registry only covers restore and review-compose truth, while evidence and review-pack runs still lack artifact-backed reconciliation even though their artifact models already expose scope, lifecycle, and fingerprint proof.
- Narrowest correct implementation: add only evidence snapshot and review-pack adapters over existing models and write seams; keep generic stored-report reconciliation deferred until direct causal proof exists.
- Ownership cost: adapter maintenance, focused tests, and some monitoring/detail copy review. No migration, new artifact table, or new operator workflow family is introduced.
- Alternative intentionally rejected: a generic "latest artifact exists => mark success" heuristic was rejected because it would overclaim success for unsupported or ambiguous report families, especially
StoredReport. - Release truth: current-release truth
Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Canonical replacement is preferred over preservation.
Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)
- Test purpose / classification: Unit, Feature, Browser
- Validation lane(s): fast-feedback, confidence, browser
- Why this classification and these lanes are sufficient: adapter selection, proof evaluation, and metadata formatting are cheapest in Unit coverage; run finalization, scope safety, and artifact-link behavior require Feature coverage; one bounded Browser smoke is enough for existing Operations and artifact surfaces if visible operator wording changes.
- New or expanded test families: one explicit Spec 361 Unit/Feature family and one bounded Browser smoke
- Fixture / helper cost impact: moderate existing factory usage for
OperationRun,EvidenceSnapshot,ReviewPack,EnvironmentReview, and workspace/environment membership; no new expensive global defaults should be introduced - Heavy-family visibility / justification: no heavy-governance family is added
- Special surface test profile: monitoring-state-page
- Standard-native relief or required special coverage: ordinary Feature coverage for existing Filament surfaces plus one bounded Browser smoke when UI wording changes
- Reviewer handoff: reviewers must confirm generic
StoredReportfamilies stay fail-closed unless safe proof is demonstrated, that adapters do not mutate artifacts, and that proof commands stay scoped to Spec 361 plus contextual artifact regressions only - Budget / baseline / trend impact: none expected beyond one bounded browser smoke
- Escalation needed: document-in-feature if generic stored-report proof remains insufficient; follow-up-spec only if the repo later needs a dedicated stored-report causality contract
- Active feature PR close-out entry: Guardrail / Smoke Coverage
- Planned validation commands:
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.phpcd apps/platform && ./vendor/bin/pint --dirtygit diff --check
User Scenarios & Testing (mandatory)
User Story 1 - Reconcile evidence generation against an existing snapshot (Priority: P1)
An operator sees a queued, running, or stale evidence-generation run and needs the run to finalize honestly when the matching EvidenceSnapshot already exists and is scope-safe, complete, and active.
Why this priority: EvidenceSnapshot already has direct operation_run_id, lifecycle status, completeness state, and fingerprint signals, so this is the safest and highest-confidence artifact-backed reconciliation extension.
Independent Test: seed a queued or stale tenant.evidence.snapshot.generate run plus a matching active, complete snapshot in the same workspace/environment, run reconciliation, and verify the run finalizes successfully with canonical related-artifact metadata.
Acceptance Scenarios:
- Given a queued or stale evidence-generation run and a matching active, complete snapshot with the same scope and fingerprint, When adapter reconciliation runs, Then the run becomes completed/succeeded and links to the snapshot safely.
- Given a queued or stale evidence-generation run and a partial, failed, expired, or wrong-scope snapshot, When adapter reconciliation runs, Then the run does not claim success and remains pending or attention-required.
User Story 2 - Reconcile review-pack generation against an existing pack (Priority: P1)
An operator sees a queued, running, or stale review-pack generation run and needs the run to finalize honestly when the matching ReviewPack already exists, is ready, non-expired, and belongs to the same workspace/environment/review scope.
Why this priority: review-pack output is already customer-facing and productized; ghost run state here directly damages trust in delivered governance artifacts.
Independent Test: seed a queued or stale environment.review_pack.generate run plus a matching ready pack with canonical scope and fingerprint signals, run reconciliation, and verify the run finalizes successfully with canonical related-artifact metadata.
Acceptance Scenarios:
- Given a queued or stale review-pack run and a matching ready, non-expired pack for the same scope, When adapter reconciliation runs, Then the run becomes completed/succeeded and exposes the safe pack link through current operations surfaces.
- Given a queued or stale review-pack run and a generating, failed, expired, incomplete, or wrong-scope pack, When adapter reconciliation runs, Then the run does not claim success and the operator sees honest follow-up state instead.
User Story 3 - Keep unsupported generic report families honest (Priority: P2)
An operator sees a queued or stale run for a report-producing operation such as permission.posture.check or entra.admin_roles.scan and must not see false success merely because a latest StoredReport exists without direct causal proof.
Why this priority: the current StoredReport model is not strong enough to justify blind success. Preserving fail-closed behavior is a product-truth requirement and prevents overclaiming.
Independent Test: seed queued or stale report-producing runs plus retained StoredReport rows and verify the run stays unresolved or diagnostic-first because Spec 361 does not allow any StoredReport-backed success path.
Acceptance Scenarios:
- Given a report-producing run and only a latest retained
StoredReportwith no direct causal proof, When reconciliation runs, Then the run does not finalize as succeeded from that report alone. - Given a future repo-real direct report-artifact proof path is absent, When implementation reaches that branch, Then the feature records a defer/follow-up note instead of inventing a new persistence or lifecycle model.
Edge Cases
- Multiple matching artifacts exist and no single current-scope winner is provable.
- An artifact exists but belongs to another workspace or managed environment.
- A snapshot is
activebutpartial,missing, or otherwise incomplete. - A review pack is
readybut expired or no longer the current export for the review context. - A run already has reconciliation metadata from another source and the adapter should not overwrite terminal truth incorrectly.
- A generic
StoredReportlooks current but still cannot prove causal linkage to the run that is being reconciled.
Requirements (mandatory)
Functional Requirements
- FR-361-001: New artifact-backed reconciliation MUST reuse the current
OperationRunReconciliationRegistry,OperationRunReconciliationAdaptercontract,AdapterRunReconciler, andOperationRunService::updateRunWithReconciliation()write seam. No second registry or direct model write path is allowed. - FR-361-002: The feature MUST implement bounded reconciliation for
tenant.evidence.snapshot.generateusing existingEvidenceSnapshotscope, status, fingerprint, completeness, andoperation_run_idtruth. - FR-361-003: The feature MUST implement bounded reconciliation for
environment.review_pack.generateusing existingReviewPackscope, status, fingerprint, expiration, andoperation_run_idtruth. - FR-361-004: Unsupported generic report families, especially
permission.posture.checkandentra.admin_roles.scan, MUST remain fail-closed in Spec 361 and MUST NOT gain anyStoredReport-backed success path in this package. - FR-361-005: Any shared proof helper introduced for this feature MUST remain derived-only, read-only, and local to current reconciliation scope; it MUST NOT create new persisted truth or a generic artifact workflow engine.
- FR-361-006: Evidence and review-pack adapters MUST validate workspace/environment scope before success. If present, they SHOULD also validate direct
operation_run_id, fingerprint, review scope, or other current repo-real identity signals. - FR-361-007: Evidence reconciliation MUST require a snapshot state that is good enough to prove success:
activeplus non-missing completeness. Partial, failed, expired, stale, or wrong-scope states must not succeed silently. - FR-361-008: Review-pack reconciliation MUST require a pack state that is good enough to prove success:
ready, non-expired, current-scope, and tied to the same review/evidence context when current repo truth exposes those links. - FR-361-009: All successful artifact-backed reconciliation MUST persist canonical metadata only through
context.reconciliation, including reason, adapter key, previous lifecycle state, and related artifact reference. - FR-361-010: Adapters MUST be read-only toward
EvidenceSnapshot,ReviewPack, andStoredReport. They may read and compare; they may not mutate artifact lifecycle or regenerate output. - FR-361-011: Existing operations surfaces MUST explain reconciled or unsupported states calmly and truthfully without adding a new route family, a new page family, or raw storage/debug data as the primary visible message.
- FR-361-012: The feature MUST NOT widen restore, backup, sync, or review-compose behavior beyond the current registry-owned contract.
Non-Functional Requirements
- NFR-361-001: The feature MUST fail closed on ambiguous, partial, expired, stale, or cross-scope artifact states.
- NFR-361-002: The feature MUST preserve auditability by keeping reconciliation writes inside the current
OperationRunlifecycle path. - NFR-361-003: The feature MUST be idempotent; re-running reconciliation over the same eligible artifact must not create duplicate lifecycle churn.
- NFR-361-004: The feature SHOULD avoid migrations. If implementation somehow proves a migration is required, work must stop and spec/plan must be updated before coding further.
- NFR-361-005: The feature MUST not add compatibility shims for pre-production historical report aliases or old fixture shapes.
- NFR-361-006: The feature adds no destructive action, so no new confirmation flows are expected.
- NFR-361-007: Filament and Livewire posture remains current repo truth: Filament v5 on Livewire v4, with provider registration in
apps/platform/bootstrap/providers.php. - NFR-361-008: No new Filament asset registration is allowed;
filament:assetsremains unchanged. - NFR-361-009: Changed operator-facing surfaces MUST keep default-visible decision content above diagnostics, keep raw/support evidence behind existing host-gated reveal paths, and preserve exactly one dominant default next action.
UI Action Matrix (mandatory when Filament is changed)
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Operations hub | apps/platform/app/Filament/Pages/Monitoring/Operations.php |
existing only | row click to canonical detail | existing only | existing only | unchanged | N/A | N/A | existing run lifecycle audit only | no new action |
| Run detail | apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php |
existing only | N/A | N/A | N/A | unchanged | existing navigation only | N/A | existing run lifecycle audit only | no new action |
| Evidence Snapshot detail | apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php |
existing only | row click remains canonical | existing only | existing only | unchanged | existing only | N/A | existing audit only | related run or artifact copy only |
| Review Pack detail | apps/platform/app/Filament/Resources/ReviewPackResource.php |
existing only | row click remains canonical | existing only | existing only | unchanged | existing only | N/A | existing audit only | no new mutation surface |
Key Entities (include if feature involves data)
- OperationRun: persisted execution and reconciliation truth; owns
type,status,outcome,summary_counts, andcontext.reconciliation - EvidenceSnapshot: persisted evidence-generation truth with
operation_run_id, status, completeness state, scope, and fingerprint - ReviewPack: persisted review-pack artifact truth with
operation_run_id, status, scope, expiration, and fingerprint - StoredReport: retained report artifact context only; currently lacks direct causal linkage strong enough for generic reconciliation
- ReconciliationResult / proof helper: bounded derived decision output only; no new persistence
Success Criteria (mandatory)
Measurable Outcomes
- SC-361-001: queued, running, or stale
tenant.evidence.snapshot.generateruns can be reconciled to an existing active, current-scope snapshot without adding new persistence or new operation types. - SC-361-002: queued, running, or stale
environment.review_pack.generateruns can be reconciled to an existing ready, non-expired, current-scope pack without adding new persistence or rendered-report scope. - SC-361-003: operations surfaces show one canonical artifact-backed success or non-success story, and unsupported generic
StoredReportfamilies do not silently appear successful. - SC-361-004: focused Unit, Feature, and bounded Browser validation passes with no new asset strategy, no migration, and no new destructive action.
Assumptions
- Spec 359 runtime is already merged and remains the baseline adapter consumer next to restore reconciliation.
- Current
platform-devalready contains the sharedcontext.dispatchseam andOperationRunCorrelationResolver. EvidenceSnapshotandReviewPacklifecycle fields remain the current repo-real truth for artifact readiness.- Generic
StoredReportcausality is intentionally out of scope unless implementation can prove it without new persistence or compatibility logic.
Risks
- A helper introduced for shared proof checks could drift into a generic artifact framework if review is not strict about the two-family boundary.
- Review-pack or evidence detail copy could overclaim success if it exposes "artifact exists" without retaining completeness or scope checks.
- Implementers may be tempted to rescue generic
StoredReportfamilies with weak heuristics; this must be treated as out-of-scope creep unless the spec is updated first.
Open Questions
- None blocking prep. The main repo-truth deviation is already resolved in this spec: generic
StoredReportreconciliation is not part of the initial safe implementation slice.
Follow-up Spec Candidates
- Stored-report causal reconciliation follow-through: if a future repo slice introduces direct
StoredReportcausal linkage, readiness lifecycle, or canonical report-output proof strong enough for safe success reconciliation, promote a separate follow-up instead of widening Spec 361 silently.