# Tasks: Tenant Selector and Remembered Context Enforcement

**Input**: Design documents from `/specs/147-tenant-selector-remembered-context-enforcement/`
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/

**Tests**: For runtime behavior changes in this repo, tests are REQUIRED (Pest).
**Operations**: This feature does not introduce long-running, remote, queued, or scheduled work. No `OperationRun` creation or lifecycle changes are required.
**RBAC**: This feature hardens admin-plane context behavior without changing the capability model. Tasks MUST preserve `404` for non-members or non-entitled actors and `403` for in-scope capability denial, and MUST include positive and negative authorization regression coverage for tenant-bound and canonical routes.
**UI Naming**: Copy must preserve the distinction between `workspace`, `selected tenant`, `no tenant selected`, `viewed tenant`, and `run tenant`, and must not imply that selected tenant state determines route legitimacy.
**Filament UI Action Surfaces**: This feature does not add new actions. Existing header, row, bulk, and empty-state action inventories must remain consistent while selector and shell semantics are hardened.
**Filament UI UX-001 (Layout & IA)**: Existing layouts remain intact. Tasks below only adjust selector semantics, workspace-safe fallback behavior, and informational mismatch messaging within current screens.
**Badges**: Existing centralized lifecycle presentation from Spec 146 must continue to be used anywhere lifecycle or selector availability is shown.

**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.

## Format: `[ID] [P?] [Story] Description`

- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
- Include exact file paths in descriptions

## Phase 1: Setup (Shared Infrastructure)

**Purpose**: Prepare the focused regression targets and implementation surfaces for context-enforcement work.

- [X] T001 [P] Create the remembered-context unit test target in `tests/Unit/Support/Workspaces/WorkspaceContextRememberedTenantTest.php`
- [X] T002 [P] Create the choose-tenant and workspace-fallback feature test target in `tests/Feature/Workspaces/ChooseTenantPageTest.php`
- [X] T003 [P] Review and extend the existing shell and canonical route regression targets in `tests/Feature/OpsUx/OperateHubShellTest.php` and `tests/Feature/Operations/TenantlessOperationRunViewerTest.php`
- [X] T004 [P] Create the workspace-context global-search safety regression target in `tests/Feature/Rbac/AdminGlobalSearchContextSafetyTest.php`

---

## Phase 2: Foundational (Blocking Prerequisites)

**Purpose**: Centralize selector eligibility, remembered-context validation, and workspace-safe no-tenant fallback before any story-specific surface work begins.

**⚠️ CRITICAL**: No user story work can begin until this phase is complete

- [X] T005 Implement validated remembered-tenant lookup, invalidation, and explicit clear helpers in `app/Support/Workspaces/WorkspaceContext.php`
- [X] T006 [P] Refactor shell active-tenant resolution states for workspace-level, tenant-bound, and canonical routes in `app/Support/OperateHub/OperateHubShell.php`
- [X] T007 [P] Align active-lane selector eligibility helpers across `app/Services/Tenants/TenantOperabilityService.php` and `app/Models/User.php`
- [X] T008 Remove hidden tenant-required gating from workspace-safe middleware and routes in `app/Support/Middleware/EnsureFilamentTenantSelected.php` and `routes/web.php`
- [X] T009 Audit and harden workspace-context global-search scoping so remembered tenant state cannot leak tenant-owned results in `app/Filament/Resources/TenantResource.php`, `app/Filament/Resources/OperationRunResource.php`, and `tests/Feature/Rbac/AdminGlobalSearchContextSafetyTest.php`
- [X] T010 Add foundational coverage for shared remembered-context and shell-resolution behavior in `tests/Unit/Support/Workspaces/WorkspaceContextRememberedTenantTest.php` and `tests/Feature/OpsUx/OperateHubShellTest.php`

**Checkpoint**: Foundation ready. Selector and shell rules are centralized, and user stories can proceed against one shared context model.

---

