## Summary
Fixes the sidebar context bug where navigating to the **Required Permissions** page (`/admin/tenants/{id}/required-permissions`) would switch the sidebar from workspace navigation to tenant-scoped navigation, confusing users.
## Problem
The `EnsureFilamentTenantSelected` middleware detected a tenant ID in the URL and called `setTenant()`, which switched the entire sidebar to tenant-scoped navigation. The Required Permissions page is logically a **workspace-level** page that happens to reference a tenant — it should keep showing workspace nav.
## Changes
### Middleware (`EnsureFilamentTenantSelected.php`)
- **`isWorkspaceScopedPageWithTenant()`** — new private helper that detects workspace-scoped pages containing a tenant parameter via regex
- **Livewire referer bypass** — checks if a Livewire request originates from a workspace-scoped page and preserves workspace nav
- **`setTenant()` bypass** — skips tenant activation and `rememberLastTenantId()` for workspace-scoped pages
### Tests
- **`RequiredPermissionsSidebarTest.php`** (NEW) — 7 tests covering:
- Workspace nav visible on required-permissions page
- Tenant nav absent on required-permissions page
- Direct URL access preserves workspace nav
- 404 for non-member tenants
- 404 for tenants without entitlement
- Tenant pages still show tenant sidebar (regression guard)
- Scoped tenant resolves correctly on tenant pages
### Pre-existing test fixes
- **`RequiredPermissionsEmptyStateTest`** — fixed URL assertion (dynamic `TenantResource::getUrl()` instead of hardcoded `/admin/onboarding`)
- **`RequiredPermissionsLinksTest`** — fixed URL assertion + multiline HTML `data-testid` assertion
- **`RequiredPermissionsFiltersTest`** — fixed `entra_permissions` config leak from branch 105
## Test Results
| Suite | Result |
|-------|--------|
| RequiredPermissions (26 tests) | **26 pass** (73 assertions) |
| Full regression (1571 tests) | **1562 pass**, 2 fail (pre-existing OpsUx), 7 skipped |
The 2 failures are pre-existing in `OpsUx/OperationCatalogCoverageTest` and `OpsUx/OperationSummaryKeysSpecTest` — unrelated to this feature.
## Spec Artifacts
- `specs/106-required-permissions-sidebar-context/plan.md`
- `specs/106-required-permissions-sidebar-context/tasks.md`
- `specs/106-required-permissions-sidebar-context/research.md`
- `specs/106-required-permissions-sidebar-context/data-model.md`
- `specs/106-required-permissions-sidebar-context/quickstart.md`
Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #129
8.8 KiB
Tasks: Required Permissions Sidebar Context Fix
Input: Design documents from /specs/106-required-permissions-sidebar-context/
Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, quickstart.md
Tests: This feature changes runtime behavior (middleware navigation logic), so tests are REQUIRED (Pest). Operations: N/A — no long-running/remote/queued/scheduled work. RBAC: No authorization changes. All 8 existing authorization checks are preserved. Only sidebar rendering is affected. Filament UI Action Surfaces: Exemption — no Filament Resource/Page/RelationManager created or modified. Filament UI UX-001: Exemption — no new screens, no layout changes. Badges: N/A — no badge changes.
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)
- Include exact file paths in descriptions
Phase 1: Setup
Purpose: No project initialization needed — this is a fix in an existing codebase. Phase is empty.
(No tasks — feature modifies existing files only.)
Phase 2: Foundational (Blocking Prerequisites)
Purpose: No foundational infrastructure changes needed. The middleware, test helpers, and page classes already exist.
(No tasks — all prerequisites are already in place.)
Checkpoint: Foundation ready — user story implementation can begin immediately.
Phase 3: User Story 1 — Consistent Workspace Sidebar on Required Permissions (Priority: P1) MVP
Goal: When navigating to /admin/tenants/{tenant}/required-permissions, the sidebar always shows workspace-level navigation instead of tenant-scoped navigation (Inventory, Backups & Restore, Directory, Governance, Findings). Note: Actual workspace nav item labels MUST be derived from configureNavigationForRequest() at implementation time — do not hardcode assumed names.
Independent Test: Navigate to /admin/tenants/{tenant}/required-permissions while a tenant context is active in the session. Verify workspace navigation items are present and tenant-scoped items are absent. Verify Livewire filter updates preserve workspace sidebar.
Tests for User Story 1
- T001 [US1] Create sidebar context test file at tests/Feature/RequiredPermissions/RequiredPermissionsSidebarTest.php with test cases: (a) page shows workspace nav items — derive actual item labels from
configureNavigationForRequest()output at implementation time (do NOT hardcode assumed labels from the spec), (b) page does not show tenant nav items (Inventory, Backups), (c) direct URL navigation shows workspace sidebar, (d) Livewire filter updates preserve workspace sidebar context, (e) non-member access still returns 404 after middleware change (explicit FR-002 regression guard) - T002 [US1] Add regression test in tests/Feature/RequiredPermissions/RequiredPermissionsSidebarTest.php asserting that tenant-scoped pages (e.g., a page under
/admin/t/{tenant}/) still show tenant sidebar — no regression
Implementation for User Story 1
- T003 [US1] Add
isWorkspaceScopedPageWithTenant()private helper method to app/Support/Middleware/EnsureFilamentTenantSelected.php — regex match for/admin/tenants/{tenant}/required-permissions - T004 [US1] Add Livewire
/livewire/updatereferer check for Required Permissions page in app/Support/Middleware/EnsureFilamentTenantSelected.php — add regex match in the existing/livewire/updateblock (after operations check, before the block returns) - T005 [US1] Add workspace-scoped page bypass in the
$tenantParameter !== nullblock of app/Support/Middleware/EnsureFilamentTenantSelected.php — after all 8 authorization checks pass but beforeFilament::setTenant($tenant, true), callisWorkspaceScopedPageWithTenant($path)and return early withconfigureNavigationForRequest()(skipsetTenantandrememberLastTenantId) - T006 [US1] Run tests:
vendor/bin/sail artisan test --compact tests/Feature/RequiredPermissions/— verify all new sidebar tests pass AND all existing Required Permissions tests still pass (no regression)
Checkpoint: User Story 1 complete — Required Permissions page always shows workspace sidebar. All existing functionality preserved.
Phase 4: User Story 2 — Context Bar Reflects Tenant Scope (Priority: P2)
Goal: The context bar (top bar) correctly shows the tenant name for orientation while the sidebar displays workspace navigation.
Independent Test: Navigate to Required Permissions for a specific tenant. Verify the page heading or context area displays the tenant name. Verify sidebar shows workspace navigation.
Implementation for User Story 2
- T007 [US2] Verify context bar behavior in tests/Feature/RequiredPermissions/RequiredPermissionsSidebarTest.php — add assertion that the page response contains the tenant display name. Note: The page resolves
$scopedTenantfrom the route param viaresolveScopedTenant()(NOT fromFilament::getTenant()), so the tenant name is available even thoughFilament::setTenant()is skipped. Verify the heading renders the tenant'sdisplay_name.
Checkpoint: User Story 2 complete — tenant name visible in page context while sidebar remains workspace-scoped.
Phase 5: Polish & Cross-Cutting Concerns
Purpose: Code quality, formatting, and final validation.
- T008 Run
vendor/bin/sail bin pint --dirty --format agentto ensure code style compliance on app/Support/Middleware/EnsureFilamentTenantSelected.php - T009 Run full Required Permissions test suite:
vendor/bin/sail artisan test --compact tests/Feature/RequiredPermissions/— final regression check - T010 Run quickstart.md validation: verify all steps described in specs/106-required-permissions-sidebar-context/quickstart.md are implemented
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1): Empty — no setup needed
- Foundational (Phase 2): Empty — no foundational work needed
- User Story 1 (Phase 3): Can start immediately — core fix
- User Story 2 (Phase 4): Can start after US1 (depends on sidebar fix being in place to verify both sidebar + context bar)
- Polish (Phase 5): Depends on US1 + US2 completion
User Story Dependencies
- User Story 1 (P1): No dependencies — can start immediately. This IS the MVP.
- User Story 2 (P2): Soft dependency on US1 (needs the sidebar fix to verify context bar works alongside workspace sidebar). Can technically be verified independently since the page already renders tenant name.
Within Each User Story
- Tests (T001, T002) can be written in parallel with each other
- Implementation tasks (T003, T004, T005) are sequential — each builds on the previous
- T006 (test run) depends on T001–T005 all being complete
Parallel Opportunities
- T001 and T002 can run in parallel (different test cases, same new file)
- T003, T004, T005 modify the same file sequentially — no parallelism
- T007 (US2) can start after T005 is complete
Parallel Example: User Story 1
# Write both test groups in parallel:
Task T001: "Create sidebar context tests in tests/Feature/RequiredPermissions/RequiredPermissionsSidebarTest.php"
Task T002: "Add regression test for tenant-scoped pages in tests/Feature/RequiredPermissions/RequiredPermissionsSidebarTest.php"
# Then implement sequentially (same file):
Task T003: "Add isWorkspaceScopedPageWithTenant() helper"
Task T004: "Add Livewire referer check"
Task T005: "Add workspace-scoped page bypass in tenant param block"
# Then validate:
Task T006: "Run all Required Permissions tests"
Implementation Strategy
MVP First (User Story 1 Only)
- Skip Phase 1 + Phase 2 (empty)
- Complete Phase 3: User Story 1 (T001–T006)
- STOP and VALIDATE: All Required Permissions tests pass, sidebar shows workspace nav
- This is a shippable fix.
Incremental Delivery
- User Story 1 (T001–T006): Sidebar fix → Test → Ship (MVP!)
- User Story 2 (T007): Context bar verification → Test → Ship
- Polish (T008–T010): Code style + final validation
Notes
- Total tasks: 10
- Tasks per user story: US1 = 6, US2 = 1, Polish = 3
- Parallel opportunities: T001 + T002 (test writing)
- All middleware changes are in a single file:
app/Support/Middleware/EnsureFilamentTenantSelected.php - All new tests are in a single file:
tests/Feature/RequiredPermissions/RequiredPermissionsSidebarTest.php - Suggested MVP scope: User Story 1 only (T001–T006) — this fully resolves the sidebar bug
- Format validation: All tasks follow
- [ ] [TaskID] [P?] [Story?] Description with file pathformat