TenantAtlas/specs/306-decision-register-reconciliation/decision-register-reconciliation.md
ahmido ba0b6ec07e docs: reconcile decision register product truth (#361)
## Summary
- add the Spec 306 docs-only reconciliation package under `specs/306-decision-register-reconciliation/`
- reconcile existing Spec 265, runtime pages/builders/tests, and product docs so Decision Register is treated as repo-verified rather than a missing greenfield feature
- minimally sync `docs/product/implementation-ledger.md`, `docs/product/roadmap.md`, and `docs/product/spec-candidates.md` to reflect current repo truth
- classify Decision Register as `partial productization`, not `not implemented`
- recommend one narrow next step instead of a broad restart: `307-decision-register-evidence-operationrun-link-polish`

## Scope
- docs-only reconciliation and product-doc truth sync
- no application runtime changes
- no migrations
- no routes, policies, providers, or UI asset changes
- no test edits

## Key Conclusions Recorded
- a broad new `Decision Register v1` or `Decision Register & Approval Workflow v1` spec should not be created
- Spec 265 runtime is repo-verified and usable on `/admin/governance/decisions`
- the remaining gap is narrow productization around direct evidence/report links, OperationRun links, and adjacent customer-safe consumption polish
- product docs previously understated repo truth and were corrected minimally in this branch

## Filament / Runtime Notes
- remains compliant with Filament v5 on Livewire v4
- no provider registration changes; provider registration location remains `apps/platform/bootstrap/providers.php`
- no globally searchable resources were added or changed in this docs-only PR
- no destructive actions were added or changed
- no asset registration changes; existing deploy posture for `cd apps/platform && php artisan filament:assets` is unchanged

## Validation Notes
- the reconciliation artifact records the focused existing test evidence used to support the product-truth claims
- no new runtime validation was executed in this turn beyond committing and pushing the docs-only package

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #361
2026-05-15 10:18:48 +00:00

26 KiB

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 category: narrow follow-up spec required.

307 should be a small Decision Register follow-up, not a broad feature restart.

Recommended 307 name:

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:

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:

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:

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:

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:

git diff --check

Result: passed, no whitespace errors.

Scope validation:

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.