## Phase 3: User Story 1 - Trust The Active Tenant Selector (Priority: P1) 🎯 MVP

**Goal**: Make the standard header selector and choose-tenant page represent only the normal active operating lane.

**Independent Test**: In one workspace with active, draft, onboarding, and archived tenants, verify that only active tenants appear as selectable choices in both the header selector and choose-tenant page while non-active tenants remain discoverable elsewhere.

### Tests for User Story 1 ⚠️

- [X] T011 [P] [US1] Add choose-tenant eligibility and empty-state assertions in `tests/Feature/Workspaces/ChooseTenantPageTest.php`
- [X] T012 [P] [US1] Add header selector scope and non-active exclusion assertions in `tests/Feature/TenantRBAC/TenantSwitcherScopeTest.php`
- [X] T013 [P] [US1] Add managed-tenant discoverability assertions for onboarding and archived records in `tests/Feature/Filament/ManagedTenantsLandingLifecycleTest.php`

### Implementation for User Story 1

- [X] T014 [US1] Refactor active-lane tenant retrieval and selection handling in `app/Filament/Pages/ChooseTenant.php`
- [X] T015 [US1] Align POST tenant selection enforcement with the shared selector rule in `app/Http/Controllers/SelectTenantController.php`
- [X] T016 [US1] Update choose-tenant copy and card behavior to reflect the active-lane-only selector meaning in `resources/views/filament/pages/choose-tenant.blade.php`
- [X] T017 [US1] Update the header context-bar tenant list and selector affordances to use the same active-lane semantics in `resources/views/filament/partials/context-bar.blade.php`
- [X] T018 [US1] Preserve intentional non-active tenant discoverability in workspace admin surfaces in `app/Filament/Pages/Workspaces/ManagedTenantsLanding.php` and `app/Filament/Resources/TenantResource.php`

**Checkpoint**: User Story 1 is complete when both selector surfaces expose the same active-only operating lane and no contradictory inactive choices remain.

---

## Phase 4: User Story 2 - Recover Safely From Stale Remembered Context (Priority: P2)

**Goal**: Revalidate remembered tenant context on use and degrade cleanly to a legitimate no-tenant workspace state when it becomes stale or invalid.

**Independent Test**: Persist remembered context for an active tenant, then invalidate it by lifecycle change, entitlement loss, or workspace switch and verify the shell falls back to no selected tenant while `/admin`, `/admin/operations`, and `/admin/tenants` remain usable.

### Tests for User Story 2 ⚠️

- [X] T019 [P] [US2] Add remembered-context invalidation scenarios for workspace mismatch, missing tenant, and selector-ineligible lifecycle in `tests/Unit/Support/Workspaces/WorkspaceContextRememberedTenantTest.php`
- [X] T020 [P] [US2] Add workspace switch, explicit clear, and no-selected-tenant fallback assertions in `tests/Feature/Workspaces/ChooseTenantPageTest.php`, `tests/Feature/Workspaces/ChooseWorkspaceRedirectsToChooseTenantTest.php`, and `tests/Feature/Rbac/TenantResourceAuthorizationTest.php`

### Implementation for User Story 2

- [X] T021 [US2] Update workspace-switch and explicit-clear flows to preserve workspace-safe no-tenant fallback in `app/Http/Controllers/SwitchWorkspaceController.php` and `app/Http/Controllers/ClearTenantContextController.php`
- [X] T022 [US2] Remove workspace-page assumptions that an active tenant is required in `app/Filament/Pages/Monitoring/Operations.php`, `app/Filament/Resources/TenantResource.php`, and `app/Support/Middleware/EnsureFilamentTenantSelected.php`
- [X] T023 [US2] Update shell and chooser copy to present “no tenant selected” as a legitimate workspace state in `resources/views/filament/partials/context-bar.blade.php` and `resources/views/filament/pages/choose-tenant.blade.php`

**Checkpoint**: User Story 2 is complete when stale remembered context clears deterministically and workspace-level pages continue working without selected tenant state.

