TenantAtlas/specs/221-findings-operator-inbox/research.md
ahmido 81bb5f42c7
Some checks failed
Main Confidence / confidence (push) Failing after 55s
feat: add findings operator inbox (#258)
## Summary
- add the canonical admin-plane `My Findings` inbox at `/admin/findings/my-work`
- add the workspace overview `Assigned to me` signal and inbox-to-detail continuity
- add focused Pest coverage plus the full Spec 221 artifact bundle

## Validation
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/MyWorkInboxTest.php tests/Feature/Authorization/MyWorkInboxAuthorizationTest.php tests/Feature/Dashboard/MyFindingsSignalTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/WorkspaceOverviewNavigationTest.php`
- integrated-browser smoke completed against the browser-facing `tenantatlas` runtime, including seeded positive-path and negative-path checks plus fixture cleanup

## Filament v5 Guardrails
- Livewire v4.0+ compliant
- panel provider registration remains in `apps/platform/bootstrap/providers.php`
- global search behavior is unchanged; `FindingResource` already has a View page and the new inbox is a custom page, not a searchable resource
- no destructive actions were introduced on the inbox or overview signal
- no new assets were added; the existing deploy step for `cd apps/platform && php artisan filament:assets` remains unchanged
- coverage includes the new inbox page, authorization boundaries, the workspace overview signal, and the overview CTA regression

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #258
2026-04-21 09:19:54 +00: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.