# Research: Findings Intake & Team Queue V1 ## Decision 1: Implement the intake queue as an admin panel page with slug `findings/intake` - **Decision**: Add a new Filament admin page under the existing `AdminPanelProvider` for the canonical route `/admin/findings/intake`. - **Rationale**: The feature is an admin-plane, workspace-scoped decision surface, not a tenant-local variant of the existing findings resource. A page registration keeps the same Filament middleware, route shape, session handling, and Livewire page lifecycle already used by `MyFindingsInbox`. - **Alternatives considered**: - Reuse the tenant-local `FindingResource` list with a preset filter. Rejected because it still forces tenant-first navigation and does not answer the cross-tenant intake question. - Add a standalone controller route in `routes/web.php`. Rejected because this is a normal admin panel surface and should stay inside Filament routing and guardrails. ## Decision 2: Keep intake truth as a direct `Finding` query, but use `Finding::openStatuses()` instead of `openStatusesForQuery()` - **Decision**: Build the intake queue from `Finding` records scoped by current workspace, visible tenant IDs, `assignee_user_id IS NULL`, and `Finding::openStatuses()`. - **Rationale**: Spec 222 explicitly reuses Spec 111 open statuses for intake: `new`, `triaged`, `in_progress`, and `reopened`. The broader `openStatusesForQuery()` helper includes `acknowledged`, which belongs in existing tenant-local workflows but not in this shared intake queue. - **Alternatives considered**: - Reuse `Finding::openStatusesForQuery()` exactly as `MyFindingsInbox` does. Rejected because it would leak `acknowledged` rows into intake and violate FR-003. - Introduce a new shared intake-query service immediately. Rejected because there is still only one concrete intake consumer and the repo guidance prefers direct implementation until reuse pressure is real. ## Decision 3: Model `Unassigned` and `Needs triage` as fixed page-level views, not a new taxonomy or generic filter framework - **Decision**: Represent `Unassigned` and `Needs triage` as fixed queue-view controls in the page shell, with `Needs triage` implemented as the strict subset of intake rows in `new` or `reopened` status. - **Rationale**: The two views are product vocabulary, not a reusable classification framework. Page-local view state keeps the implementation explicit, honors the spec's fixed queue contract, and avoids adding new persisted preferences or a generic queue-view registry. - **Alternatives considered**: - Add a reusable taxonomy or enum for queue view types. Rejected because two concrete values do not justify new semantic machinery. - Model the views as ordinary optional filters only. Rejected because the spec treats them as fixed queue modes, not ad hoc filter combinations. ## Decision 4: Reuse canonical admin tenant filter and navigation context helpers - **Decision**: Use `CanonicalAdminTenantFilterState` to apply the active tenant as the default prefilter and `CanonicalNavigationContext` to carry `Back to findings intake` continuity into tenant finding detail. - **Rationale**: The repo already uses these helpers for canonical admin-plane filters and cross-surface back links. Reusing them keeps intake aligned with the existing admin shell, keeps row and count disclosure tenant-safe, and avoids adding another page-specific context mechanism. If a workspace member has no currently viewable findings scope anywhere, the queue should fail with `403` instead of pretending the backlog is simply empty. - **Alternatives considered**: - Store active tenant and return-path state in a queue-local session structure. Rejected because the existing helpers already solve both problems and another state path would add drift. - Depend on browser history for return links. Rejected because it is brittle across reloads, tabs, and copied URLs. ## Decision 5: Add `Claim finding` as a narrow row action that reuses assignment semantics, adds a lightweight preview/confirmation step, and adds a stale-row conflict guard - **Decision**: Implement `Claim finding` as the single inline safe shortcut on the intake row, gated by `Capabilities::TENANT_FINDINGS_ASSIGN`, surfaced through a lightweight preview/confirmation modal, and routed through `FindingWorkflowService` plus the existing `finding.assigned` audit action while adding a claim-specific re-check that refuses rows whose assignee is no longer null under lock. - **Rationale**: The current assignment service already owns audit logging, tenant ownership checks, and capability enforcement, but plain assign semantics would allow a stale queue click to overwrite a newer assignee and would not satisfy the repository write-flow governance. A lightweight preview/confirmation step plus a narrow guard inside the existing service seam solves both needs without inventing a second assignment system. - **Alternatives considered**: - Reuse the existing `Assign` form unchanged. Rejected because the intake surface needs a lighter self-claim preview/confirmation flow, not a broader owner/assignee form. - Reuse `assign()` without an extra guard. Rejected because it could silently overwrite another operator's successful claim, violating FR-014. ## Decision 6: Keep post-claim continuity explicit through `My Findings` rather than auto-redirecting away from intake - **Decision**: Refresh the queue after a successful claim so the row disappears immediately, then provide a clear next step into `/admin/findings/my-work` while leaving row-open detail continuity available when the operator needs deeper context first. - **Rationale**: The queue is still the canonical shared backlog surface. Auto-redirecting every successful claim would interrupt batch intake review, while a clear `Open my findings` next step satisfies the spec without hiding the updated queue truth. - **Alternatives considered**: - Redirect to `My Findings` after every claim. Rejected because it would add navigation churn when multiple intake items are reviewed in sequence. - Keep success feedback to a generic toast only. Rejected because the spec requires a clear next step into the existing personal execution destination. ## Decision 7: Prove the feature with three focused feature suites and rely on existing UI guard tests as ambient protection - **Decision**: Add `FindingsIntakeQueueTest`, `FindingsIntakeAuthorizationTest`, and `FindingsClaimHandoffTest` as the focused proving suites while allowing existing action-surface and Filament-table guards to stay in their normal CI role. - **Rationale**: The user-visible risk is queue truth, hidden-tenant isolation, claim authorization, stale-row conflict handling, and handoff continuity. Those are best proven with focused feature tests that exercise the real Livewire and Filament seams. - **Alternatives considered**: - Add browser coverage. Rejected because the surface is straightforward and already well served by existing feature-test patterns. - Add a new heavy-governance suite for this page. Rejected because the change is still one bounded feature surface, not a new cross-cutting UI family.