TenantAtlas/specs/187-portfolio-triage-arrival-context/tasks.md
ahmido 28e62bd22c feat: preserve portfolio triage arrival context (#218)
## Summary
- preserve portfolio triage arrival context from workspace overview and tenant registry drill-throughs
- add a tenant dashboard continuity widget plus bounded arrival token and resolver support
- add focused Pest coverage for arrival routing, return flow, RBAC degradation, and request-local performance
- include the Spec 187 spec, plan, research, data model, quickstart, contract, and tasks artifacts

## Validation
- integrated browser smoke: workspace overview -> tenant dashboard arrival -> backup sets CTA
- integrated browser smoke: tenant registry triage -> tenant dashboard arrival -> return to tenant triage
- branch includes focused automated test coverage for the new arrival-context surfaces

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #218
2026-04-09 21:38:31 +00:00

249 lines
20 KiB
Markdown

# Tasks: Portfolio Triage Arrival Context
**Input**: Design documents from `/specs/187-portfolio-triage-arrival-context/`
**Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, `contracts/portfolio-triage-arrival-context.logical.openapi.yaml`, `quickstart.md`
**Tests**: Tests are REQUIRED for this feature. Use Pest unit coverage for the arrival-context codec and resolver, Filament feature coverage for workspace overview drilldowns, tenant-registry triage, tenant-dashboard continuity rendering, explicit legacy overview and registry regressions, and existing backup or restore continuity surfaces.
**Operations**: This feature introduces no new `OperationRun`, queue, scheduler, remote call, or audit-log mutation surface. All work stays request-scoped and read-only.
**RBAC**: Existing tenant-context membership and deny-as-not-found behavior remain authoritative. Tasks must preserve 404 responses for non-members, truthful degraded guidance for in-scope operators who cannot open deeper follow-up surfaces, and no new capability strings outside the existing registry.
**Operator Surfaces**: The affected operator surfaces are workspace overview recovery triage, tenant-registry recovery triage, the tenant dashboard arrival surface, and the existing backup-set or restore-run follow-up pages that already own deeper continuity messaging.
**Filament UI Action Surfaces**: No new destructive action, bulk action, or action group is introduced. The tenant dashboard receives only read-only continuity links, and existing tenant-open affordances remain authoritative on workspace overview and tenant registry.
**Filament UI UX-001**: No create, edit, or view-form layouts change. This slice adds an additive dashboard widget and preserves existing page layouts and action placement.
**Badges**: No new badge family is introduced. Existing backup-posture and recovery-evidence semantics remain unchanged.
**Organization**: Tasks are grouped by user story so each story can be implemented and verified independently after the shared arrival-context foundation is in place.
## Phase 1: Setup (Shared Test Infrastructure)
**Purpose**: Prepare reusable test data and helpers for portfolio-arrival scenarios shared across all stories.
- [X] T001 [P] Add stale and degraded backup fixture states in `apps/platform/database/factories/BackupSetFactory.php` and failed, partial, and completed-with-follow-up restore fixture states in `apps/platform/database/factories/RestoreRunFactory.php`
- [X] T002 [P] Create reusable portfolio triage fixtures for workspace, tenant, operator, and generic-session scenarios in `apps/platform/tests/Feature/Concerns/BuildsPortfolioTriageFixtures.php`
**Checkpoint**: Shared fixtures are ready for overview, registry, and tenant-dashboard arrival tests.
---
## Phase 2: Foundational (Blocking Arrival-Context Core)
**Purpose**: Build the single request-scoped arrival-context contract, token codec, and resolver that every story depends on.
**CRITICAL**: No user story work should start before this phase is complete.
- [X] T003 [P] Add encode, decode, unsupported-version, malformed-token, and allowlist regression coverage in `apps/platform/tests/Unit/Support/PortfolioTriage/PortfolioArrivalContextTokenTest.php`
- [X] T004 [P] Add resolver coverage for tenant binding, workspace binding, concern-family allowlists, next-step derivation, disabled-target degradation, and return-target sanitization in `apps/platform/tests/Unit/Support/PortfolioTriage/PortfolioArrivalContextResolverTest.php`
- [X] T005 Create the request-scoped arrival-context value object and versioned token codec in `apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContext.php` and `apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextToken.php`
- [X] T006 Implement scope validation, concern-to-target mapping, claim-boundary text, and bounded return-target resolution in `apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextResolver.php`
**Checkpoint**: One authoritative arrival-context seam exists and is covered by focused token and resolver tests.
---
## Phase 3: User Story 1 - Understand Why The Tenant Opened (Priority: P1) MVP
**Goal**: Make tenant arrivals from workspace overview and filtered tenant-registry triage immediately explain why the operator opened this tenant.
**Independent Test**: Open a tenant dashboard from workspace recovery triage and from filtered tenant-registry triage, then verify a top-of-page continuity block names the source surface, concern family, and bounded reason before deeper widgets load.
### Tests for User Story 1
- [X] T007 [P] [US1] Add workspace-overview arrival-token emission coverage for backup-absent and recovery-evidence drilldowns in `apps/platform/tests/Feature/Filament/WorkspaceOverviewArrivalContextTest.php`
- [X] T008 [P] [US1] Add filtered tenant-registry arrival-token emission coverage for triage-driven tenant opens in `apps/platform/tests/Feature/Filament/TenantRegistryArrivalContextTest.php`
- [X] T009 [P] [US1] Add tenant-dashboard continuity rendering coverage for source surface, concern family, and bounded arrival reason in `apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php`
### Implementation for User Story 1
- [X] T010 [US1] Append bounded arrival tokens to tenant-dashboard targets emitted from workspace recovery attention and recovery summary metrics in `apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php`
- [X] T011 [US1] Append arrival-context and return-state payloads only for triage-driven tenant opens in `apps/platform/app/Filament/Resources/TenantResource.php` and `apps/platform/app/Filament/Resources/TenantResource/Pages/ListTenants.php`
- [X] T012 [US1] Create the tenant-dashboard continuity widget and template in `apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php` and `apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php`
- [X] T013 [US1] Register the arrival continuity widget first in the tenant dashboard widget stack in `apps/platform/app/Filament/Pages/TenantDashboard.php`
**Checkpoint**: User Story 1 is independently functional and every triage-driven tenant arrival explains why the tenant opened.
---
## Phase 4: User Story 2 - See The Right Next Action (Priority: P2)
**Goal**: Make the arrival continuity block recommend the correct existing backup or restore follow-up surface for the triggering concern.
**Independent Test**: Render arrivals for backup-absent, backup-stale, backup-degraded, recovery-unvalidated, and recovery-weakened concerns and verify the continuity block recommends the matching existing follow-up surface while staying truthful when access is limited.
### Tests for User Story 2
- [X] T014 [P] [US2] Extend tenant-dashboard continuity coverage for backup-vs-restore next-step guidance and disabled-CTA degradation in `apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php`
- [X] T015 [P] [US2] Extend downstream continuity regressions for arrival-driven `backup_health_reason` and `recovery_posture_reason` behavior in `apps/platform/tests/Feature/Filament/BackupSetListContinuityTest.php` and `apps/platform/tests/Feature/Filament/RestoreRunListContinuityTest.php`
### Implementation for User Story 2
- [X] T016 [US2] Derive concern-family-specific next-step targets, downstream reason params, and disabled helper text in `apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextResolver.php`
- [X] T017 [US2] Render concern-specific next-step labels, claim boundaries, and disabled follow-up guidance in `apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php` and `apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php`
- [X] T018 [US2] Preserve existing backup and restore continuity ownership while accepting arrival-driven follow-up params in `apps/platform/app/Filament/Resources/BackupSetResource/Pages/ListBackupSets.php`, `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ListRestoreRuns.php`, and `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ViewRestoreRun.php`
**Checkpoint**: User Story 2 is independently functional and the arrival block tells the operator the correct next action for each concern family.
---
## Phase 5: User Story 3 - Return To Portfolio Flow (Priority: P2)
**Goal**: Let operators leave the tenant surface and resume the same workspace or tenant-registry triage flow they came from.
**Independent Test**: Open a tenant from workspace overview and from filtered tenant-registry triage, use the return affordance, and verify the originating workspace or filtered registry context is restored.
### Tests for User Story 3
- [X] T019 [P] [US3] Add workspace-overview return-target coverage for tenant-dashboard arrivals in `apps/platform/tests/Feature/Filament/WorkspaceOverviewArrivalContextTest.php`
- [X] T020 [P] [US3] Add filtered tenant-registry return-state coverage for preserved `backup_posture`, `recovery_evidence`, and `triage_sort` values in `apps/platform/tests/Feature/Filament/TenantRegistryArrivalContextTest.php`
- [X] T021 [P] [US3] Add tenant-dashboard return-affordance rendering and navigation coverage in `apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php`
### Implementation for User Story 3
- [X] T022 [US3] Build bounded workspace-overview and tenant-registry return targets in `apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextResolver.php`
- [X] T023 [US3] Reuse the existing triage-filter sanitizers when emitting and restoring return-state query params in `apps/platform/app/Filament/Resources/TenantResource.php` and `apps/platform/app/Filament/Resources/TenantResource/Pages/ListTenants.php`
- [X] T024 [US3] Render the return-to-portfolio affordance only for valid arrival contexts in `apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php` and `apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php`
**Checkpoint**: User Story 3 is independently functional and operators can continue portfolio triage without reconstructing context manually.
---
## Phase 6: User Story 4 - Stay Honest When Truth Or Access Changes (Priority: P3)
**Goal**: Keep arrival continuity truthful when posture changes, multiple concerns coexist, the token is invalid, or the operator lacks access to the deeper follow-up surface.
**Independent Test**: Open triage-driven arrivals after posture changes, with multiple concerns, without any arrival token, with malformed tokens, and under RBAC-limited access; verify the page preserves why the operator came while keeping current truth and access limits explicit.
### Tests for User Story 4
- [X] T025 [P] [US4] Extend tenant-dashboard continuity coverage for stale-context honesty, multiple-concern wording, invalid-token suppression, and generic-session calmness in `apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php`
- [X] T026 [P] [US4] Add positive and negative RBAC arrival-visibility coverage for enabled follow-up links, degraded guidance, 403 capability denials, and 404 deny-as-not-found semantics in `apps/platform/tests/Feature/Rbac/TenantDashboardArrivalContextVisibilityTest.php`
### Implementation for User Story 4
- [X] T027 [US4] Differentiate arrival reason from current tenant truth, surface multi-concern wording, and fail closed on stale or malformed tokens in `apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextResolver.php`
- [X] T028 [US4] Keep the continuity block additive, suppress it for generic or invalid sessions, and render truthful current-truth deltas in `apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php`, `apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php`, and `apps/platform/app/Filament/Pages/TenantDashboard.php`
**Checkpoint**: User Story 4 is independently functional and continuity remains truthful across stale truth, multiple concerns, generic sessions, and RBAC limits.
---
## Phase 7: Polish & Cross-Cutting Concerns
**Purpose**: Final alignment, formatting, and focused verification across all stories.
- [X] T029 [P] Extend legacy source-route preservation regressions in `apps/platform/tests/Feature/Filament/WorkspaceOverviewContentTest.php` and `apps/platform/tests/Feature/Filament/TenantRegistryRecoveryTriageTest.php` so existing non-dashboard destinations remain authoritative when current routing chooses them
- [X] T030 [P] Add query-shape and request-local resolution regression coverage in `apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextPerformanceTest.php`
- [X] T031 [P] Review operator-facing continuity copy and `Verb + Object` link labels in `apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextResolver.php`, `apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php`, `apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php`, `apps/platform/app/Filament/Resources/BackupSetResource/Pages/ListBackupSets.php`, and `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ListRestoreRuns.php`
- [X] T032 [P] Run formatting for touched files with `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` using `specs/187-portfolio-triage-arrival-context/quickstart.md`
- [X] T033 Run the focused verification pack from `specs/187-portfolio-triage-arrival-context/quickstart.md` against `apps/platform/tests/Unit/Support/PortfolioTriage/PortfolioArrivalContextTokenTest.php`, `apps/platform/tests/Unit/Support/PortfolioTriage/PortfolioArrivalContextResolverTest.php`, `apps/platform/tests/Feature/Filament/WorkspaceOverviewArrivalContextTest.php`, `apps/platform/tests/Feature/Filament/TenantRegistryArrivalContextTest.php`, `apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php`, `apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextPerformanceTest.php`, `apps/platform/tests/Feature/Filament/WorkspaceOverviewContentTest.php`, `apps/platform/tests/Feature/Filament/TenantRegistryRecoveryTriageTest.php`, `apps/platform/tests/Feature/Filament/BackupSetListContinuityTest.php`, `apps/platform/tests/Feature/Filament/RestoreRunListContinuityTest.php`, and `apps/platform/tests/Feature/Rbac/TenantDashboardArrivalContextVisibilityTest.php`
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: Starts immediately and prepares shared fixtures.
- **Foundational (Phase 2)**: Depends on Setup and blocks all user stories until the arrival-context contract, token, and resolver exist.
- **User Story 1 (Phase 3)**: Starts after Foundational and is the recommended MVP slice.
- **User Story 2 (Phase 4)**: Starts after User Story 1 because the next-step CTA extends the continuity widget and arrival-token seams established there.
- **User Story 3 (Phase 5)**: Starts after User Story 1 because the return affordance depends on the same arrival-context seams but can proceed in parallel with User Story 2 once the base widget exists.
- **User Story 4 (Phase 6)**: Starts after User Stories 2 and 3 because honesty and degradation rules need the final next-step and return-path behaviors in place.
- **Polish (Phase 7)**: Starts after all desired user stories are complete.
### User Story Dependencies
- **US1**: Depends only on the shared arrival-context foundation.
- **US2**: Depends on US1 because concern-specific next-step guidance extends the continuity widget and the emitted arrival tokens.
- **US3**: Depends on US1 because return targets are only meaningful once arrival tokens are already emitted and rendered.
- **US4**: Depends on US2 and US3 because truthful stale-state and RBAC degradation must account for both next-step and return-target behavior.
### Within Each User Story
- Write or extend the story tests first and confirm they fail before implementation is considered complete.
- Land resolver or routing changes before widget copy and view adjustments in the same story.
- Keep each story shippable on its own before moving to the next priority.
### Parallel Opportunities
- `T001` and `T002` can run in parallel during Setup.
- `T003` and `T004` can run in parallel during Foundational work, then `T005` and `T006` can proceed sequentially.
- Within US1, `T007`, `T008`, and `T009` can run in parallel, then `T010`, `T011`, and `T012` can be split before `T013` registers the widget.
- Within US2, `T014` and `T015` can run in parallel, then `T016`, `T017`, and `T018` can be split across contributors.
- Within US3, `T019`, `T020`, and `T021` can run in parallel, then `T022`, `T023`, and `T024` can be split across contributors.
- Within US4, `T025` and `T026` can run in parallel, then `T027` and `T028` can proceed.
- Within Phase 7, `T029` and `T030` can run in parallel, then `T031`, `T032`, and `T033` follow.
---
## Parallel Example: User Story 1
```bash
# User Story 1 tests in parallel
T007 apps/platform/tests/Feature/Filament/WorkspaceOverviewArrivalContextTest.php
T008 apps/platform/tests/Feature/Filament/TenantRegistryArrivalContextTest.php
T009 apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php
# User Story 1 implementation split
T010 apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php
T011 apps/platform/app/Filament/Resources/TenantResource.php and apps/platform/app/Filament/Resources/TenantResource/Pages/ListTenants.php
T012 apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php and apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php
```
## Parallel Example: User Story 2
```bash
# User Story 2 tests in parallel
T014 apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php
T015 apps/platform/tests/Feature/Filament/BackupSetListContinuityTest.php and apps/platform/tests/Feature/Filament/RestoreRunListContinuityTest.php
# User Story 2 implementation split
T016 apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextResolver.php
T017 apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php and apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php
T018 apps/platform/app/Filament/Resources/BackupSetResource/Pages/ListBackupSets.php and apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ListRestoreRuns.php
```
## Parallel Example: User Story 3
```bash
# User Story 3 tests in parallel
T019 apps/platform/tests/Feature/Filament/WorkspaceOverviewArrivalContextTest.php
T020 apps/platform/tests/Feature/Filament/TenantRegistryArrivalContextTest.php
T021 apps/platform/tests/Feature/Filament/TenantDashboardArrivalContextTest.php
# User Story 3 implementation split
T022 apps/platform/app/Support/PortfolioTriage/PortfolioArrivalContextResolver.php
T023 apps/platform/app/Filament/Resources/TenantResource.php and apps/platform/app/Filament/Resources/TenantResource/Pages/ListTenants.php
T024 apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php and apps/platform/resources/views/filament/widgets/tenant/triage-arrival-continuity.blade.php
```
---
## Implementation Strategy
### MVP First
1. Complete Phase 1: Setup.
2. Complete Phase 2: Foundational.
3. Complete Phase 3: User Story 1.
4. Validate that triage-driven tenant arrivals now explain why the tenant opened before any deeper dashboard scan is required.
### Incremental Delivery
1. Add User Story 2 to align the arrival block with the correct existing follow-up surface.
2. Add User Story 3 to preserve the operator's return-to-portfolio flow.
3. Add User Story 4 to harden truthfulness, generic-session calmness, and RBAC-safe degradation.
4. Finish with formatting and the focused verification pack.
### Parallel Team Strategy
1. One contributor can prepare fixture and token coverage while another scaffolds the overview, registry, and dashboard feature tests.
2. After US1 lands, one contributor can take next-step mapping while another implements return-target behavior.
3. Rejoin for US4 and Phase 7 so honesty, legacy route preservation, performance protection, formatting, and verification land together.
---
## Notes
- `[P]` tasks touch separate files or can be split without waiting on unfinished work in the same phase.
- `[US1]`, `[US2]`, `[US3]`, and `[US4]` labels map directly to the user stories in `spec.md`.
- The suggested MVP scope is Phase 1 through Phase 3 only.
- This task plan stays within Filament v5 on Livewire v4, makes no panel-provider changes, introduces no globally searchable resource changes, adds no destructive action, and requires no new asset strategy beyond the project's existing `filament:assets` deployment behavior.