TenantAtlas/specs/250-decision-governance-inbox/research.md
ahmido 72bfb37ba7
Some checks failed
Main Confidence / confidence (push) Failing after 57s
feat: add decision-based governance inbox (#291)
## Summary
- add a read-first governance inbox page at `/admin/governance/inbox`
- aggregate assigned findings, intake, stale operations, alert-delivery failures, and review follow-up into one canonical routing surface
- add focused coverage for inbox authorization, navigation context, page behavior, and section builder logic
- include the Spec Kit artifacts for spec 250

## Notes
- branch is synced with `dev`
- this PR supersedes #290 for the governance inbox work

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #291
2026-04-28 10:13:09 +00:00

5.8 KiB

Research: Decision-Based Governance Inbox v1

Date: 2026-04-28
Feature: spec.md

Decision Summary

The repo already contains the underlying governance attention signals. The missing product slice is not another source page or another workflow state, but one bounded decision-first page that composes the existing source seams into a calm workspace starting point.

Key Decisions

1. Use section-based composition, not a generic task engine

  • Decision: Build the inbox as one read-only Filament page with bounded family sections and preview entries.
  • Why: A polymorphic table or persisted inbox-item model would import a second workflow truth before the first read-only operator surface is proven.
  • Repo truth: Findings, operations, alerts, and review follow-up already have their own truthful pages and models.

2. Reuse findings queue semantics directly

  • Decision: The assigned-findings and intake sections should reuse the inclusion and urgency rules already owned by MyFindingsInbox and FindingsIntakeQueue.
  • Why: Those pages already codify open-status filtering, tenant entitlement, urgency ordering, and calm empty states.
  • Source seams:
    • apps/platform/app/Filament/Pages/Findings/MyFindingsInbox.php
    • apps/platform/app/Filament/Pages/Findings/FindingsIntakeQueue.php

3. Use stale or terminal-follow-up operations as the operations-family signal

  • Decision: The operations section should derive from the same stale or follow-up attention rules already exposed on the canonical Operations page.
  • Why: The repo already has a canonical operations monitoring surface and run-detail route; the inbox should route into it instead of inventing a second operations diagnostic layer.
  • Source seams:
    • apps/platform/app/Filament/Pages/Monitoring/Operations.php
    • apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php
    • apps/platform/app/Support/OperationRunLinks.php

4. Keep the alert-family slice narrow: failed alert deliveries, not alert-rule config

  • Decision: The alerts section should surface delivery failures or similar operator-attention alert outcomes, not alert-rule configuration.
  • Why: Delivery failure is the actionable alerting gap that belongs in an attention inbox. Alert-rule editing stays a configuration workflow on its existing surfaces.
  • Source seams:
    • apps/platform/app/Filament/Pages/Monitoring/Alerts.php
    • apps/platform/app/Filament/Resources/AlertDeliveryResource.php
    • apps/platform/app/Models/AlertDelivery.php

5. Use triage-review follow-up as the review-family signal

  • Decision: The review section should derive from TenantTriageReview states such as follow_up_needed and changed-since-review semantics.
  • Why: The repo already distinguishes review follow-up from the underlying review artifact; the inbox should reuse that distinction rather than invent a second attention reason model.
  • Source seams:
    • apps/platform/app/Services/PortfolioTriage/TenantTriageReviewService.php
    • apps/platform/app/Models/TenantTriageReview.php
    • apps/platform/app/Filament/Resources/TenantReviewResource.php

6. Preserve navigation continuity through shared context helpers

  • Decision: Every section and preview entry should use existing navigation helpers for back links and canonical destinations.
  • Why: The inbox only reduces attention load if it preserves return context instead of opening detached utility flows.
  • Source seams:
    • apps/platform/app/Support/Navigation/CanonicalNavigationContext.php
    • apps/platform/app/Support/Navigation/RelatedNavigationResolver.php
    • apps/platform/app/Support/OperateHub/OperateHubShell.php

7. Keep the inbox read-only in v1

  • Decision: No claim, snooze, acknowledge, assign, or triage mutations are introduced on the inbox page.
  • Why: Those mutations already belong to source surfaces and would force the inbox to become a second workflow owner.
  • Result: The inbox remains a decision hub, not an execution surface.

Access Model Decision

  • Workspace membership remains the first gate.
  • The page only needs to exist for actors who can already see at least one family.
  • Rows and counts must stay family-specific:
    • findings sections require Capabilities::TENANT_FINDINGS_VIEW
    • review follow-up requires Capabilities::TENANT_REVIEW_VIEW
    • alert-family sections require Capabilities::ALERTS_VIEW
    • source mutations remain on source pages with their existing capabilities
  • Explicit out-of-scope tenant_id inputs return 404.

Rejected Alternatives

Rejected: persisted inbox-item table

  • Reason: adds durable workflow truth, migration cost, audit burden, and new lifecycle semantics before the read-only composition page is proven.

Rejected: generic cross-domain work-item abstraction

  • Reason: over-generalizes five concrete families into a second vocabulary and invites a platform-level task framework that current-release truth does not require.

Rejected: extend one existing page instead of adding a canonical inbox

  • Reason: no single existing page can truthfully host all five families without becoming the wrong domain owner.

Implications For Implementation

  • Prefer one bounded Support/GovernanceInbox/ seam only if page-local composition becomes unreadable.
  • Keep source-family labels close to existing UI copy to avoid a second UX language.
  • Keep empty states honest:
    • tenant-prefilter-hidden attention -> Clear tenant filter
    • globally calm -> one neutral workspace return CTA
  • Do not add page-level audit noise for mere page views.

Planning Outcome

The smallest viable implementation slice is one new read-only workspace page that reuses existing source-page queries, existing navigation helpers, and existing capability semantics. No new persistence or mutation lane is justified.