TenantAtlas/specs/221-findings-operator-inbox/research.md
Ahmed Darrazi 8cc73dff71
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 4m59s
feat: add findings operator inbox
2026-04-21 10:19:14 +02:00

5.5 KiB

Research: Findings Operator Inbox V1

Decision 1: Implement the inbox as an admin panel page with slug findings/my-work

  • Decision: Add a new Filament admin page under the existing AdminPanelProvider for the canonical inbox route /admin/findings/my-work.
  • Rationale: The feature is explicitly an admin-plane, workspace-scoped surface. The admin panel already owns comparable custom pages such as FindingExceptionsQueue, and page registration gives the correct Filament middleware, route shape, and Livewire page lifecycle without creating a second routing model.
  • Alternatives considered:
    • Reuse the tenant-local FindingResource list as the canonical inbox. Rejected because it keeps the operator trapped in tenant-first navigation and does not answer the cross-tenant personal-work question.
    • Add a standalone controller route in routes/web.php. Rejected because this is a normal admin panel surface, not a one-off shell route like /admin home.

Decision 2: Keep queue truth as a direct Finding query, not a new shared query subsystem

  • Decision: Build the inbox from Finding records scoped by current workspace, visible capability-eligible tenant IDs, assignee_user_id = current user, and Finding::openStatusesForQuery(), with eager-loaded tenant, ownerUser, and assigneeUser relationships.
  • Rationale: The feature has two concrete consumers, but both are narrow and local: one queue page and one workspace signal. A direct query keeps the logic readable, honors Spec 111 and Spec 219 as-is, and avoids importing a new reusable abstraction before it is clearly needed.
  • Alternatives considered:
    • Introduce a new shared findings-query service immediately. Rejected because the scope is still small and the repo guidance prefers direct implementation until a second real abstraction pressure appears.
    • Mix owner and assignee semantics into one queue query. Rejected because Spec 219 explicitly separates assignee work from owner accountability.

Decision 3: Reuse CanonicalAdminTenantFilterState for the default active-tenant prefilter

  • Decision: Let the inbox synchronize its tenant filter through CanonicalAdminTenantFilterState, so the active tenant becomes the default prefilter and can be cleared without removing personal assignment scope.
  • Rationale: The repo already uses this helper on admin-panel lists and monitoring pages to keep active tenant context honest and clearable. Reusing it keeps the inbox aligned with existing admin context behavior and avoids inventing a page-specific prefilter mechanism.
  • Alternatives considered:
    • Drive tenant prefiltering only through explicit query parameters. Rejected because the feature requirement is about active tenant context, not just shareable URLs.
    • Hard-lock the queue to the active tenant whenever tenant context exists. Rejected because the spec requires a clear path back to all visible tenants.

Decision 4: Add the workspace signal as a dedicated overview payload and Blade block

  • Decision: Extend WorkspaceOverviewBuilder with a compact my_findings_signal payload and render it directly in the existing workspace overview Blade view with one explicit CTA.
  • Rationale: The signal must show open count, overdue count, calm state, and one named CTA. The existing generic summary_metrics lane is optimized for one metric value plus description and does not cleanly express the contract without distorting the overview metric family.
  • Alternatives considered:
    • Encode the signal as another generic summary metric. Rejected because the metric card does not naturally expose both counts and an explicit Open my findings CTA.
    • Add a second standalone dashboard or queue widget. Rejected because the overview only needs a small drill-in signal, not another work surface.

Decision 5: Preserve queue-to-detail continuity through CanonicalNavigationContext

  • Decision: Append a CanonicalNavigationContext payload when an inbox row opens /admin/t/{tenant}/findings/{finding} so the detail page can render Back to my findings.
  • Rationale: The repo already uses CanonicalNavigationContext for cross-surface return links on admin and tenant detail pages. Reusing it preserves a single continuity model and keeps the return path explicit instead of relying on fragile browser history.
  • Alternatives considered:
    • Depend on the browser referer only. Rejected because it is brittle across reloads, tabs, and copied links.
    • Add a new inbox-specific controller just to set session return state. Rejected because the existing navigation context already solves this problem cleanly.

Decision 6: Prove the feature with three focused feature suites plus one route-alignment extension

  • Decision: Add MyWorkInboxTest, MyWorkInboxAuthorizationTest, and MyFindingsSignalTest as the three new focused suites, and extend WorkspaceOverviewNavigationTest for route-alignment proof.
  • Rationale: The user-visible risk is visibility, prioritization, tenant safety, and overview-to-inbox truth alignment. Those are best proven through focused feature coverage using the existing workspace and tenant helpers, while the inbox CTA alignment belongs in the existing route-alignment regression instead of a fourth new suite.
  • Alternatives considered:
    • Add browser coverage. Rejected because the surface is simple and already well represented by Filament/Livewire feature assertions.
    • Add a unit-only seam around queue counting. Rejected because the important risk is integrated scope behavior, not isolated arithmetic.