---

## Phase 5: User Story 3 - Keep Route Legitimacy Separate From Header Context (Priority: P3)

**Goal**: Preserve route-authoritative behavior for tenant-bound pages and canonical run viewers even when selected tenant context differs, is empty, or has just been cleared.

**Independent Test**: Open authorized tenant-bound and canonical run routes with mismatched, stale, or empty selected tenant state and verify the pages still resolve while non-member or non-entitled access keeps `404` semantics and capability denial keeps `403` semantics.

### Tests for User Story 3 ⚠️

- [X] T024 [P] [US3] Add positive and negative tenant-bound route-authority assertions in `tests/Feature/TenantRBAC/ArchivedTenantRouteAccessTest.php` and `tests/Feature/TenantRBAC/TenantRouteDenyAsNotFoundTest.php`
- [X] T025 [P] [US3] Add canonical run mismatch, no-selected-tenant, entitlement, and capability assertions in `tests/Feature/Operations/TenantlessOperationRunViewerTest.php`

### Implementation for User Story 3

- [X] T026 [US3] Refine route-authoritative tenant resolution for admin-panel pages in `app/Support/OperateHub/OperateHubShell.php` and `app/Filament/Concerns/ResolvesPanelTenantContext.php`
- [X] T027 [US3] Preserve mismatch-as-information behavior for canonical run viewing in `app/Filament/Pages/Operations/TenantlessOperationRunViewer.php` and `resources/views/filament/pages/operations/tenantless-operation-run-viewer.blade.php`
- [X] T028 [US3] Audit workspace and canonical route integration so selected tenant never acts as a legitimacy shortcut in `routes/web.php` and `app/Policies/OperationRunPolicy.php`

**Checkpoint**: User Story 3 is complete when route identity and policy fully outrank selected tenant state on tenant-bound and canonical pages.

---

## Phase 6: Polish & Cross-Cutting Concerns

**Purpose**: Final regression validation, formatting, and manual verification across all stories.

- [X] T029 [P] Run focused Pest suites and render/query-safety validation covering `tests/Unit/Support/Workspaces/WorkspaceContextRememberedTenantTest.php`, `tests/Feature/Workspaces/ChooseTenantPageTest.php`, `tests/Feature/Workspaces/ChooseWorkspaceRedirectsToChooseTenantTest.php`, `tests/Feature/Filament/ManagedTenantsLandingLifecycleTest.php`, `tests/Feature/TenantRBAC/TenantSwitcherScopeTest.php`, `tests/Feature/Rbac/TenantResourceAuthorizationTest.php`, `tests/Feature/Rbac/AdminGlobalSearchContextSafetyTest.php`, `tests/Feature/TenantRBAC/ArchivedTenantRouteAccessTest.php`, `tests/Feature/TenantRBAC/TenantRouteDenyAsNotFoundTest.php`, `tests/Feature/OpsUx/OperateHubShellTest.php`, and `tests/Feature/Operations/TenantlessOperationRunViewerTest.php`
- [X] T030 Run formatting for touched files with `vendor/bin/sail bin pint --dirty --format agent`
- [X] T031 [P] Validate the manual verification checklist in `specs/147-tenant-selector-remembered-context-enforcement/quickstart.md` and review `/admin/tenants` plus `/admin/operations` against `docs/product/standards/list-surface-review-checklist.md`

---

## Dependencies & Execution Order

### Phase Dependencies

- **Setup (Phase 1)**: No dependencies, can start immediately
- **Foundational (Phase 2)**: Depends on Setup completion and blocks all story work
- **User Story 1 (Phase 3)**: Depends on Foundational completion
- **User Story 2 (Phase 4)**: Depends on Foundational completion and benefits from US1 surface alignment
- **User Story 3 (Phase 5)**: Depends on Foundational completion and is safest after US1 and US2 because it hardens route behavior on the same shell/context surfaces
- **Polish (Phase 6)**: Depends on all desired user stories being complete

