25 KiB
title + explanation + exactly 1 CTA, and tables provide search/sort/filters for core dimensions.
Feature Specification: Portfolio Triage Arrival Context
Feature Branch: [187-portfolio-triage-arrival-context]
Created: 2026-04-09
Status: Draft
Input: User description: "Spec 187 - Portfolio Triage Arrival Context"
Spec Scope Fields (mandatory)
- Scope: workspace
- Primary Routes:
/admin/w/{workspace},/admin/tenants,/admin/t/{tenant}, plus existing concern-specific tenant routes such as/admin/t/{tenant}/backup-sets,/admin/t/{tenant}/restore-runs, and/admin/t/{tenant}/restore-runs/{record}when current routing already chooses them - Data Ownership: Workspace overview and tenant-registry triage remain derived views over existing tenant-owned backup-health and restore-history truth scoped to the active workspace. Arrival context stays request-scoped and non-persisted; no new stored workflow state is introduced.
- RBAC: Workspace membership remains required on portfolio surfaces, and tenant membership remains required on
/admin/t/{tenant}and deeper tenant surfaces. Non-members continue to receive deny-as-not-found semantics. Members who can see portfolio posture but cannot open a deeper backup or restore destination must still receive truthful arrival copy and only actionable next steps they can actually use.
UI/UX Surface Classification (mandatory when operator-facing surfaces are changed)
| Surface | Surface Type | 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Workspace overview recovery attention and summary metrics | Workspace summary / attention surface | Explicit card or stat CTA to the existing best destination | forbidden | Helper copy within the card or stat only | none | /admin/w/{workspace} |
Existing chosen destination: /admin/tenants, /admin/t/{tenant}, /admin/t/{tenant}/backup-sets, or /admin/t/{tenant}/restore-runs |
Active workspace, visible tenant label when singular, backup vs recovery family | Workspace recovery attention / flagged tenant | Why this tenant needs follow-up stays visible before leaving the portfolio surface | existing widget pattern |
| Tenant registry recovery triage list | List-first directory / triage view | Existing tenant-open affordance with preserved triage context | allowed under the existing list contract | Existing filters, sort controls, and open affordance only | none | /admin/tenants |
/admin/t/{tenant} |
Active workspace visibility, backup posture, recovery evidence, triage sort and filters | Tenants / Tenant | Backup posture and recovery evidence stay separate while preserving which concern triggered the open action | existing triage list pattern |
| Tenant dashboard arrival continuity block | Embedded dashboard callout | Explicit next-step CTA plus explicit return-to-portfolio link inside the continuity block | forbidden | Inline secondary link and compact helper copy inside the block | none | /admin/t/{tenant} |
Existing next-step tenant surfaces such as /admin/t/{tenant}/backup-sets, /admin/t/{tenant}/restore-runs, or /admin/t/{tenant}/restore-runs/{record} |
Workspace context, tenant context, arrival source label, concern family, concern state, and current-truth boundary | Tenant dashboard / triage arrival | Why the operator arrived, which concern triggered the open, what to do next, and how to return | additive continuity block |
Operator Surface Contract (mandatory when operator-facing surfaces are changed)
| Surface | Primary Persona | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|
| Workspace overview recovery attention and summary metrics | Workspace operator | Portfolio summary and attention surface | Which visible tenant needs review next, and why is it being escalated? | Tenant label, bounded concern headline, supporting reason, destination label | Raw scoring inputs, builder internals, low-level reason payloads | concern family, concern state, urgency, destination availability | None; read-only triage surface | Open tenant, choose tenant, or open the existing concern-specific destination | none |
| Tenant registry recovery triage list | Workspace operator | Filtered portfolio list | Which flagged tenant should I open next, and which recovery domain triggered the flag? | Tenant label, backup posture, recovery evidence, triage filters, bounded reason cues | Hidden sort internals, raw query payloads, low-level derivation details | backup posture, recovery evidence, triage urgency, current filter scope | None; read-only triage surface | Open tenant, adjust filters, return to default calm browsing order | none |
| Tenant dashboard arrival continuity block | Workspace operator arriving in tenant context | Embedded arrival and guidance surface | Why was this tenant opened from portfolio triage, what should I do next, and how do I get back? | Arrival reason, source surface, triggering concern, bounded current concern, next-step guidance, return target | Raw reason codes, encoded return payload, low-level route state | arrival reason, concern family, concern state, current-truth divergence, access availability | None; read-only guidance surface | Open recommended next step, return to originating portfolio surface | none |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no
- New persisted entity/table/artifact?: no
- New abstraction?: yes
- New enum/state/reason family?: no
- New cross-domain UI framework/taxonomy?: no
- Current operator problem: Portfolio surfaces already identify weak tenants and the relevant domain, but once the operator lands on the tenant dashboard the workflow becomes generic again and the operator must rediscover why the tenant was opened.
- Existing structure is insufficient because: Existing workspace attention items, workspace summary metrics, and tenant-registry filters can compute concern family and destination choice, but that triage intent stops at the navigation boundary. The tenant dashboard renders current tenant truth without preserving source, reason, next step, or return path.
- Narrowest correct implementation: Reuse existing bounded reason context and current routing decisions inside one lightweight request-scoped arrival-context contract that travels with the drilldown, renders a compact continuity block on the tenant dashboard, and preserves a safe return target.
- Ownership cost: A small derived arrival-context abstraction, limited route or query encoding rules, dashboard copy, and focused regression tests across overview, registry, and tenant arrival surfaces.
- Alternative intentionally rejected: Persisted triage sessions, a new recovery-confidence model, or a broad breadcrumb or navigation refactor were rejected because they add new truth or new ownership cost when the gap is a last-mile continuity problem.
- Release truth: current-release workflow continuity hardening
User Scenarios & Testing (mandatory)
User Story 1 - Understand Why The Tenant Opened (Priority: P1)
A workspace operator clicks a flagged tenant from workspace recovery triage and needs the tenant destination to immediately explain why this tenant was opened.
Why this priority: This is the core workflow gap. If the operator still has to rescan the tenant dashboard to rediscover the concern, the portfolio triage flow loses most of its value.
Independent Test: Can be fully tested by opening a tenant dashboard from a workspace overview attention item or filtered tenant-registry triage link and verifying that a top-of-page continuity block names the source surface, concern family, and bounded reason before the operator scans deeper widgets.
Acceptance Scenarios:
- Given a workspace overview attention item opens a tenant because backup posture is absent, When the tenant dashboard loads, Then the arrival block states that the tenant was opened from workspace triage for an absent backup posture concern.
- Given a filtered tenant-registry triage list opens a tenant because recovery evidence is unvalidated, When the tenant dashboard loads, Then the arrival block states that the tenant was opened from portfolio triage for that recovery-evidence concern rather than presenting a generic tenant entry.
User Story 2 - See The Right Next Action (Priority: P2)
A workspace operator arriving on a tenant because of a backup or recovery concern needs the page to tell them what to do next without deep scanning.
Why this priority: Preserving reason without preserving the next action still leaves the operator translating posture into action manually.
Independent Test: Can be fully tested by rendering triage arrivals for backup-absent, backup-stale, backup-degraded, recovery-unvalidated, and recovery-weakened cases and verifying that the continuity block recommends the matching existing backup or restore follow-up surface.
Acceptance Scenarios:
- Given the operator arrives because backup posture is stale or degraded, When the continuity block renders, Then the next step points to existing backup-readiness or backup-set follow-up rather than generic tenant browsing language.
- Given the operator arrives because recovery evidence is weakened or unvalidated, When the continuity block renders, Then the next step points to existing restore-history or flagged restore-run follow-up rather than backup-only guidance.
- Given the operator lacks access to the deeper destination, When the continuity block renders, Then the guidance stays truthful and does not present an impossible CTA.
User Story 3 - Return To Portfolio Flow (Priority: P2)
A workspace operator triaging multiple tenants needs an explicit way to leave the tenant surface and continue the same portfolio workflow they came from.
Why this priority: Triage efficiency degrades if every tenant review ends in a contextless tenant-only browsing session.
Independent Test: Can be fully tested by opening a tenant from both workspace overview and filtered tenant-registry triage, then using the return affordance and verifying that the operator lands back on the originating portfolio surface with meaningful workspace, filter, and sort context preserved.
Acceptance Scenarios:
- Given the operator opened a tenant from workspace overview attention, When they use the return affordance, Then they return to the relevant workspace overview context rather than reconstructing it manually.
- Given the operator opened a tenant from a filtered tenant-registry triage list, When they use the return affordance, Then they return to that filtered registry context instead of an unfiltered tenant directory.
User Story 4 - Stay Honest When Truth Or Access Changes (Priority: P3)
A workspace operator needs continuity copy that preserves arrival reason without overstating the tenant's current recovery truth or implying unavailable actions.
Why this priority: Arrival continuity becomes dangerous if stale context, multiple concerns, or RBAC limits cause the product to overclaim recovery truth or promise actions the operator cannot take.
Independent Test: Can be fully tested by opening triage arrivals after posture changes, with multiple simultaneous concerns, and under RBAC-limited visibility, then verifying that the arrival block preserves why the operator came while keeping current truth and access boundaries explicit.
Acceptance Scenarios:
- Given the tenant concern changed before the page loaded, When the operator lands on the tenant dashboard, Then the arrival block preserves why they came but does not present the old concern as current fact.
- Given the tenant has both backup and recovery-evidence issues, When the operator arrives from one triggering concern, Then the arrival block preserves that specific trigger or explicitly says that multiple recovery-related concerns remain visible.
- Given the operator opens the tenant through ordinary navigation without triage context, When the tenant dashboard renders, Then no portfolio-arrival block or portfolio-return affordance is shown.
Edge Cases
- A tenant was flagged earlier, but current posture is now healthier by the time the destination loads; the page preserves why the operator arrived while still showing the latest truth.
- A tenant has both backup and recovery-evidence concerns; the continuity layer preserves the specific triggering concern or explicitly signals multiple concerns instead of a vague problem statement.
- A filtered tenant-registry triage view opened the tenant with non-default filters or sort; the return affordance must preserve meaningful triage context rather than dropping the operator into an unfiltered list.
- A user can see the tenant dashboard but cannot access restore history or backup detail pages; the continuity block must not overpromise inaccessible next actions.
- Arrival context is missing, malformed, stale, or intentionally shared without valid auth; the destination fails safely into the normal tenant experience with no misleading triage messaging.
Requirements (mandatory)
This feature introduces no new Microsoft Graph calls, no new background work, no new OperationRun, and no new persistence. It is a read-first workflow-continuity slice that carries existing portfolio reason context into tenant arrival without redefining backup health, recovery evidence, or destination semantics.
Authorization spans existing workspace portfolio surfaces and the tenant/admin plane under /admin/t/{tenant}. Non-members continue to receive 404 responses. Members who can see high-level posture but cannot open deeper backup or restore destinations must receive truthful degraded guidance rather than impossible CTAs. No new mutation, confirmation flow, or destructive action is introduced.
This slice reuses existing Filament pages, widgets, list surfaces, and concern-specific destinations. UI-FIL-001 is satisfied by keeping the tenant arrival treatment inside existing Filament page and widget primitives or a shared callout primitive rather than introducing a new local status language. UI-NAMING-001 is satisfied by preserving current operator-facing vocabulary such as backup posture, recovery evidence, restore history, and workspace triage across origin surface, arrival block, and next-step links.
Action Surface Contract expectations remain satisfied. Workspace overview and tenant registry keep their existing primary open models. The tenant dashboard receives an additive read-only continuity block with explicit navigation-only links. No redundant View action, no empty action group, and no destructive action is added. UX-001 create, edit, and view-form rules are not materially changed because this feature modifies dashboard and list guidance surfaces rather than form layouts.
Direct mapping from current route alone to a useful arrival message is insufficient because the same tenant dashboard can be opened generically or from several distinct recovery-triage paths. A small request-scoped arrival-context layer is therefore warranted, but it must derive from existing bounded reason_context, existing portfolio filters, and existing destination rules rather than becoming a second posture model.
Functional Requirements
- FR-187-001: Portfolio recovery and backup drilldowns that open tenant-level surfaces MUST carry a request-scoped arrival context that identifies source surface, concern family, concern state, bounded operator-facing reason, intended next step, and return target.
- FR-187-002: The arrival-context contract MUST support at least the existing concern states
backup absent,backup stale,backup degraded,recovery evidence unvalidated, andrecovery evidence weakenedwithout introducing a new posture family. - FR-187-003: Arrival context MUST NOT rely on the HTTP referrer alone and MUST fail safely when missing or invalid by rendering the ordinary tenant destination with no false continuity messaging.
- FR-187-004: When
/admin/t/{tenant}is opened with valid triage arrival context, the tenant dashboard MUST render a compact top-of-page continuity block before deep scanning of tenant widgets begins. - FR-187-005: The continuity block MUST explicitly answer why the operator is here, which concern triggered the drilldown, what next action is recommended, and how to return to the originating portfolio workflow.
- FR-187-006: Continuity messaging MUST reuse existing backup-health and recovery-evidence claim boundaries and MUST NOT introduce statements that tenant recovery is broken, proven, or guaranteed unless current product truth already supports that claim elsewhere.
- FR-187-007: If the tenant's current posture changed between click time and arrival time, the continuity block MAY preserve why the operator came, but it MUST distinguish arrival reason from current tenant truth and MUST NOT suppress the latest visible posture.
- FR-187-008: If multiple recovery-related concerns exist on the same tenant, the continuity layer MUST preserve the triggering concern specifically or clearly state that multiple concerns remain visible; it MUST NOT collapse them into an ambiguous generic warning.
- FR-187-009: Recommended next-step guidance MUST remain concern-family-specific. Backup concerns MUST point toward existing backup-readiness or backup-set follow-up, while recovery-evidence concerns MUST point toward existing restore-history or restore-run follow-up.
- FR-187-010: If the operator cannot access the deeper next-step destination, the continuity block MUST degrade gracefully with truthful copy or a disabled or absent CTA and MUST NOT imply that an unavailable action can be performed.
- FR-187-011: When arrival context exists, the tenant destination MUST display a visible return-to-portfolio affordance that routes back to the originating workspace overview or filtered tenant-registry triage context.
- FR-187-012: Return-to-portfolio behavior from a filtered tenant-registry triage flow MUST preserve meaningful filter and sort context required to continue triage, rather than dropping the operator into an unfiltered generic tenant directory.
- FR-187-013: Generic tenant browsing sessions MUST remain generic. Opening a tenant through ordinary navigation MUST NOT show triage-specific continuity messaging or portfolio-return affordances.
- FR-187-014: Existing destination semantics from workspace overview, summary metrics, and tenant-registry triage MUST be preserved. The continuity layer MUST augment current routing decisions instead of forcing every recovery concern through the tenant dashboard.
- FR-187-015: Existing concern-specific tenant destinations that already provide semantically specific continuity, such as restore-history surfaces, MUST remain authoritative when current routing chooses them; this feature MUST NOT replace those destinations with a generic tenant landing.
- FR-187-016: Arrival-context encoding MUST be safe for bookmarking and authenticated sharing within the product's existing auth model and MUST degrade simply when the encoded context is stale, malformed, or no longer valid.
- FR-187-017: The tenant dashboard MUST remain renderable without workspace-only services during generic sessions. Arrival-context rendering MUST be additive and removable without making normal tenant dashboard rendering depend on portfolio-only state.
- FR-187-018: Focused regression coverage MUST prove continuity rendering, concern-specific next-step guidance, return-path preservation, generic-session calmness, posture-change honesty, and RBAC-safe degradation across workspace overview, tenant-registry triage, and tenant dashboard surfaces.
Assumptions
- Existing workspace overview reason context and tenant-registry triage state already expose or can derive a bounded concern family, concern state, and destination intent without inventing a second concern model.
- Existing restore-history and backup-posture destinations remain the canonical deeper follow-up surfaces for recovery-evidence and backup concerns once the operator leaves the tenant dashboard.
- A safe return target can be encoded as a bounded route plus allowed filter or sort state without creating a persisted triage session.
- The tenant dashboard remains the primary tenant-level arrival surface for single-tenant portfolio drilldowns that do not already land on a more semantically specific destination.
Dependencies
- Workspace overview attention items and summary metrics remain the source of workspace-level triage reason and destination choice.
- The tenant-registry triage list remains the source of filtered portfolio follow-up context when the operator opens a tenant from
/admin/tenants. - The existing tenant dashboard remains the first tenant-level summary surface above Recovery Readiness, Dashboard KPIs, and Needs Attention.
- Existing backup-set and restore-run surfaces remain the canonical next-step destinations for backup and recovery follow-up.
Out of Scope and Follow-up
- No new backup-health or recovery-evidence computation, state family, or confidence engine.
- No new persistence, tables, migrations, or stored triage workflow state.
- No redesign of
ChooseTenant,ManagedTenantsLanding, or the full tenant dashboard architecture. - No broad navigation or breadcrumb refactor.
- No full sequential "next affected tenant" workflow beyond preserving the current return path.
- Reasonable follow-up work, if later needed, is a dedicated multi-tenant triage queue once this smaller continuity gap is closed.
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 |
|---|---|---|---|---|---|---|---|---|---|---|
| Workspace overview recovery attention and summary metrics | app/Filament/Pages/WorkspaceOverview.php, app/Filament/Widgets/Workspace/WorkspaceNeedsAttention.php, app/Filament/Widgets/Workspace/WorkspaceSummaryStats.php |
none added | Existing card or stat CTA to the current destination | none | n/a | Existing calm-state messaging remains read-only | n/a | n/a | no | Read-only portfolio surfaces only; no destructive action or new action placement rule is introduced. |
| Tenant registry recovery triage list | app/Filament/Resources/TenantResource.php, app/Filament/Resources/TenantResource/Pages/ListTenants.php |
none added | Existing tenant-open affordance and list-open behavior remain authoritative | Existing tenant-open affordance only; no new mutation | Existing bulk behavior unchanged and out of scope | Existing filter-reset guidance remains | n/a | n/a | no | This feature preserves triage-open context and return context, but does not redesign the tenant list or its destructive surfaces. |
| Tenant dashboard arrival continuity block | app/Filament/Pages/TenantDashboard.php plus an additive top-of-page continuity widget or section on the dashboard |
none added | Explicit next-step CTA and return link inside the continuity block only | none | n/a | none | n/a | n/a | no | Read-only arrival guidance only. UI-FIL-001 stays satisfied by using existing Filament page or widget primitives. No destructive action is introduced. |
Key Entities (include if feature involves data)
- Portfolio arrival context: A request-scoped envelope that carries source surface, triggering concern family and state, bounded reason, recommended next step, and return target for one tenant-opening action.
- Portfolio source surface: The workspace overview or filtered tenant-registry triage surface from which the operator initiated the tenant drilldown.
- Concern focus: The existing backup-health or recovery-evidence posture that triggered the drilldown and determines which next action should be recommended.
- Return context: A bounded portfolio destination and allowed filter or sort state that lets the operator continue triage after reviewing one tenant.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: In acceptance testing, operators can identify within 10 seconds why a tenant opened from portfolio recovery triage without rescanning the full tenant dashboard.
- SC-002: In 100% of tested triage-driven tenant-dashboard arrivals, the top-of-page continuity block names the source surface and the triggering concern family.
- SC-003: In 100% of tested backup and recovery concern arrivals, the recommended next action matches the triggering concern family and does not instruct operators to use a destination they cannot access.
- SC-004: In 100% of tested filtered-registry arrivals, the return affordance restores meaningful triage context instead of dropping the operator into an unfiltered generic tenant directory.
- SC-005: In 100% of tested generic tenant-opening sessions, no triage-specific continuity block or portfolio-return affordance is shown.
- SC-006: In 100% of tested stale-context, changed-posture, and RBAC-limited scenarios, arrival messaging remains truthful, preserves the reason for arrival, and introduces no overclaim about recovery truth.