13 KiB
| description |
|---|
| Task list for Spec 077 implementation |
Tasks: Workspace-first Navigation & Monitoring Hub (077)
Input: Design documents from /specs/077-workspace-nav-monitoring-hub/
Prerequisites:
- Required: spec.md, plan.md
- Optional (used): research.md, data-model.md, contracts/routes.md, quickstart.md
Tests: REQUIRED (Pest) — this feature changes runtime behavior (navigation + authorization + filtering).
Livewire/Filament compatibility: Filament v5 + Livewire v4 only.
Phase 1: Setup (Shared Infrastructure)
Purpose: Prepare the minimal scaffolding for safe, test-first delivery.
- T001 Create new Pest test file for workspace navigation in tests/Feature/Workspaces/WorkspaceNavigationHubTest.php
- T002 Create new Pest test file for operations canonical routing in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
- T003 [P] Create new Pest test file for non-leakage semantics in tests/Feature/OpsUx/NonLeakageWorkspaceOperationsTest.php
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Shared plumbing needed by multiple stories.
- T004 Add intended-URL session key constant in app/Support/Workspaces/WorkspaceContext.php
- T005 Implement “store intended URL” helper in app/Support/Workspaces/WorkspaceIntendedUrl.php
- T006 [P] Add tests for intended-URL helper in tests/Feature/Workspaces/WorkspaceIntendedUrlTest.php
- T007 Update middleware to use intended-URL helper in app/Http/Middleware/EnsureWorkspaceSelected.php
- T008 [P] Add safe-redirect allowlist for intended URLs in app/Support/Workspaces/WorkspaceIntendedUrl.php
Checkpoint: Intended redirect plumbing exists and is covered by tests.
Phase 3: User Story 1 — Switch workspace without ambiguity (Priority: P1) 🎯 MVP
Goal: Clear separation between “Switch workspace” and “Manage workspaces”, with correct 404/403 behavior.
Independent Test: A signed-in user can switch workspaces via “Switch workspace”, and “Manage workspaces” is only visible/accessible when authorized.
Tests for User Story 1 (write first)
- T009 [P] [US1] Assert nav label “Switch workspace” appears when tenant is not selected in tests/Feature/Workspaces/WorkspaceNavigationHubTest.php
- T010 [P] [US1] Assert no ambiguous “Workspaces” nav item exists in tests/Feature/Workspaces/WorkspaceNavigationHubTest.php
- T011 [P] [US1] Assert
/admin/workspacesis tenantless and reachable for a workspace owner in tests/Feature/Workspaces/WorkspacesResourceIsTenantlessTest.php - T012 [P] [US1] Assert
/admin/workspaces/{record}is deny-as-not-found for non-members (404) in tests/Feature/Workspaces/WorkspacesResourceIsTenantlessTest.php
Implementation for User Story 1
- T013 [US1] Rename fallback nav item to “Switch workspace” in app/Support/Middleware/EnsureFilamentTenantSelected.php
- T014 [US1] Update user-menu copy/CTA to “Switch workspace” in resources/views/filament/partials/workspace-switcher.blade.php
- T015 [US1] Rename admin sidebar item to “Manage workspaces” in app/Providers/Filament/AdminPanelProvider.php
- T016 [US1] Gate “Manage workspaces” navigation visibility via capability in app/Providers/Filament/AdminPanelProvider.php
- T017 [US1] Enforce workspace-scoped RBAC semantics for workspace management (404 non-member, 403 missing capability) in app/Policies/WorkspacePolicy.php
- T018 [US1] Ensure workspace management breadcrumbs point to
/admin/workspacesin app/Filament/Resources/Workspaces/WorkspaceResource.php - T019 [US1] Ensure
/admin/workspacesroutes do not require tenant context in app/Support/Middleware/EnsureFilamentTenantSelected.php - T020 [US1] Run focused tests for US1 via
./vendor/bin/sail artisan test --compact --filter=WorkspaceNavigationHub(document in specs/077-workspace-nav-monitoring-hub/quickstart.md)
Checkpoint: UI uses unambiguous labels; /admin/workspaces follows workspace RBAC semantics (no leakage).
Phase 4: User Story 2 — Use Monitoring hub from canonical links (Priority: P2)
Goal: /admin/operations and /admin/operations/{run} work regardless of tenant context; tenant context only sets removable default filters.
Independent Test: Visiting /admin/operations works tenantless (workspace-selected), and in tenant context it defaults to that tenant via a removable filter chip.
Tests for User Story 2 (write first)
- T021 [P] [US2] Assert
/admin/operationsis reachable without tenant context in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php - T022 [P] [US2] Assert
/admin/operations/{run}works with and without tenant context in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php - T023 [P] [US2] Assert operations list defaults to current tenant (filter state) when tenant context active in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
- T024 [P] [US2] Assert clearing tenant filter shows workspace-wide runs in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
Implementation for User Story 2
- T025 [US2] Allow
/admin/operations(index) through tenancy-enforcing middleware without auto-setting tenant in app/Support/Middleware/EnsureFilamentTenantSelected.php - T026 [US2] Ensure workspace selection is required for
/admin/operationsand stores intended URL for return flow in app/Http/Middleware/EnsureWorkspaceSelected.php - T027 [US2] Redirect back to intended URL after workspace selection in both app/Filament/Pages/ChooseWorkspace.php and app/Http/Controllers/SwitchWorkspaceController.php
- T028 [US2] Remove hard tenant scoping from query in app/Filament/Resources/OperationRunResource.php
- T029 [US2] Add tenant SelectFilter with removable chip and server-side default state in app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
- T030 [US2] Scope selectable tenants in the filter to current workspace in app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
- T031 [US2] Add “Recent operations” summary (last 5 by created_at) + “View all operations” CTA on tenant view page in app/Filament/Resources/TenantResource/Pages/ViewTenant.php
- T032 [US2] Ensure “View all operations” CTA routes to canonical
/admin/operationsin app/Filament/Resources/TenantResource/Pages/ViewTenant.php - T033 [US2] Ensure operations pages remain DB-only (no Graph calls) by extending existing checks in tests/Feature/MonitoringOperationsTest.php
- T034 [US2] Run focused tests for US2 via
./vendor/bin/sail artisan test --compact --filter=OperationsCanonicalUrlsand update specs/077-workspace-nav-monitoring-hub/quickstart.md
Checkpoint: Canonical operations URLs work; tenant context only affects default filter state.
Phase 5: User Story 3 — Navigate and search without leaking inaccessible data (Priority: P3)
Goal: Enforce strict 404 vs 403 semantics without leaking admin surfaces or cross-workspace/tenant data.
Independent Test: Non-members get 404; members missing capability get 403, and no navigation labels hint at inaccessible features.
Tests for User Story 3 (write first)
- T035 [P] [US3] Assert non-member access to another workspace’s operations is 404 in tests/Feature/OpsUx/NonLeakageWorkspaceOperationsTest.php
- T036 [P] [US3] Assert member missing
workspace.managegets 403 on/admin/workspaces/{record}/editin tests/Feature/OpsUx/NonLeakageWorkspaceOperationsTest.php - T037 [P] [US3] Assert invalid tenant context is auto-cleared when switching workspace in tests/Feature/Workspaces/ManagedTenantsWorkspaceRoutingTest.php
- T038 [P] [US3] Assert reserved Monitoring placeholder pages exist (
/admin/alerts,/admin/audit-log) in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
Implementation for User Story 3
- T039 [US3] Implement “auto-clear invalid tenant context” check in app/Support/Middleware/EnsureFilamentTenantSelected.php
- T040 [US3] Confirm and implement correct Filament v5 mechanism for clearing persisted tenant state in app/Support/Middleware/EnsureFilamentTenantSelected.php
- T041 [US3] Implement reserved Monitoring placeholder pages (Alerts, Audit Log) as Filament pages under app/Filament/Pages/Monitoring/**
- T042 [US3] Ensure navigation does not expose admin-only surfaces to unauthorized users in app/Providers/Filament/AdminPanelProvider.php
- T043 [US3] Verify global search does not introduce new leakage for operations/workspaces and, if needed, disable global search for resources without view/edit pages in app/Filament/**
- T044 [US3] Run focused tests for US3 via
./vendor/bin/sail artisan test --compact --filter=NonLeakageWorkspaceOperations
Checkpoint: 404/403 behavior matches spec; no cross-scope leaks.
Phase 6: Polish & Cross-Cutting Concerns
Purpose: Stabilize, format, and validate end-to-end.
- T045 Run formatter on touched files via
./vendor/bin/sail bin pint --dirty - T046 Run targeted full suite for touched areas via
./vendor/bin/sail artisan test --compact tests/Feature/Workspaces tests/Feature/Monitoring tests/Feature/OpsUx - T047 [P] Confirm manual quickstart steps still match UI labels and routes in specs/077-workspace-nav-monitoring-hub/quickstart.md
- T048 [P] Confirm route semantics still match contracts in specs/077-workspace-nav-monitoring-hub/contracts/routes.md
- T049 Ensure Filament v5 + Livewire v4 APIs are used (no v3/v4 Filament APIs) in app/Filament/**
- T050 Run full suite (optional) via
./vendor/bin/sail artisan test --compact
Post-implementation bugfixes
- T058 Fix route conflict so Operations “View” consistently hits canonical
/admin/operations/{run}by moving Filament resource view route to/admin/operations/r/{record}in app/Filament/Resources/OperationRunResource.php
Phase 7: Addendum — Header Context Bar (FR-077-016)
Goal: Always-visible context bar for Workspace + Tenant, usable on tenantless pages without implicit switching.
Tests (write first)
- T051 [P] [FR-077-016] Assert tenant picker renders on
/admin/operationsin tests/Feature/Monitoring/HeaderContextBarTest.php - T052 [P] [FR-077-016] Assert tenant picker lists only entitled tenants in tests/Feature/Monitoring/HeaderContextBarTest.php
- T053 [P] [FR-077-016] Assert deep link
/admin/operations/{run}does not auto-switch tenant in tests/Feature/Monitoring/HeaderContextBarTest.php
Implementation
- T054 [FR-077-016] Render context bar in topbar via render hook in app/Providers/Filament/AdminPanelProvider.php
- T055 [FR-077-016] Add context bar partial view in resources/views/filament/partials/context-bar.blade.php
- T056 [FR-077-016] Remove implicit tenant auto-selection behavior while preserving deny-as-not-found semantics in app/Support/Middleware/EnsureFilamentTenantSelected.php
- T057 [FR-077-016] Persist last-selected tenant per workspace session in app/Support/Workspaces/WorkspaceContext.php and controllers/pages that select tenants
Checkpoint: Tenant picker usable on tenantless pages; no silent tenant switching.
Dependencies & Execution Order
Phase Dependencies
- Phase 1 (Setup) → Phase 2 (Foundational)
- Phase 2 (Foundational) → Phase 3+ (User stories)
- Phase 3 (US1) is the MVP and should be delivered first.
- Phase 4 (US2) depends on the clarified navigation + intended-URL plumbing (Phases 1–2).
- Phase 5 (US3) depends on the implemented behavior from US1/US2 so it can assert non-leakage.
User Story Dependencies
- US1 → US2: soft dependency (naming + intended redirect improves US2 flows)
- US2 → US3: recommended dependency (US3 asserts final 404/403 and filter semantics)
Parallel Execution Examples
US1 parallelizable work
- T009, T010, T011, T012 can be written in parallel (different assertions/files)
- T013, T014, T015 can be implemented in parallel (different files)
US2 parallelizable work
- T021–T024 can be written in parallel
- T028 (resource query) and T029 (table filters) can be implemented in parallel
- T031–T032 can be implemented in parallel with operations filter work (different file)
US3 parallelizable work
- T035–T038 can be written in parallel
- T039–T042 can be implemented in parallel (different files)
Implementation Strategy
MVP scope (recommended)
- Deliver Phase 1–3 (US1) only.
- Validate with
./vendor/bin/sail artisan test --compact --filter=WorkspaceNavigationHub. - Demo “Switch workspace” vs “Manage workspaces” clarity + correct 404/403 behavior.
Incremental delivery
- Add US2 (canonical operations URLs + removable tenant default filter)
- Add US3 (non-leakage regression guards)
- Finish with Phase 6 polish and a full suite run