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
4.7 KiB
4.7 KiB
Research — Workspace-first Navigation & Monitoring Hub (077)
Date: 2026-02-06
Branch: 077-workspace-nav-monitoring-hub
Spec: specs/077-workspace-nav-monitoring-hub/spec.md
Repo Reality Check (what exists today)
- Admin panel exists at
/adminvia app/Providers/Filament/AdminPanelProvider.php. - System panel exists at
/systemwith a separate auth guard (platform) via app/Providers/Filament/SystemPanelProvider.php. - Workspace context selection exists:
- Page
/admin/choose-workspacevia app/Filament/Pages/ChooseWorkspace.php - POST switch endpoint
/admin/switch-workspacevia routes/web.php - Workspace switcher UI in the user menu via resources/views/filament/partials/workspace-switcher.blade.php
- Page
- Navigation ambiguity is currently real:
- When no tenant is selected, navigation is replaced with a single item labeled "Workspaces" linking to the choose-workspace page via app/Support/Middleware/EnsureFilamentTenantSelected.php.
- Separately, the sidebar includes another "Workspaces" item linking to
/admin/workspaces(workspace CRUD) via app/Providers/Filament/AdminPanelProvider.php.
- Operations is already canonical and tenantless:
- Resource slug is
/admin/operationsvia app/Filament/Resources/OperationRunResource.php. - Detail page is
/admin/operations/{record}.
- Resource slug is
Decisions (resolved)
D1 — Manage workspaces stays on /admin/workspaces and follows workspace RBAC semantics (404 for non-members, 403 for missing capability)
- Decision: Treat
/admin/workspacesas a workspace-scoped management surface in the tenant plane (/admin, Entra users):- Non-members (or out-of-scope workspace records) → 404 (deny-as-not-found)
- Members missing required capabilities for protected actions/screens → 403
- Rationale: Aligns with the constitution RBAC-UX model (membership is the isolation boundary; capability denial is 403 after membership is established) while still preventing cross-workspace leakage.
- Alternatives considered:
- Move management into
/systempanel: rejected because this feature targets the tenant plane IA. (If workspace CRUD becomes platform-admin only later, that should be handled as a separate migration spec.)
- Move management into
D2 — Tenant context influences Operations via server-side default filter state, not querystring
- Decision: Apply the tenant default filter server-side while keeping the canonical URL
/admin/operationsunchanged. - Rationale: Matches Spec 077 clarification (Q2=A). Prevents link-sharing surprises and keeps canonical monitoring routes stable.
- Alternatives considered:
- Querystring-based default filtering (e.g.
?tenant_id=): rejected as it makes filtered URLs the de-facto navigation target.
- Querystring-based default filtering (e.g.
D3 — Missing workspace context redirects to /admin/choose-workspace and returns to the requested URL
- Decision: When a workspace-scoped page is visited without an active workspace selection, redirect to
/admin/choose-workspaceand then return. - Rationale: Matches Spec 077 clarification (Q3=A) and aligns with existing
/adminroot override behavior in routes/web.php.
D4 — Invalid tenant context (tenant not in current workspace) is auto-cleared
- Decision: If tenant context is active but does not belong to the current workspace, clear tenant context and continue on workspace-level pages.
- Rationale: Matches Spec 077 clarification (Q4=A). Reduces “ghost tenant” behavior after a workspace switch.
- Alternatives considered:
- Hard 404: rejected as too confusing during normal context switching.
Key Implementation Implications (for planning)
- Rename navigation labels to satisfy “one label, one meaning”:
- The “Workspaces” navigation item that points to the choose-workspace page must become "Switch workspace".
- The “Workspaces” navigation item that points to CRUD must become "Manage workspaces" and be capability-gated with workspace RBAC semantics (404 for non-members; 403 for missing capability).
- Operations filter chip/removal: current behavior filters by
Tenant::current()insideOperationRunResource::getEloquentQuery(), which is not user-removable. The plan should move this behavior into a table filter with default state. - No render-time external calls: monitoring pages must remain DB-only at render (already consistent with constitution).