## 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
28 KiB
Feature Specification: Findings Operator Inbox V1
Feature Branch: 221-findings-operator-inbox
Created: 2026-04-20
Status: Draft
Input: User description: "Findings Operator Inbox v1"
Spec Candidate Check (mandatory — SPEC-GATE-001)
- Problem: Findings can already be assigned, but the current assignee still has to reconstruct personal work from tenant-local findings lists and ad hoc filters.
- Today's failure: Assignment remains metadata instead of day-to-day workflow. Operators cannot answer "what is mine right now?" from one trustworthy surface, so they tenant-hop or miss overdue assigned work.
- User-visible improvement: One personal inbox shows the current user's open assigned findings across visible tenants, highlights urgency, and gives a direct path into the correct finding record.
- Smallest enterprise-capable version: A canonical read-first inbox for the current user's assigned open findings, urgency filters, tenant-safe drilldown into the existing finding detail, and one small workspace-overview signal that links into the inbox.
- Explicit non-goals: No owner-only accountability queue, no unassigned intake queue, no notifications or escalation, no comments or external ticketing, no team-routing logic, no bulk queue actions, and no new permission system.
- Permanent complexity imported: One canonical inbox page, one small workspace overview summary signal, one derived personal-assignment query contract, and focused regression coverage for visibility, context handoff, and empty-state behavior.
- Why now: Spec 219 made owner versus assignee semantics explicit. The next smallest findings execution slice is to make assignee-based work actually discoverable before intake, escalation, or hygiene hardening land.
- Why not local: A tenant-local
My assignedfilter still forces operators to guess which tenant to open first and does not create one trustworthy start-of-day queue across the workspace-visible tenant set. - Approval class: Core Enterprise
- Red flags triggered: One mild
Many surfacesrisk because the slice touches the inbox and a workspace overview signal. The scope remains acceptable because both surfaces express the same personal-work truth and do not introduce a new meta-layer. - Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 2 | Wiederverwendung: 1 | Gesamt: 10/12
- Decision: approve
Spec Scope Fields (mandatory)
- Scope: canonical-view
- Primary Routes:
/admin/findings/my-workas the new canonical personal findings inbox/adminas the workspace overview where the assigned-to-me signal links into the inbox/admin/t/{tenant}/findingsas the existing tenant findings list fallback/admin/t/{tenant}/findings/{finding}as the existing tenant finding detail drilldown
- Data Ownership: Tenant-owned findings remain the only source of truth. The inbox and workspace overview signal are derived views over existing finding assignment, lifecycle, severity, due-date, and tenant-entitlement truth.
- RBAC: Workspace membership is required to reach the canonical inbox in the admin plane. Every visible row and count additionally requires tenant entitlement plus the existing findings view capability for the referenced tenant. Non-members or out-of-scope users remain deny-as-not-found. In-scope users without the required capability remain forbidden on protected destinations.
For canonical-view specs, the spec MUST define:
- Default filter behavior when tenant-context is active: The inbox always applies
assignee = current userand open-status scope. When an active tenant context exists, the page additionally prefilters to that tenant by default while allowing the operator to clear only the tenant prefilter, not the personal assignment scope. - Explicit entitlement checks preventing cross-tenant leakage: Counts, rows, tenant filter values, and drilldown links materialize only from tenants the current user may already inspect. Hidden tenants contribute nothing to counts, labels, filter values, or empty-state hints.
UI / Surface Guardrail Impact (mandatory when operator-facing surfaces are changed; otherwise write N/A)
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / N/A Note |
|---|---|---|---|---|---|---|
| My Findings inbox | yes | Native Filament page + existing table, filter, and empty-state primitives | Same findings workflow family as tenant findings list and finding detail | table, filter state, urgency emphasis, return path | no | Read-first queue; no new mutation family on the inbox itself |
| Workspace overview assigned-to-me signal | yes | Native Filament widget or summary primitives | Same workspace-overview summary family as other /admin attention signals |
embedded summary, drill-in CTA | no | Small entry signal only; not a second queue |
Decision-First Surface Role (mandatory when operator-facing surfaces are changed)
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| My Findings inbox | Primary Decision Surface | The operator starts the work session or returns to outstanding assigned findings | Tenant, severity, lifecycle status, due or overdue state, and reopened cues for the operator's assigned work | Full finding detail, evidence, audit trail, and exception context after opening the finding | Primary because this is the first dedicated queue for assignee-based execution work | Aligns daily execution around assigned findings instead of tenant hopping | Removes repeated search across tenant dashboards and tenant findings lists |
| Workspace overview assigned-to-me signal | Secondary Context Surface | The operator lands on /admin and needs to know whether personal follow-up exists before choosing a domain |
Open assigned count, overdue count, and one CTA into the inbox | Full inbox and finding detail after drill-in | Secondary because it points to work rather than hosting it | Keeps workspace home aligned with the assignee queue | Removes opening multiple pages just to discover personal work |
UI/UX Surface Classification (mandatory when operator-facing surfaces are changed)
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| My Findings inbox | List / Table / Bulk | CRUD / List-first Resource | Open the most urgent assigned finding | Finding | required | Utility filters and fallback navigation stay outside row action noise | None on the inbox; dangerous lifecycle actions stay on finding detail | /admin/findings/my-work | /admin/t/{tenant}/findings/{finding} | Active workspace, optional active-tenant prefilter, tenant column, assigned-to-me scope | Findings / Finding | What is assigned to the current user, what is overdue, and which tenant it belongs to | Operationally this is a personal worklist, but the interaction model is list-first because row open is the only primary action and all mutation remains on the finding detail surface. |
| Workspace overview assigned-to-me signal | Utility / System | Read-only Registry / Report Surface | Open the inbox | Explicit summary CTA | forbidden | Summary strip only | none | /admin | /admin/findings/my-work | Active workspace and visible-scope counts | My findings | Whether the current user has assigned open or overdue work | Embedded summary drill-in that stays read-only and points into the canonical inbox rather than becoming its own queue surface. |
Operator Surface Contract (mandatory when operator-facing surfaces are changed)
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| My Findings inbox | Tenant operator or tenant manager | Decide which assigned finding to open and work next | List-first personal work surface | What is assigned to me right now across my visible tenants, and what needs attention first? | Tenant, finding summary, severity, lifecycle status, due date or overdue state, reopened cue, and owner when different from assignee | Raw evidence, run context, exception history, and full audit trail | lifecycle, due urgency, severity, responsibility role | none on the inbox itself; existing tenant detail surfaces keep their current mutation scopes | Open finding, apply filters, clear tenant prefilter | none |
| Workspace overview assigned-to-me signal | Workspace member with findings visibility | Decide whether personal findings work exists and drill into it | Summary drill-in | Do I have assigned findings work that needs attention right now? | Open assigned count, overdue count, and one CTA | none | queue presence, overdue urgency | none | Open my findings | none |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no
- New persisted entity/table/artifact?: no
- New abstraction?: no
- New enum/state/reason family?: no
- New cross-domain UI framework/taxonomy?: no
- Current operator problem: Assigned findings are already present in the product, but there is no single trustworthy place where the assignee can start work across visible tenants.
- Existing structure is insufficient because: Tenant-local findings pages and one quick filter do not answer the cross-tenant personal-work question. They force the operator to search for assigned work instead of receiving a real queue.
- Narrowest correct implementation: One derived inbox page and one small workspace summary signal, both powered by existing assignee, severity, due-date, lifecycle, tenant, and entitlement truth.
- Ownership cost: One cross-tenant query shape, one context-prefilter rule, one return-path convention, and focused regression tests for visibility and empty-state behavior.
- Alternative intentionally rejected: A full cross-tenant findings register, an owner-plus-assignee mixed queue, or a team workboard was rejected because those shapes are broader than the current operator problem.
- Release truth: Current-release truth. This slice makes the already-shipped assignment concept operational now.
Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Canonical replacement is preferred over preservation.
Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)
- Test purpose / classification: Feature
- Validation lane(s): fast-feedback, confidence
- Why this classification and these lanes are sufficient: The change is proven by visible operator behavior on one canonical page and one workspace summary surface. Focused feature coverage is sufficient to prove personal-queue visibility, tenant-safe filtering, context handoff, and empty-state behavior without introducing heavy-governance or browser cost.
- New or expanded test families: Add focused coverage for the canonical inbox page, the workspace overview signal, positive and negative authorization, owner-only versus assignee-only visibility, and active-tenant prefilter behavior.
- Fixture / helper cost impact: Low to moderate. Tests need one workspace, multiple visible and hidden tenants, memberships, and findings in open and terminal states with explicit owner and assignee combinations.
- Heavy-family visibility / justification: none
- Special surface test profile: global-context-shell
- Standard-native relief or required special coverage: Ordinary feature coverage is sufficient, plus explicit assertions that active tenant context prefilters the inbox safely, that the tenant-prefilter empty-state CTA clears back to all visible tenants, and that row drilldown preserves a return path to the queue.
- Reviewer handoff: Reviewers must confirm that hidden-tenant findings never leak into rows or counts, owner-only findings are excluded from the personal queue, the queue remains read-first, and the workspace overview CTA lands on the same assigned-work truth shown by the inbox.
- Budget / baseline / trend impact: none
- Escalation needed: none
- Active feature PR close-out entry: Guardrail
- Planned validation commands:
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/MyWorkInboxTest.php tests/Feature/Authorization/MyWorkInboxAuthorizationTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Dashboard/MyFindingsSignalTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/WorkspaceOverviewNavigationTest.php
User Scenarios & Testing (mandatory)
User Story 1 - See my assigned findings in one queue (Priority: P1)
As a tenant operator, I want one personal findings queue across my visible tenants so I can start work without searching tenant by tenant.
Why this priority: This is the core value. If the assignee still has to reconstruct personal work from multiple tenant pages, assignment remains metadata instead of workflow.
Independent Test: Can be fully tested by seeding multiple visible tenants with findings where the current user is assignee, owner-only, or unrelated, then verifying that the inbox shows only open assigned work from entitled tenants.
Acceptance Scenarios:
- Given the current user is assigned open findings across multiple visible tenants, When the user opens the inbox, Then the page shows only those open assigned findings with tenant and urgency context.
- Given an active tenant context exists, When the user opens the inbox, Then the queue is prefiltered to that tenant while keeping the personal assignment scope intact.
- Given the current user is owner but not assignee on an open finding, When the user opens the inbox, Then that finding does not appear in the personal queue.
User Story 2 - Prioritize urgent work and drill into the right finding (Priority: P1)
As a tenant operator, I want the queue to surface overdue or otherwise urgent assigned work first and take me straight into the correct finding detail, so I can act without reconstructing tenant context.
Why this priority: A queue that is complete but not prioritizable still slows operators down. The first work surface must make the next click obvious.
Independent Test: Can be fully tested by seeding overdue, reopened, high-severity, and ordinary assigned findings, opening the inbox, and verifying both urgency ordering and drilldown behavior.
Acceptance Scenarios:
- Given the current user has overdue, reopened, and ordinary assigned findings, When the inbox renders, Then overdue findings are presented first, reopened non-overdue findings are presented ahead of ordinary assigned work, and high severity remains a filter and emphasis cue rather than a separate mandatory sort bucket in v1.
- Given the operator opens a finding from the inbox, When the destination page loads, Then it opens the existing tenant finding detail for the correct tenant and preserves a return path to the inbox.
- Given no visible assigned findings exist because the active tenant prefilter excludes them, When the operator opens the inbox, Then the empty state explains that the current tenant filter is narrowing the queue and offers one clear fallback CTA that clears the tenant prefilter back to all visible tenants.
User Story 3 - Discover my assigned work from the workspace overview (Priority: P2)
As a workspace member, I want a small assigned-to-me signal on the workspace overview so I can tell immediately whether personal findings work exists before I choose a tenant or open another domain.
Why this priority: This is the smallest entry-point improvement that makes the new queue discoverable without turning /admin into a second findings page.
Independent Test: Can be fully tested by seeding assigned and unassigned work, opening the workspace overview, and verifying that the signal matches the inbox truth and drills into the queue in one click.
Acceptance Scenarios:
- Given the current user has visible assigned open findings, When the user opens the workspace overview, Then the assigned-to-me signal shows the open count, overdue count, and one CTA into the inbox.
- Given the current user has no visible assigned open findings, When the user opens the workspace overview, Then the signal remains calm and does not imply missing or hidden work.
Edge Cases
- A finding may still reference the current user as assignee in a tenant the user is no longer entitled to; the inbox and overview counts must not show it.
- An active tenant prefilter may produce an empty queue while other visible tenants still contain assigned work; the empty state must explain the filter boundary instead of claiming no work exists anywhere.
- A finding can move to a terminal state in another browser tab while the inbox is open; refresh behavior must remove or de-emphasize it without implying it is still active assigned work.
- A finding may have the current user as both owner and assignee; it remains visible because assignee governs inbox inclusion.
- A finding may have the current user as owner only; it remains out of scope for this personal queue until a later accountability-focused slice explicitly defines that workload.
Requirements (mandatory)
Constitution alignment (required): This feature adds no Microsoft Graph calls, no new long-running work, and no new OperationRun. It introduces a derived read surface and a summary signal only. Existing tenant findings mutations, audit logging, and workflow confirmations remain governed by their current specs and surfaces.
Constitution alignment (RBAC-UX): The feature operates in the admin /admin plane for the canonical inbox and workspace overview, with tenant entitlement enforced per referenced finding before disclosure and before drilldown to /admin/t/{tenant}/findings/{finding}. Non-members or out-of-scope users continue to receive 404. When workspace membership exists but workspace context has not yet been established, the feature follows the existing chooser or resume flow instead of returning 404. In-scope users lacking the existing findings view capability continue to receive 403 on protected destinations. No raw capability strings, role checks, or second permission system may be introduced. Global search behavior is unchanged.
Constitution alignment (UI-FIL-001): The inbox and overview signal must use native Filament page, table, filter, stat, badge, and empty-state primitives or existing shared UI helpers. No local status language, ad hoc color system, or custom badge markup may be introduced for urgency or queue state.
Constitution alignment (UI-NAMING-001): The canonical operator-facing vocabulary is My Findings, Assigned to me, Open my findings, and Open finding. The page is about finding work, not a generic task engine. Terms such as inbox item, work unit, or queue record must not replace the finding domain language in primary labels.
Constitution alignment (DECIDE-001): The inbox is a primary decision surface because it answers the assignee's first daily workflow question in one place. The workspace signal is secondary because it points into that work rather than replacing it. Default-visible content must be enough to choose the next finding without reconstructing tenant context elsewhere.
Constitution alignment (UI-CONST-001 / UI-SURF-001 / ACTSURF-001 / HDR-001): The inbox has exactly one primary inspect model: the finding. Row click is required. There is no redundant View action. Utility controls such as tenant filter and clear-filter affordances stay outside the row action lane. Dangerous lifecycle actions remain on the existing finding detail instead of being promoted into the queue. The workspace overview signal remains a summary drill-in surface with one explicit CTA.
Constitution alignment (OPSURF-001): Default-visible content on the inbox must stay operator-first: finding summary, tenant, severity, lifecycle state, and due urgency before diagnostics. The inbox itself is read-first and does not introduce a new mutation lane. Workspace and tenant scope must remain explicit through the page title, tenant column, active-tenant prefilter state, and drilldown routing.
Constitution alignment (UI-SEM-001 / LAYER-001 / TEST-TRUTH-001): Direct reuse of the tenant-local My assigned filter is insufficient because it does not create one cross-tenant personal-work surface. This feature still avoids new semantic infrastructure by deriving the inbox directly from existing assignee, lifecycle, severity, due-date, and entitlement truth. Tests must prove the business consequences: visibility, prioritization, tenant safety, and drilldown continuity.
Functional Requirements
- FR-001: The system MUST provide a canonical personal findings inbox at
/admin/findings/my-workfor the current user. - FR-002: The inbox MUST include only findings that are in an open workflow status, are currently assigned to the current user, and belong to tenants the current user is entitled to inspect.
- FR-003: Findings where the current user is owner but not assignee MUST NOT appear in the inbox.
- FR-004: The inbox MUST show at minimum the tenant, finding summary, severity, lifecycle status, due date or overdue state, and reopened cue for each visible row.
- FR-005: If the finding owner differs from the assignee, the inbox MUST show that owner context without turning owner into the inclusion rule for the queue.
- FR-006: The inbox MUST prioritize urgent work ahead of ordinary assigned work using a deterministic rule: overdue findings first, reopened non-overdue findings next, then remaining assigned work. Within each bucket, rows with due dates sort by
due_atascending, rows without due dates sort last, and remaining ties sort by finding ID descending. High severity is a supported filter and emphasis cue in v1, but it does not create a separate mandatory sort bucket. - FR-007: The inbox MUST expose available filters for fixed personal assignment scope, tenant, overdue state, reopened state, and high-severity work. The personal assignment scope is fixed and cannot be removed in v1, and tenant filter options MUST be limited to visible capability-eligible tenants.
- FR-008: When an active tenant context exists, the inbox MUST apply that tenant as a default prefilter and allow the operator to clear that tenant prefilter to return to all visible tenants. If the tenant prefilter alone causes the queue to become empty while other visible tenants still contain assigned work, the empty-state CTA for that branch MUST clear the tenant prefilter.
- FR-009: Opening a row from the inbox MUST navigate to the existing tenant finding detail for the correct tenant and preserve a return path back to the inbox.
- FR-010: The workspace overview at
/adminMUST expose a small assigned-to-me signal that shows the current user's visible assigned open count and overdue count and links into the inbox. - FR-011: Inbox rows, overview counts, tenant filter values, and inbox summary counts MUST be derived only from findings the current user is entitled and currently authorized through the existing findings-view capability to inspect and MUST NOT leak hidden or capability-blocked tenants through counts, labels, filter options, or empty-state hints. Inbox summary counts MUST reflect the currently visible queue after active filters are applied.
- FR-012: When the current user has no visible assigned open findings, the inbox MUST render a calm empty state that explains there is no assigned work and offers one clear CTA. When active tenant context exists, the CTA opens that tenant's findings list. When no active tenant context exists, the CTA opens
/admin/choose-tenantso the operator can establish tenant context before opening tenant findings. - FR-013: The feature MUST reuse the existing finding lifecycle semantics from Spec 111 and the owner-versus-assignee semantics from Spec 219 and MUST NOT introduce new workflow states, new owner semantics, or a second permission system.
UI Action Matrix (mandatory when Filament is changed)
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| My Findings inbox | /admin/findings/my-work |
Clear tenant filter only when an active tenant prefilter is applied |
Full-row open to /admin/t/{tenant}/findings/{finding} |
none | none | Clear tenant filter when the tenant prefilter excludes rows; otherwise Open tenant findings with active tenant context or Choose a tenant |
n/a | n/a | no direct audit because the surface is read-first | Action Surface Contract satisfied. One inspect model only, no redundant View, no dangerous queue actions, and no empty groups. |
| Workspace overview assigned-to-me signal | /admin workspace overview |
none | Explicit summary CTA Open my findings |
none | none | none | n/a | n/a | no | Summary drill-in only; not a second work surface |
Key Entities (include if feature involves data)
- Assigned finding: An open tenant-owned finding where the current user is the assignee and is entitled to inspect the tenant that owns the finding.
- My Findings inbox: A derived canonical queue over assigned findings that emphasizes urgency and tenant-safe drilldown.
- Assigned-to-me signal: A derived workspace overview summary that counts visible assigned open findings and overdue assigned findings for the current user.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: In acceptance review, an operator can determine within 10 seconds from
/adminwhether they have overdue assigned findings and open the inbox in one click. - SC-002: 100% of covered automated tests show only current-user assigned open findings from visible tenants in the inbox and overview counts.
- SC-003: 100% of covered automated tests exclude owner-only, terminal, or hidden-tenant findings from the personal queue and assigned-to-me signal.
- SC-004: From the inbox, an operator can reach the target tenant finding detail in one interaction while preserving a clear return path to the queue.
Assumptions
- Spec 219 is the authoritative contract for owner versus assignee semantics.
- The existing tenant finding detail remains the canonical mutation surface for finding lifecycle and assignment actions.
- The workspace overview at
/admincan host one small additional summary signal without introducing a new landing-page architecture.
Non-Goals
- Introduce a general cross-tenant findings register for all findings
- Introduce an owner-based accountability queue
- Add unassigned intake, claim flow, or team workboard behavior
- Add notification, escalation, or stale-work automation
- Add new bulk lifecycle actions or a second mutation lane on the inbox
Dependencies
- Spec 111, Findings Workflow + SLA, remains the source of truth for open finding lifecycle, due-date behavior, and tenant findings workflow.
- Spec 219, Finding Ownership Semantics Clarification, remains the source of truth for assignee-based work versus owner-based accountability.