# Decision Register Reconciliation ## Executive Conclusion Decision Register is repo-verified and implemented as the bounded Spec 265 operator register over existing `FindingException` and append-only `FindingExceptionDecision` truth. A broad new `Decision Register v1` or `Decision Register & Approval Workflow v1` spec should not be created. Spec 265 runtime is usable: the `/admin/governance/decisions` page exists, is registered in the admin panel, is backed by `GovernanceDecisionRegisterBuilder`, links into the existing FindingException detail surface, and focused tests pass. Sellability classification: `partial productization`. Reason: the operator-facing register, source linkage, workspace/environment isolation, detail handoff, and existing approval/closure audit semantics are implemented. The remaining gap is not a rebuild; it is a narrow productization gap around direct evidence/report/OperationRun/review-pack link polish and customer-safe decision consumption readiness. Recommended next action: `narrow follow-up spec required`. Primary follow-up candidate: `decision-register-evidence-operationrun-link-polish`. ## Scope Boundary - `repo-verified`: this reconciliation inspected specs, runtime, tests, product docs, and validation output. - `not applicable`: no runtime implementation was performed for Spec 306. - `not applicable`: no migrations, models, services, Filament pages/resources, routes, providers, jobs, policies, UI assets, or tests were changed. - `follow-up required`: product docs needed minimal sync because they still framed Decision Register as missing or future-only. ## Inputs Reviewed Specs and audits: - `specs/265-decision-register-approval/spec.md` - `specs/265-decision-register-approval/plan.md` - `specs/265-decision-register-approval/tasks.md` - `specs/265-decision-register-approval/checklists/requirements.md` - `specs/305-feature-readiness-gate-audit/feature-readiness-audit.md` - `specs/306-decision-register-reconciliation/spec.md` - `specs/306-decision-register-reconciliation/plan.md` - `specs/306-decision-register-reconciliation/tasks.md` Runtime evidence: - `apps/platform/app/Filament/Pages/Governance/DecisionRegister.php` - `apps/platform/resources/views/filament/pages/governance/decision-register.blade.php` - `apps/platform/app/Support/GovernanceDecisions/GovernanceDecisionRegisterBuilder.php` - `apps/platform/app/Filament/Pages/Governance/GovernanceInbox.php` - `apps/platform/app/Support/GovernanceInbox/GovernanceInboxSectionBuilder.php` - `apps/platform/app/Filament/Resources/FindingExceptionResource.php` - `apps/platform/app/Filament/Resources/FindingExceptionResource/Pages/ViewFindingException.php` - `apps/platform/app/Services/Findings/FindingExceptionService.php` - `apps/platform/app/Models/FindingException.php` - `apps/platform/app/Models/FindingExceptionDecision.php` - `apps/platform/app/Models/FindingExceptionEvidenceReference.php` - `apps/platform/app/Providers/Filament/AdminPanelProvider.php` - `apps/platform/bootstrap/providers.php` - `apps/platform/database/migrations/2026_03_19_000001_create_finding_exceptions_table.php` - `apps/platform/database/migrations/2026_03_19_000002_create_finding_exception_decisions_table.php` - `apps/platform/database/migrations/2026_03_19_000003_create_finding_exception_evidence_references_table.php` Product docs: - `docs/product/spec-candidates.md` - `docs/product/implementation-ledger.md` - `docs/product/roadmap.md` Routes: - Laravel route inspection returned `GET|HEAD admin/governance/decisions` and `GET|HEAD admin/governance/inbox`. ## Spec 265 Summary Spec 265 promised a bounded Decision Register, not a new workflow platform. Scope classification: | Area | Spec 265 promise | Current classification | |---|---|---| | Data model | Reuse `FindingException`, `FindingExceptionDecision`, `FindingExceptionEvidenceReference`; no new `GovernanceDecision` table. | `implemented` | | UI surface | Add one workspace-level `/admin/governance/decisions` Filament page. | `implemented` | | Governance Inbox integration | Keep Governance Inbox as an adjacent decision-entry surface and avoid a second decision truth. | `partial productization` | | Finding integration | Register rows derive from FindingException truth and open the existing detail page. | `implemented` | | Approval semantics | Existing approve/reject actions stay on queue/detail surfaces; no inline register approval. | `implemented` | | Closure semantics | Existing renewal/revocation/rejection state and recently closed register view show closure reason. | `implemented` | | Evidence links | Use existing proof only; missing proof must stay truthful. | `partial productization` | | OperationRun links | Optional deep-link only when current proof already exposes it; no run start path. | `foundation-only` | | RBAC/capabilities | Workspace membership first; view via `FINDING_EXCEPTION_VIEW`; mutations keep existing manage/approve gates. | `implemented` | | Audit/event semantics | Existing FindingExceptionService audit entries stay authoritative. | `implemented` | | Tests | Focused Unit and Feature coverage plus browser smoke allowance. | `implemented` | | Docs | Product docs should stop treating Decision Register as Greenfield. | `stale docs` | Spec 265 tasks are marked complete in `specs/265-decision-register-approval/tasks.md`. Its explicit non-goals were no new decision table, no generic task engine, no customer-facing decision portal, no inline register mutations, no autonomous escalation, no new review-pack workflow, and no new OperationRun start path. ## Runtime Evidence Matrix | Runtime area | Status | Repo evidence | Caveat | |---|---|---|---| | Admin page route | `implemented` | `DecisionRegister` slug is `governance/decisions`; route inspection shows `admin/governance/decisions`. | Route is operator/admin only. | | Panel registration | `implemented` | `AdminPanelProvider` lists `DecisionRegister::class` in `->pages([...])`; `bootstrap/providers.php` registers `AdminPanelProvider`. | No provider change needed. | | Register builder | `implemented` | `GovernanceDecisionRegisterBuilder::build()` derives open and recently closed rows from `FindingException` and `FindingExceptionDecision`. | Builder does not create a persisted decision projection. | | Register UI | `implemented` | `DecisionRegister.php` defines Filament table columns for environment, status, impact, owner, review due, proof, next action, closure reason; Blade view hosts the table and state toggles. | No inline mutation actions. | | Decision detail handoff | `implemented` | `DecisionRegister::decisionUrl()` opens `FindingExceptionResource` view with `CanonicalNavigationContext::forDecisionRegister()`. | Detail page owns lifecycle actions. | | Detail summary/back action | `implemented` | `ViewFindingException` adds `return_to_decision_register` and register-aware subheading when navigation context source is `governance.decision_register`. | Summary is context only, not a separate workflow. | | Decision persistence | `implemented` | `finding_exceptions` has current status, validity, owner, due/review and closure fields; `finding_exception_decisions` stores append-only decision history. | No generic decision table. | | Evidence references | `implemented` | `finding_exception_evidence_references` model and migration exist; detail infolist renders evidence references; register shows proof count from `evidence_summary`. | Direct artifact URLs from register are not fully productized. | | Approval lifecycle | `implemented` | `FindingExceptionService::approve()` and `reject()` write decision rows, state fields, and audit entries. | Actions are outside the register page by design. | | Renewal/revocation lifecycle | `implemented` | `FindingExceptionService::renew()` and `revoke()` write decision rows, state fields, evidence references, and audit entries. | Actions are outside the register page by design. | | Governance Inbox relationship | `partial productization` | `GovernanceInboxSectionBuilder` contains a `finding_exceptions` family and routes to `FindingExceptionsQueue`. | It does not directly route to Decision Register. | | Review/customer workspace relationship | `foundation-only` | `EnvironmentReviewComposer` packages `governance_decisions`; `CustomerReviewWorkspace` summarizes accepted-risk accountability. | Not the same as a customer-safe Decision Register. | | OperationRun relationship | `foundation-only` | Finding and review/report layers carry OperationRun links elsewhere; Spec 265 allowed optional proof links only. | Decision Register itself does not expose direct OperationRun links. | | Audit trail | `implemented` | `FindingExceptionService` logs `FindingExceptionRequested`, `Approved`, `Rejected`, `RenewalRequested`, `Renewed`, and `Revoked` actions. | Register page views are not a new audit stream. | ## Test Evidence Matrix | Test file | What it proves | Validation result | Caveat | |---|---|---|---| | `tests/Unit/Support/GovernanceDecisions/GovernanceDecisionRegisterBuilderTest.php` | Open/recently closed derivation, visible tenant filtering, owner handling, closure reason, next-action labels. | Included in 27 passed / 137 assertions. | Does not prove UI rendering. | | `tests/Feature/Governance/DecisionRegisterPageTest.php` | Page renders open and recently closed rows, hides hidden tenants, shows truthful filtered empty states. | Included in 27 passed / 137 assertions. | Does not prove browser interaction. | | `tests/Feature/Governance/DecisionRegisterAuthorizationTest.php` | Workspace chooser redirect, non-member 404, no-visible-decisions 403, hidden navigation, explicit tenant 404, recently closed redirect. | Included in 27 passed / 137 assertions. | No mutation actions expected. | | `tests/Feature/Findings/FindingExceptionDecisionRegisterNavigationTest.php` | Register row URL preserves navigation context and back link. | Included in 27 passed / 137 assertions. | Link goes to FindingException detail, not a register detail page. | | `tests/Feature/Findings/FindingExceptionDetailDecisionSummaryTest.php` | Detail page keeps existing renew/revoke actions and adds register return action/subheading. | Included in 27 passed / 137 assertions. | Approve/reject are queue-owned in existing flow. | | `tests/Feature/Findings/FindingExceptionDecisionRegisterBoundariesTest.php` | Register remains read-only and excludes terminal rows outside 30-day window. | Included in 27 passed / 137 assertions. | Evidence/OperationRun direct links are not proven here. | | `tests/Unit/Support/GovernanceInbox/GovernanceInboxSectionBuilderTest.php` | Governance Inbox includes finding exception family, source links, canonical order, hidden family behavior. | Included in 27 passed / 137 assertions. | It routes to FindingExceptionsQueue, not Decision Register. | | `tests/Feature/Governance/GovernanceInboxPageTest.php` | Governance Inbox renders attention sections and capability-hidden finding exceptions lane. | Included in 27 passed / 137 assertions. | Not a Decision Register page test. | | `tests/Feature/Governance/GovernanceInboxAuthorizationTest.php` | Governance Inbox workspace redirects, non-member 404, no family 403, tenant-scope 404. | Included in 27 passed / 137 assertions. | Not specific to Decision Register. | | `tests/Unit/Findings/FindingExceptionDecisionTest.php` | Decision rows are append-only: update/delete throw `LogicException`. | 7 passed / 91 assertions with workflow lane. | Unit-only persistence guard. | | `tests/Feature/Findings/FindingExceptionWorkflowTest.php` | Request/approve/reject writes state and audit entries. | 7 passed / 91 assertions with workflow lane. | Uses existing queue/detail flow. | | `tests/Feature/Findings/FindingExceptionRenewalTest.php` | Renewal preserves history, evidence references, approval/rejection semantics, audit entries. | 7 passed / 91 assertions with workflow lane. | Not initiated from register. | | `tests/Feature/Findings/FindingExceptionRevocationTest.php` | Revoke writes terminal state, reason, timestamp, decision history, audit entry. | 7 passed / 91 assertions with workflow lane. | Not initiated from register. | | Evidence/review/customer workspace tests | EvidenceSnapshot, EnvironmentReview, CustomerReviewWorkspace, pack access, launch links, artifact deep links. | 51 passed / 362 assertions. | Supporting evidence only, not direct register productization. | | OperationRun/link guard tests | Operation dashboard drill-through, legacy run route guards, provider redirects, canonical environment route, policy-version links. | 15 passed / 98 assertions. | Supporting link/route evidence only. | ## Product Docs Drift | Product doc | Drift classification | Repo evidence | Minimal sync performed | |---|---|---|---| | `docs/product/spec-candidates.md` | `stale docs`, understate repo truth, duplicate candidate risk | It listed broad Decision Register & Approval Workflow v1 as an open Priority 1 candidate even though Spec 265/runtime/tests exist. | Yes: broad Greenfield candidate moved to reconciled Spec 265 truth and narrowed follow-up. | | `docs/product/implementation-ledger.md` | `stale docs`, understate repo truth | It listed Decision Register & Approval Workflow v1 under Not Implemented and as still missing. | Yes: added Decision Register operator surface truth and replaced broad missing gap with narrow productization gap. | | `docs/product/roadmap.md` | `stale docs`, understate repo truth | It said bounded decision-register follow-through was still open and ranked broad Decision Register v1 first. | Yes: small notes now say Spec 265 register is repo-verified and only narrow follow-up remains. | ## Capability Matrix | Capability | Status | Repo evidence | Test evidence | Caveat | Recommended action | |---|---|---|---|---|---| | Decision Register page | `implemented` | `DecisionRegister.php`, Blade host, admin route `admin/governance/decisions` | `DecisionRegisterPageTest`, `DecisionRegisterAuthorizationTest` | Operator/admin only. | Keep; do not rebuild. | | Decision detail or summary surface | `implemented` | `ViewFindingException`, `FindingExceptionResource::infolist()` | `FindingExceptionDetailDecisionSummaryTest` | Detail is FindingException detail, not a separate decision detail. | Keep detail-owned lifecycle. | | Decision source linkage | `implemented` | `decisionUrl()` uses `FindingExceptionResource::getUrl()` and `CanonicalNavigationContext` | `FindingExceptionDecisionRegisterNavigationTest` | Link source is accepted-risk exception truth. | Keep. | | FindingException integration | `implemented` | `FindingException`, `FindingExceptionDecision`, service and resource | Decision Register and FindingException workflow tests | Register covers this decision family only. | Keep as bounded v1 truth. | | Governance Inbox integration | `partial productization` | `GovernanceInboxSectionBuilder` finding exception family routes to queue | GovernanceInbox tests | No direct Decision Register CTA. | Consider separate IA polish only if needed. | | Owner/assignment semantics | `implemented` | `owner_user_id`, owner relationship, register owner column, builder owner_name | Builder and page tests | Missing owner remains visible. | Keep. | | Due state semantics | `implemented` | `review_due_at`, `expires_at`, register review due column, next action labels | Builder/page tests | No shared due-state taxonomy beyond current exception logic. | Keep for v1; avoid widening. | | Approval semantics | `implemented` | `FindingExceptionService::approve()` / `reject()`, queue/detail actions | Workflow tests | Not inline on register by design. | Keep existing owner surface. | | Closure semantics | `implemented` | rejected/revoked/superseded terminal state, reasons, timestamps, recently closed window | Boundary/workflow/revocation tests | Closed window is 30 days. | Keep. | | Audit/event semantics | `implemented` | `AuditActionId` and `FindingExceptionService` AuditLogger calls | Workflow/renewal/revocation tests | No register page-view audit. | Keep existing mutation audit trail. | | RBAC/capability enforcement | `implemented` | `DecisionRegister::canAccess()`, `FINDING_EXCEPTION_VIEW`, detail manage/approve gates | Authorization and workflow tests | Register uses view capability; mutations use existing manage/approve gates. | Keep. | | Workspace isolation | `implemented` | Workspace context checks and workspace-scoped queries | Authorization tests | No visible rows returns 403 for default unfiltered register. | Keep. | | Environment isolation | `implemented` | Tenant filters validated against visible decision tenants; out-of-scope tenant 404 | Page/authorization tests | Filtered empty state differs from out-of-scope 404. | Keep. | | Evidence/report linkage | `partial productization` | `evidence_summary` count on register; `evidenceReferences` detail section | Renewal test; EvidenceSnapshot tests support artifact truth | Direct evidence/report links from register are not fully productized. | `follow-up required`: link polish. | | OperationRun linkage | `foundation-only` | `OperationRunLinks` exists elsewhere; reviews/findings can carry run references | OperationRun/link guard tests | Decision Register does not expose direct run links. | Include in narrow link-polish follow-up. | | Review/review-pack linkage | `foundation-only` | `EnvironmentReviewComposer` packages governance decisions; review packs have operation/evidence links | Evidence/review/customer workspace tests | Not a direct Decision Register review-pack inclusion. | Adjacent follow-up candidate only. | | Customer-safe consumption readiness | `productization gap` | CustomerReviewWorkspace summarizes accepted-risk accountability; Decision Register remains admin/operator | CustomerReviewWorkspace tests | Customer-safe Decision Register output is not implemented. | Adjacent follow-up after link polish. | | Product docs alignment | `stale docs` | Product docs listed broad v1 as missing/future | This artifact and docs diff | Product docs were corrected minimally. | Keep docs synchronized after 307. | ## Sellability Classification Classification: `partial productization`. Short reason: Decision Register is implemented and test-proven for operator use, but not yet `near sellable` or `sellable` as a decision product layer because direct proof links, OperationRun/review-pack linkage, and customer-safe consumption remain productization gaps. It is not `foundation-only` because the operator-facing page, row model, navigation, authorization, and detail handoff are implemented. It is not `not implemented` because Spec 265 runtime and tests are repo-verified. ## Open Gaps | Gap | Status | Evidence | Recommended action | |---|---|---|---| | Broad product docs still treated Decision Register as future-only before this spec. | `stale docs` | Product-doc references in spec-candidates, ledger, roadmap. | Minimal docs sync completed under Spec 306. | | Register shows proof count but not direct evidence/report artifact links. | `productization gap` | `DecisionRegister.php` reads `evidence_summary.reference_count`; detail renders evidence references. | Primary 307 follow-up. | | Decision Register does not expose direct OperationRun links. | `productization gap` | OperationRun link helpers exist elsewhere, but no direct register/run link in `DecisionRegister.php` or builder. | Primary 307 follow-up. | | Decision Register is not included as a customer-safe review-pack/register surface. | `productization gap` | CustomerReviewWorkspace and EnvironmentReviewComposer handle accepted-risk/governance-decision summaries, not a customer-safe register. | Adjacent follow-up, not bundled unless 307 remains narrow. | | Governance Inbox does not directly route to Decision Register. | `partial productization` | Governance Inbox finding-exception family routes to FindingExceptionsQueue. | Optional IA polish only if product need is proven. | ## Recommended Next Action Recommended next action category: `narrow follow-up spec required`. 307 should be a small Decision Register follow-up, not a broad feature restart. Recommended 307 name: ```text 307-decision-register-evidence-operationrun-link-polish ``` Recommended 307 scope: - expose direct evidence/report proof links where existing `FindingExceptionEvidenceReference`, `EvidenceSnapshot`, `StoredReport`, or review-pack truth already exists - expose direct OperationRun links only through existing helpers and only when current truth already has a run reference - preserve FindingException as decision truth - preserve existing approval/closure actions on queue/detail surfaces - preserve workspace/environment isolation and non-member/out-of-scope denial semantics - add no new decision table, no workflow engine, no review-pack redesign, no customer portal ## Candidate Follow-ups Primary: - `decision-register-evidence-operationrun-link-polish` - `follow-up required` Adjacent candidates, not part of the primary 307 unless explicitly split: - `decision-register-review-pack-inclusion` - `productization gap` - `decision-register-customer-safe-summary` - `productization gap` - `decision-register-governance-inbox-cta-polish` - `partial productization` Do not name the follow-up: - `Decision Register v1` - `Decision-Based Governance Inbox v1` - `Governance Workflow Platform` - `Approval Engine` ## Validation Evidence Focused Decision Register / Governance / FindingException lane: ```bash export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/GovernanceDecisions/GovernanceDecisionRegisterBuilderTest.php tests/Unit/Support/GovernanceInbox/GovernanceInboxSectionBuilderTest.php tests/Feature/Governance/DecisionRegisterPageTest.php tests/Feature/Governance/DecisionRegisterAuthorizationTest.php tests/Feature/Governance/GovernanceInboxPageTest.php tests/Feature/Governance/GovernanceInboxAuthorizationTest.php tests/Feature/Findings/FindingExceptionDecisionRegisterNavigationTest.php tests/Feature/Findings/FindingExceptionDetailDecisionSummaryTest.php tests/Feature/Findings/FindingExceptionDecisionRegisterBoundariesTest.php ``` Result: passed, 27 tests, 137 assertions. Supporting Evidence / Review / Customer Review / artifact link lane: ```bash export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Evidence/EvidenceSnapshotResourceTest.php tests/Feature/Evidence/EvidenceSnapshotAuditLogTest.php tests/Feature/EnvironmentReview/EnvironmentReviewAuditLogTest.php tests/Feature/EnvironmentReview/EnvironmentReviewRegisterTest.php tests/Feature/EnvironmentReview/EnvironmentReviewRegisterRbacTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php tests/Feature/Filament/GovernanceArtifacts/GovernanceArtifactDeepLinkContractTest.php ``` Result: passed, 51 tests, 362 assertions. Supporting OperationRun / link guard lane: ```bash export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Monitoring/OperationsDashboardDrillthroughTest.php tests/Feature/Operations/LegacyRunRoutesNotFoundTest.php tests/Feature/ProviderConnections/LegacyRedirectTest.php tests/Feature/RequiredPermissions/RequiredPermissionsLegacyRouteTest.php tests/Feature/Guards/ManagedEnvironmentCanonicalRouteContractTest.php tests/Feature/Filament/PolicyVersionResolvedReferenceLinksTest.php ``` Result: passed, 15 tests, 98 assertions. FindingException lifecycle / audit lane: ```bash export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Findings/FindingExceptionDecisionTest.php tests/Feature/Findings/FindingExceptionWorkflowTest.php tests/Feature/Findings/FindingExceptionRenewalTest.php tests/Feature/Findings/FindingExceptionRevocationTest.php ``` Result: passed, 7 tests, 91 assertions. Browser smoke: `not applicable` for Spec 306 because no runtime UI, route, asset, or frontend behavior changed. Existing Spec 265 browser smoke remains repository evidence, but it was not rerun for this docs-only reconciliation. Whitespace validation: ```bash git diff --check ``` Result: passed, no whitespace errors. Scope validation: ```bash git status --short --branch ``` Result: passed. Changed files are limited to `docs/product/spec-candidates.md`, `docs/product/implementation-ledger.md`, `docs/product/roadmap.md`, and `specs/306-decision-register-reconciliation/`. ## Close-Out Notes - Files created/updated under Spec 306: `spec.md`, `plan.md`, `tasks.md`, `checklists/requirements.md`, and `decision-register-reconciliation.md`. - Product docs changed: `docs/product/spec-candidates.md`, `docs/product/implementation-ledger.md`, `docs/product/roadmap.md`. - Runtime files changed: none. - Spec 265 status summary: repo-verified bounded operator Decision Register implemented over existing FindingException decision truth. - Runtime classification: `implemented` for operator register; `partial productization` overall due link/customer-safe gaps. - Sellability classification: `partial productization`. - Recommended next action: `narrow follow-up spec required`. - 307 recommendation: Decision Register follow-up, specifically `decision-register-evidence-operationrun-link-polish`. - Broad Greenfield Decision Register duplication: explicitly rejected. - Focused test results: 27/137 Decision Register lane, 51/362 Evidence/Review lane, 15/98 OperationRun/link lane, 7/91 FindingException lifecycle lane, all passed. - `git diff --check`: passed, no output. - Scope check: passed; no `apps/platform/app`, `apps/platform/database`, `apps/platform/routes`, `apps/platform/resources`, `apps/platform/tests`, runtime config, providers, jobs, policies, services, UI assets, or migrations changed.