Implements Spec 077 refinements: workspace Global Mode and navigation/context-bar redundancy cleanup.
Summary
- Global Mode: `/admin/workspaces` is workspace-optional (lists only member workspaces); explicit allowlist in `EnsureWorkspaceSelected`.
- Navigation cleanup: workspace switching is topbar-only; no sidebar “Switch workspace”; removes redundant “Manage workspaces” entry from context-bar.
- Context bar: when no workspace selected, tenant picker is disabled with guidance; on tenant-scoped routes `/admin/t/{tenant}/…` the tenant indicator is read-only (Filament tenant menu remains primary).
- Authorization: workspace creation is policy-driven (`WorkspacePolicy::create()`), enforced in `ChooseWorkspace` via Gate.
Safety / Compliance
- Livewire v4.0+ compliant (Filament v5).
- Panel provider registration remains in `bootstrap/providers.php` (no changes required).
- Global search: no new globally searchable resources added; no behavior changes introduced.
- Destructive actions: none added/changed.
- Assets: no new assets registered; deploy process unchanged (if assets are registered elsewhere, ensure `php artisan filament:assets` runs in deploy as usual).
Tests
- `vendor/bin/sail bin pint --dirty`
- `vendor/bin/sail artisan test --compact tests/Feature/Workspaces tests/Feature/Monitoring tests/Feature/OpsUx tests/Feature/Filament/WorkspaceContextTopbarAndTenantSelectionTest.php`
Spec artifacts
- `specs/077-workspace-nav-monitoring-hub/{spec,plan,tasks}.md`
- `specs/077-workspace-nav-monitoring-hub/contracts/routes.md`
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #94
221 lines
14 KiB
Markdown
221 lines
14 KiB
Markdown
---
|
||
|
||
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](spec.md), [plan.md](plan.md)
|
||
- Optional (used): [research.md](research.md), [data-model.md](data-model.md), [contracts/routes.md](contracts/routes.md), [quickstart.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.
|
||
|
||
- [X] T001 Create new Pest test file for workspace navigation in tests/Feature/Workspaces/WorkspaceNavigationHubTest.php
|
||
- [X] T002 Create new Pest test file for operations canonical routing in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
|
||
- [X] 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.
|
||
|
||
- [X] T004 Add intended-URL session key constant in app/Support/Workspaces/WorkspaceContext.php
|
||
- [X] T005 Implement “store intended URL” helper in app/Support/Workspaces/WorkspaceIntendedUrl.php
|
||
- [X] T006 [P] Add tests for intended-URL helper in tests/Feature/Workspaces/WorkspaceIntendedUrlTest.php
|
||
- [X] T007 Update middleware to use intended-URL helper in app/Http/Middleware/EnsureWorkspaceSelected.php
|
||
- [X] 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)
|
||
|
||
- [X] T009 [P] [US1] Assert nav label “Switch workspace” appears when tenant is not selected in tests/Feature/Workspaces/WorkspaceNavigationHubTest.php
|
||
- [X] T010 [P] [US1] Assert no ambiguous “Workspaces” nav item exists in tests/Feature/Workspaces/WorkspaceNavigationHubTest.php
|
||
- [X] T011 [P] [US1] Assert `/admin/workspaces` is tenantless and reachable for a workspace owner in tests/Feature/Workspaces/WorkspacesResourceIsTenantlessTest.php
|
||
- [X] 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
|
||
|
||
- [X] T013 [US1] Rename fallback nav item to “Switch workspace” in app/Support/Middleware/EnsureFilamentTenantSelected.php
|
||
- [X] T014 [US1] Update user-menu copy/CTA to “Switch workspace” in resources/views/filament/partials/workspace-switcher.blade.php
|
||
- [X] T015 [US1] Rename admin sidebar item to “Manage workspaces” in app/Providers/Filament/AdminPanelProvider.php
|
||
- [X] T016 [US1] Gate “Manage workspaces” navigation visibility via capability in app/Providers/Filament/AdminPanelProvider.php
|
||
- [X] T017 [US1] Enforce workspace-scoped RBAC semantics for workspace management (404 non-member, 403 missing capability) in app/Policies/WorkspacePolicy.php
|
||
- [X] T018 [US1] Ensure workspace management breadcrumbs point to `/admin/workspaces` in app/Filament/Resources/Workspaces/WorkspaceResource.php
|
||
- [X] T019 [US1] Ensure `/admin/workspaces` routes do not require tenant context in app/Support/Middleware/EnsureFilamentTenantSelected.php
|
||
- [X] 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)
|
||
|
||
- [X] T021 [P] [US2] Assert `/admin/operations` is reachable without tenant context in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
|
||
- [X] T022 [P] [US2] Assert `/admin/operations/{run}` works with and without tenant context in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
|
||
- [X] T023 [P] [US2] Assert operations list defaults to current tenant (filter state) when tenant context active in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
|
||
- [X] T024 [P] [US2] Assert clearing tenant filter shows workspace-wide runs in tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
|
||
|
||
### Implementation for User Story 2
|
||
|
||
- [X] T025 [US2] Allow `/admin/operations` (index) through tenancy-enforcing middleware without auto-setting tenant in app/Support/Middleware/EnsureFilamentTenantSelected.php
|
||
- [X] T026 [US2] Ensure workspace selection is required for `/admin/operations` and stores intended URL for return flow in app/Http/Middleware/EnsureWorkspaceSelected.php
|
||
- [X] T027 [US2] Redirect back to intended URL after workspace selection in both app/Filament/Pages/ChooseWorkspace.php and app/Http/Controllers/SwitchWorkspaceController.php
|
||
- [X] T028 [US2] Remove hard tenant scoping from query in app/Filament/Resources/OperationRunResource.php
|
||
- [X] T029 [US2] Add tenant SelectFilter with removable chip and server-side default state in app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
|
||
- [X] T030 [US2] Scope selectable tenants in the filter to current workspace in app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
|
||
- [X] 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
|
||
- [X] T032 [US2] Ensure “View all operations” CTA routes to canonical `/admin/operations` in app/Filament/Resources/TenantResource/Pages/ViewTenant.php
|
||
- [X] T033 [US2] Ensure operations pages remain DB-only (no Graph calls) by extending existing checks in tests/Feature/MonitoringOperationsTest.php
|
||
- [X] T034 [US2] Run focused tests for US2 via `./vendor/bin/sail artisan test --compact --filter=OperationsCanonicalUrls` and 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)
|
||
|
||
- [X] T035 [P] [US3] Assert non-member access to another workspace’s operations is 404 in tests/Feature/OpsUx/NonLeakageWorkspaceOperationsTest.php
|
||
- [X] T036 [P] [US3] Assert member missing `workspace.manage` gets 403 on `/admin/workspaces/{record}/edit` in tests/Feature/OpsUx/NonLeakageWorkspaceOperationsTest.php
|
||
- [X] T037 [P] [US3] Assert invalid tenant context is auto-cleared when switching workspace in tests/Feature/Workspaces/ManagedTenantsWorkspaceRoutingTest.php
|
||
- [X] 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
|
||
|
||
- [X] T039 [US3] Implement “auto-clear invalid tenant context” check in app/Support/Middleware/EnsureFilamentTenantSelected.php
|
||
- [X] T040 [US3] Confirm and implement correct Filament v5 mechanism for clearing persisted tenant state in app/Support/Middleware/EnsureFilamentTenantSelected.php
|
||
- [X] T041 [US3] Implement reserved Monitoring placeholder pages (Alerts, Audit Log) as Filament pages under app/Filament/Pages/Monitoring/**
|
||
- [X] T042 [US3] Ensure navigation does not expose admin-only surfaces to unauthorized users in app/Providers/Filament/AdminPanelProvider.php
|
||
- [X] 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/**
|
||
- [X] 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.
|
||
|
||
- [X] T045 Run formatter on touched files via `./vendor/bin/sail bin pint --dirty`
|
||
- [X] T046 Run targeted full suite for touched areas via `./vendor/bin/sail artisan test --compact tests/Feature/Workspaces tests/Feature/Monitoring tests/Feature/OpsUx`
|
||
- [X] T047 [P] Confirm manual quickstart steps still match UI labels and routes in specs/077-workspace-nav-monitoring-hub/quickstart.md
|
||
- [X] T048 [P] Confirm route semantics still match contracts in specs/077-workspace-nav-monitoring-hub/contracts/routes.md
|
||
- [X] T049 Ensure Filament v5 + Livewire v4 APIs are used (no v3/v4 Filament APIs) in app/Filament/**
|
||
- [X] T050 Run full suite (optional) via `./vendor/bin/sail artisan test --compact`
|
||
|
||
### Post-implementation bugfixes
|
||
|
||
- [X] 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
|
||
- [X] T059 Remove “Switch workspace” from sidebar navigation (workspace switching is topbar-only) in app/Providers/Filament/AdminPanelProvider.php and app/Support/Middleware/EnsureFilamentTenantSelected.php
|
||
- [X] T060 Define Global Mode: make `/admin/workspaces` workspace-optional + add explicit allowlist in app/Http/Middleware/EnsureWorkspaceSelected.php
|
||
- [X] T061 Disable tenant picker when no workspace is active (Global Mode) in resources/views/filament/partials/context-bar.blade.php
|
||
- [X] T062 Remove “Manage workspaces” link from the topbar context switcher to avoid redundant entry points in resources/views/filament/partials/context-bar.blade.php
|
||
- [X] T063 Unify workspace creation authorization: ChooseWorkspace create action must use WorkspacePolicy (Gate) in app/Filament/Pages/ChooseWorkspace.php and app/Policies/WorkspacePolicy.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)
|
||
|
||
- [X] T051 [P] [FR-077-016] Assert tenant picker renders on `/admin/operations` in tests/Feature/Monitoring/HeaderContextBarTest.php
|
||
- [X] T052 [P] [FR-077-016] Assert tenant picker lists only entitled tenants in tests/Feature/Monitoring/HeaderContextBarTest.php
|
||
- [X] T053 [P] [FR-077-016] Assert deep link `/admin/operations/{run}` does not auto-switch tenant in tests/Feature/Monitoring/HeaderContextBarTest.php
|
||
|
||
### Implementation
|
||
|
||
- [X] T054 [FR-077-016] Render context bar in topbar via render hook in app/Providers/Filament/AdminPanelProvider.php
|
||
- [X] T055 [FR-077-016] Add context bar partial view in resources/views/filament/partials/context-bar.blade.php
|
||
- [X] T056 [FR-077-016] Remove implicit tenant auto-selection behavior while preserving deny-as-not-found semantics in app/Support/Middleware/EnsureFilamentTenantSelected.php
|
||
- [X] 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
|