### User Story Dependencies

- **User Story 1 (P1)**: No dependency on other stories after Foundational; this is the MVP slice
- **User Story 2 (P2)**: Depends on the shared context-validation foundation and uses the selector semantics stabilized in US1
- **User Story 3 (P3)**: Depends on the shared context-validation foundation and benefits from the no-tenant and selector semantics stabilized in US1 and US2

### Within Each User Story

- Tests for the story should be written first and fail before implementation
- Shared support-layer changes should land before UI surface refinements
- Route and middleware behavior should be stabilized before final mismatch-copy adjustments
- Story-specific validation should pass before moving to the next priority story

### Parallel Opportunities

- T001, T002, T003, and T004 can run in parallel because they prepare separate test targets
- T006 and T007 can run in parallel after T005 defines the shared remembered-context contract
- T011, T012, and T013 can run in parallel because they cover different selector and discoverability surfaces
- T019 and T020 can run in parallel because they cover different fallback paths
- T024 and T025 can run in parallel because they cover different route categories
- T029 and T031 can run in parallel after implementation is complete

---

## Parallel Example: User Story 1

```bash
# Launch the P1 selector regression tasks together:
Task: "Add choose-tenant eligibility and empty-state assertions in tests/Feature/Workspaces/ChooseTenantPageTest.php"
Task: "Add header selector scope and non-active exclusion assertions in tests/Feature/TenantRBAC/TenantSwitcherScopeTest.php"
Task: "Add managed-tenant discoverability assertions in tests/Feature/Filament/ManagedTenantsLandingLifecycleTest.php"
```

## Parallel Example: User Story 2

```bash
# After the foundation is in place, stale-context validation and workspace-switch coverage can proceed together:
Task: "Add remembered-context invalidation scenarios in tests/Unit/Support/Workspaces/WorkspaceContextRememberedTenantTest.php"
Task: "Add workspace switch and no-selected-tenant fallback assertions in tests/Feature/Workspaces/ChooseTenantPageTest.php, tests/Feature/Workspaces/ChooseWorkspaceRedirectsToChooseTenantTest.php, and tests/Feature/Rbac/TenantResourceAuthorizationTest.php"
```

## Parallel Example: User Story 3

```bash
# Route-authority coverage can split by tenant-bound and canonical routes:
Task: "Add tenant-bound route-authority assertions in tests/Feature/TenantRBAC/ArchivedTenantRouteAccessTest.php and tests/Feature/TenantRBAC/TenantRouteDenyAsNotFoundTest.php"
Task: "Add canonical run mismatch and authorization assertions in tests/Feature/Operations/TenantlessOperationRunViewerTest.php"
```

---

## Implementation Strategy

### MVP First (User Story 1 Only)

1. Complete Phase 1: Setup
2. Complete Phase 2: Foundational
3. Complete Phase 3: User Story 1
4. **Stop and validate** the selector semantics independently on the header selector and choose-tenant page
5. Demo or merge the MVP slice if acceptable

### Incremental Delivery

1. Complete Setup + Foundational to establish one shared context model
2. Deliver User Story 1 to make the active selector trustworthy
3. Deliver User Story 2 to make stale remembered context recover safely
4. Deliver User Story 3 to harden tenant-bound and canonical route authority
5. Finish with Polish for regression validation and formatting

### Team Strategy

1. One engineer owns the support-layer foundation in `WorkspaceContext`, `OperateHubShell`, and middleware/routes
2. A second engineer prepares selector-surface and fallback regression coverage in parallel once the shared context contract is clear
3. Route-authority hardening for canonical and tenant-bound pages can proceed as a separate stream after the foundation is merged

---

## Notes

- [P] tasks touch separate files and can be worked in parallel without blocking each other
- Every user story remains independently testable after the foundational phase
- This feature does not add schema changes, Graph calls, or new operations workflows
- Keep route legitimacy tied to route subject and policy, never to raw remembered tenant session state