# Implementation Plan: Workspace Hub Navigation Context Contract

**Branch**: `314-workspace-hub-navigation-context-contract` | **Date**: 2026-05-16 | **Spec**: `specs/314-workspace-hub-navigation-context-contract/spec.md`
**Input**: Feature specification from `specs/314-workspace-hub-navigation-context-contract/spec.md`

## Summary

Implement a hard-cutover workspace hub navigation contract so sidebar/global navigation into workspace-scoped hubs always opens workspace-wide. The implementation creates a narrow workspace hub registry, centralizes clean sidebar/global URL generation, bypasses remembered Managed Environment state for workspace hub entry, and neutralizes environment-like persisted table filters where they can override sidebar/global intent.

Spec 313 is the source of truth for the problem evidence and high-risk pages. Spec 315/316/317 remain follow-ups and must not be pulled into this implementation.

## Technical Context

**Language/Version**: PHP 8.4.15, Laravel 12.52, Filament 5.2.1, Livewire 4.1.4
**Primary Dependencies**: Filament admin panel, Livewire, Pest 4.3.1, PostgreSQL through Sail
**Storage**: PostgreSQL; no migration or data model change planned
**Testing**: Pest Feature/Livewire tests plus focused Pest Browser smoke
**Validation Lanes**: confidence, browser, `git diff --check`
**Target Platform**: Laravel monolith in `apps/platform`
**Project Type**: web application
**Performance Goals**: navigation URL generation and registry lookups are static/lightweight; no additional DB queries in sidebar generation beyond existing visibility checks unless required for existing authorization
**Constraints**: no Graph calls, no queued work, no migrations, no legacy compatibility layer, no route alias support for sidebar/global workspace hub entry
**Scale/Scope**: all workspace hubs from Spec 313, with explicit exclusions for Stored Reports environment route and Support Request action-only surface

## UI / Surface Guardrail Plan

- **Guardrail scope**: workflow/context hardening for existing operator-facing workspace hubs.
- **Native vs custom classification summary**: native Filament navigation/pages/resources; no custom UI system.
- **Shared-family relevance**: navigation, shell/context state, table filter state, evidence/report viewers, governance lists.
- **State layers in scope**: shell, URL-query, page table filters, persisted/session filters, Livewire mount state, remembered environment state.
- **Audience modes in scope**: operator-MSP and support-platform only; customer/read-only rendered content is not changed except Customer Review Workspace default scope.
- **Decision/diagnostic/raw hierarchy plan**: no new decision hierarchy; preserve existing pages and make default scope truthful.
- **Raw/support gating plan**: unchanged.
- **One-primary-action / duplicate-truth control**: no action hierarchy change; prevent scope signal duplication by making shell and data scope agree.
- **Handling modes by drift class or surface**: hidden environment filters on workspace hub sidebar/global entry are hard-stop candidates; Environment CTA and full clear-filter drift are documented follow-ups.
- **Repository-signal treatment**: review-mandatory for any new page-specific context handling; prefer registry/helper path.
- **Special surface test profiles**: global-context-shell, monitoring-state-page, exception-coded-surface.
- **Required tests or manual smoke**: focused Feature/Livewire tests plus browser smoke for Spec 313 critical flows.
- **Exception path and spread control**: none for sidebar/global workspace hub entry.
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.

## Shared Pattern & System Fit

- **Cross-cutting feature marker**: yes.
- **Systems touched**:
  - `apps/platform/app/Support/Navigation/WorkspaceSidebarNavigation.php`
  - `apps/platform/app/Providers/Filament/AdminPanelProvider.php`
  - `apps/platform/app/Support/Tenants/TenantPageCategory.php`
  - `apps/platform/app/Support/Navigation/NavigationScope.php`
  - `apps/platform/app/Support/OperateHub/OperateHubShell.php`
  - `apps/platform/app/Support/Workspaces/WorkspaceContext.php`
  - `apps/platform/app/Support/Filament/CanonicalAdminTenantFilterState.php`
  - affected Filament pages/resources from Spec 313
- **Shared abstractions reused**: `TenantPageCategory`, `NavigationScope`, `WorkspaceContext`, `CanonicalAdminTenantFilterState`, existing Filament page/resource URL APIs where safe.
- **New abstraction introduced? why?**: likely `App\Support\Navigation\WorkspaceHubRegistry`, because more than two pages need the same route/page identity and environment-param stripping rule.
- **Why the existing abstraction was sufficient or insufficient**: existing helpers classify route scope or filter state, but no helper owns workspace hub identity, clean URL generation, and persisted environment-like filter neutralization together.
- **Bounded deviation / spread control**: registry may answer only workspace hub identity and entry cleanup rules; it must not become a product IA framework or provider registry.

## OperationRun UX Impact

- **Touches OperationRun start/completion/link UX?**: no.
- **Central contract reused**: `OperationRunLinks::index()` remains the Operations collection link helper; changes may be limited to clean workspace hub navigation.
- **Delegated UX behaviors**: N/A.
- **Surface-owned behavior kept local**: Operations table/filter UI remains local to `Operations`.
- **Queued DB-notification policy**: N/A.
- **Terminal notification path**: N/A.
- **Exception path**: none.

## Provider Boundary & Portability Fit

- **Shared provider/platform boundary touched?**: yes.
- **Provider-owned seams**: ProviderConnection record actions, credentials, health/verification actions remain provider-owned and unchanged.
- **Platform-core seams**: workspace hub entry contract, workspace navigation URLs, shell/environment context, query-filter stripping.
- **Neutral platform terms / contracts preserved**: Workspace, Managed Environment, provider connection, workspace hub.
- **Retained provider-specific semantics and why**: Provider Connections may retain Microsoft-specific provider values where already stored; this spec must not add provider-specific platform navigation truth.
- **Bounded extraction or follow-up path**: document remaining explicit environment CTA/filter behavior for Spec 315; legacy tenant naming cleanup for Spec 317.

## Constitution Check

- Inventory-first: no inventory truth changes.
- Read/write separation: read/navigation only; no mutating behavior added.
- Graph contract path: no Graph calls.
- Deterministic capabilities: existing capability resolvers remain in force.
- RBAC-UX: workspace membership and capability checks remain server-side; non-members remain 404.
- Workspace isolation: workspace remains selected context and workspace-wide queries must enforce workspace membership.
- Tenant isolation: tenant-owned rows in workspace hubs must be limited to entitled Managed Environments.
- Run observability: no long-running, remote, queued, or scheduled work.
- Automation: N/A.
- Data minimization: no new sensitive data storage.
- Test governance: Feature/Livewire + browser lanes are explicit and bounded.
- Proportionality: new registry is justified by current Spec 313 evidence and more than two concrete surfaces.
- No premature abstraction: registry is allowed because navigation/scope correctness affects isolation and there are many concrete surfaces.
- Persisted truth: no persisted truth added.
- Behavioral state: no new status/state family.
- UI semantics: no badge/status taxonomy.
- Shared pattern first: registry attaches to existing navigation/shell/filter helpers.
- Provider boundary: hardens platform-core navigation and removes provider-adjacent hidden environment inference.
- V1 explicitness / few layers: direct registry + helper updates, no framework.
- Spec discipline / bloat check: proportionality review is in `spec.md`.
- Filament-native UI: existing native Filament pages/resources remain; no styling changes.

## Test Governance Check

- **Test purpose / classification by changed surface**:
  - Unit/Feature: registry contents and URL cleanup helpers.
  - Feature/Livewire: shell/data/filter state for workspace hubs.
  - Browser: critical Spec 313 flows across navigation/reload/back-forward.
- **Affected validation lanes**: confidence and browser.
- **Why this lane mix is narrowest sufficient proof**: helper behavior is deterministic; Livewire proves table state; browser catches hydration/session/back-forward drift found by Spec 313.
- **Narrowest proving commands**:
  - `cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHub`
  - `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec314WorkspaceHubNavigationContextSmoke`
  - `git diff --check`
- **Fixture / helper / factory / seed / context cost risks**: tests need explicit workspaces, two Managed Environments, user membership/capability setup, and seeded rows for Provider Connections/Operations/Decision/Register pages where proving row scope.
- **Expensive defaults or shared helper growth introduced?**: no implicit global fixture widening; any new setup helper must be explicit and local to Spec 314 tests unless already reusable.
- **Heavy-family additions, promotions, or visibility changes**: one explicit browser smoke only.
- **Surface-class relief / special coverage rule**: no visual/styling test; global-context-shell and monitoring-state-page state coverage required.
- **Closing validation and reviewer handoff**: reviewer checks no broad rebaseline, no unbounded browser family, no hidden helper default expansion.
- **Budget / baseline / trend follow-up**: none expected.
- **Review-stop questions**: lane fit, hidden stale environment state, workspace entitlement leakage, compatibility shims.
- **Escalation path**: document-in-feature.
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
- **Why no dedicated follow-up spec is needed**: sidebar/global workspace hub contract is the dedicated slice; CTA, clear-filter, legacy cleanup, and durable browser guards already have follow-up specs 315-318.

## Project Structure

### Documentation (this feature)

```text
specs/314-workspace-hub-navigation-context-contract/
|-- spec.md
|-- plan.md
|-- tasks.md
`-- checklists/
    `-- requirements.md
```

### Source Code (repository root)

Likely runtime surfaces for later implementation:

```text
apps/platform/app/
|-- Providers/Filament/AdminPanelProvider.php
|-- Support/
|   |-- Navigation/WorkspaceHubRegistry.php
|   |-- Navigation/WorkspaceSidebarNavigation.php
|   |-- Navigation/NavigationScope.php
|   |-- Tenants/TenantPageCategory.php
|   |-- OperateHub/OperateHubShell.php
|   |-- Workspaces/WorkspaceContext.php
|   |-- Filament/CanonicalAdminTenantFilterState.php
|   |-- ManagedEnvironmentLinks.php
|   `-- OperationRunLinks.php
|-- Filament/
|   |-- Resources/ProviderConnectionResource.php
|   `-- Pages/
|       |-- Monitoring/Operations.php
|       |-- Monitoring/FindingExceptionsQueue.php
|       |-- Monitoring/EvidenceOverview.php
|       |-- Governance/GovernanceInbox.php
|       |-- Governance/DecisionRegister.php
|       `-- Reviews/CustomerReviewWorkspace.php
`-- Http/Controllers/
    |-- ClearEnvironmentContextController.php
    `-- OpenFindingExceptionsQueueController.php
```

Likely tests for later implementation:

```text
apps/platform/tests/
|-- Feature/Navigation/
|   |-- WorkspaceHubRegistryTest.php
|   `-- WorkspaceHubSidebarUrlContractTest.php
|-- Feature/Workspaces/
|   `-- WorkspaceHubContextContractTest.php
|-- Feature/ProviderConnections/
|   `-- ProviderConnectionsWorkspaceHubContractTest.php
|-- Feature/Monitoring/
|   |-- FindingExceptionsQueueWorkspaceHubContractTest.php
|   |-- OperationsWorkspaceHubContractTest.php
|   `-- EvidenceOverviewWorkspaceHubContractTest.php
|-- Feature/Governance/
|   `-- DecisionRegisterWorkspaceHubContractTest.php
|-- Feature/Reviews/
|   `-- CustomerReviewWorkspaceHubContractTest.php
`-- Browser/
    `-- Spec314WorkspaceHubNavigationContextSmokeTest.php
```

**Structure Decision**: Laravel monolith under `apps/platform`; add one support class under `App\Support\Navigation` if implementation confirms no existing support class can own the contract cleanly.

## Complexity Tracking

| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| New registry/support contract | Workspace hub identity and cleanup rules cross many pages and URL helpers | Page-by-page patches would preserve the fragmentation Spec 313 identified |

## Proportionality Review

- **Current operator problem**: stale environment context can silently filter workspace hubs reached from sidebar/global navigation.
- **Existing structure is insufficient because**: `TenantPageCategory`, `NavigationScope`, `WorkspaceSidebarNavigation`, `OperateHubShell`, page URL builders, and table filter helpers each own partial behavior.
- **Narrowest correct implementation**: one registry that lists workspace hubs and forbidden environment query/filter keys, then use it in central navigation and shared filter cleanup.
- **Ownership cost created**: maintain registry when workspace hubs are added/reclassified; keep contract tests updated.
- **Alternative intentionally rejected**: page-local query stripping, because Provider Connections, Operations, Finding Exceptions, Reviews, Evidence, Governance, Audit, and Alerts need the same rule.
- **Release truth**: current-release truth from Spec 313 browser evidence.

## Technical Approach

1. Add or formalize `WorkspaceHubRegistry`.
   - Registry answers whether a route/page is a workspace hub.
   - Registry exposes the forbidden sidebar/global environment query keys.
   - Registry exposes environment-like persisted filter keys to neutralize.
   - Registry includes all in-scope Spec 313 workspace hubs and explicit exclusions in tests/docs.

2. Centralize clean workspace hub sidebar/global URL generation.
   - Update `WorkspaceSidebarNavigation` and `AdminPanelProvider` navigation items to use clean URL generation.
   - Bypass resource/page `getUrl()` behavior if it injects remembered environment state.
   - Ensure `OperationRunLinks::index()` is called for workspace-wide Operations without environment params.

3. Stop remembered environment from becoming workspace hub default scope.
   - Review `OperateHubShell`, `TenantPageCategory`, `NavigationScope`, `WorkspaceContext`, and Provider Connection tenant inference.
   - Keep remembered environment usable only for switcher convenience.

4. Neutralize persisted environment-like filters on sidebar/global workspace hub entry.
   - Extend or wrap `CanonicalAdminTenantFilterState` rather than adding one-off page patches where possible.
   - Apply targeted page fixes only where current Livewire/table lifecycle makes a shared helper insufficient.

5. Fix critical offenders.
   - Provider Connections: no sidebar/global `managed_environment_id`; workspace-wide default query.
   - Finding Exceptions Queue: no sidebar/global `tenant`; no stale persisted environment filter.
   - Operations: no sidebar/global `managed_environment_id`, `tenant_scope`, or table filter mismatch.
   - Decision Register: clean workspace URL opens for authorized users without environment filter.
   - Customer Reviews/Reviews/Evidence/Governance/Audit/Alerts: sidebar/global entry is workspace-wide and safe.

6. Browser verify focused Spec 313 flows.

## Existing Repository Surfaces

Spec 313 code ownership map and current code inspection identify these hotspots:

- `WorkspaceSidebarNavigation::build()` emits many workspace hub URLs through page/resource helpers.
- `AdminPanelProvider::navigationItems()` duplicates several workspace hub navigation entries.
- `ProviderConnectionResource::getUrl()` currently can add `managed_environment_id` from scoped/remembered context.
- `ProviderConnectionResource::resolveContextTenantExternalId()` can use `WorkspaceContext::lastTenantId()`.
- `ManagedEnvironmentLinks::providerConnectionsUrl()` adds `managed_environment_id` from an environment.
- `OperationRunLinks::index()` adds `managed_environment_id`, `tenant_scope`, `activeTab`, `problemClass`, and nested `tableFilters`.
- `FindingExceptionsQueue` has `tenant` query state and a clear action that only removes table state.
- `OpenFindingExceptionsQueueController` redirects with `tenant=<external id>`.
- `CustomerReviewWorkspace` accepts `tenant` or `managed_environment_id`, converts it to a table filter, and clear only removes table filters.
- `EvidenceOverview` is a reference pattern because clear redirects to a clean URL and resets persisted search/filter state.
- `GovernanceInbox` and `DecisionRegister` accept environment query filters and use clean links for clear actions.
- `DecisionRegister::canAccess()` and `ensureRegisterIsVisible()` are currently data/query dependent and can reject clean workspace entry.
- `CanonicalAdminTenantFilterState::sync()` can persist or forget tenant-sensitive filters based on active shell tenant.

## Domain / Model Implications

- No model changes.
- No persisted entity changes.
- No migration.
- No seed data change.
- Workspace hub registry is code-level contract only.

## UI / Filament Implications

- Existing Filament pages/resources stay native.
- No page redesign.
- No new panels.
- Admin panel path remains `/admin`.
- Panel provider registration remains in `apps/platform/bootstrap/providers.php`.
- Global search behavior is unchanged; do not enable global search for Provider Connections or other sensitive resources.
- Destructive actions are not added or changed.
- No new assets expected.

## Livewire Implications

- Livewire page `mount()` and table hydration order matter for persisted filters.
- Tests must cover session-persisted table filters and `tableDeferredFilters` where pages use them.
- Livewire v4.1.4 APIs only.
- Avoid adding broad Livewire state machinery; use focused page/helper changes.

## RBAC / Policy Implications

- Preserve existing workspace membership and capability checks.
- Workspace-wide data scope must still apply Managed Environment access entitlement.
- Do not use hidden environment filters as authorization.
- Decision Register must distinguish workspace authorization from empty workspace state.
- Provider Connections credential-adjacent actions remain protected by existing policies/capabilities.

## Audit / Logging / Evidence Implications

- No new audit logging required for navigation/read behavior.
- Existing audit logs for mutating actions must remain unchanged.
- Browser verification screenshots may be stored under `specs/314-workspace-hub-navigation-context-contract/artifacts/screenshots/` if useful.

## Data / Migration Implications

- No migrations.
- No seeders.
- No backfills.
- No compatibility fields.
- No data cleanup.

## Implementation Phases

1. **Contract and tests first**
   - Create registry contract tests for workspace hub entries and forbidden query params.
   - Add sidebar/global URL tests covering the full registry.
   - Add remembered-environment and persisted-filter regression tests for critical hubs.

2. **Registry and clean URL generation**
   - Implement `WorkspaceHubRegistry`.
   - Update `WorkspaceSidebarNavigation` and `AdminPanelProvider` to use registry-backed clean URL generation.
   - Bypass page/resource `getUrl()` methods only when they inject environment scope.

3. **Shell and remembered environment isolation**
   - Adjust shell/context resolution so workspace hubs from sidebar/global entry are tenantless.
   - Ensure remembered environment is only switcher convenience for workspace hubs.

4. **Persisted filter safety**
   - Extend shared helper for environment-like filter neutralization.
   - Apply critical page integrations for Provider Connections, Finding Exceptions Queue, Operations, Customer Reviews, Reviews, Evidence, Governance Inbox, Decision Register, Audit Log, and Alerts.

5. **Critical page fixes**
   - Fix Provider Connections, Finding Exceptions Queue, Operations, Decision Register, Customer Review Workspace, Reviews, Evidence Overview.

6. **Validation and browser verification**
   - Run focused tests.
   - Run focused browser smoke flows from Spec 313.
   - Record remaining follow-ups for 315/316/317.

## Test Strategy

Required tests:

- `it_workspace_hub_sidebar_urls_do_not_include_environment_query_params`
- `it_sidebar_from_environment_dashboard_opens_workspace_hubs_without_environment_context`
- `it_remembered_environment_does_not_affect_workspace_hub_sidebar_urls`
- `it_provider_connections_sidebar_entry_is_workspace_wide`
- `it_finding_exceptions_queue_sidebar_entry_is_workspace_wide`
- `it_operations_sidebar_entry_does_not_carry_managed_environment_filter`
- `it_decision_register_clean_workspace_url_opens_for_authorized_workspace_user`
- `it_persisted_environment_table_filters_do_not_override_workspace_hub_sidebar_intent`

Recommended exact lanes:

```bash
cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHub
cd apps/platform && ./vendor/bin/sail artisan test --filter=ProviderConnectionsWorkspaceHub
cd apps/platform && ./vendor/bin/sail artisan test --filter=FindingExceptionsQueueWorkspaceHub
cd apps/platform && ./vendor/bin/sail artisan test --filter=OperationsWorkspaceHub
cd apps/platform && ./vendor/bin/sail artisan test --filter=DecisionRegisterWorkspaceHub
cd apps/platform && ./vendor/bin/sail artisan test --filter=CustomerReviewWorkspaceHub
cd apps/platform && ./vendor/bin/sail artisan test --filter=EvidenceOverviewWorkspaceHub
cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec314WorkspaceHubNavigationContextSmoke
git diff --check
```

## Browser Verification Plan

Required pages:

- Provider Connections
- Finding Exceptions Queue
- Operations
- Decision Register
- Customer Reviews
- Evidence
- Reviews
- Governance Inbox

Required flows:

- Environment Dashboard -> Sidebar -> Page
- Workspace Overview -> Sidebar -> Page
- Reload after sidebar entry
- Back/forward for Provider Connections, Customer Reviews, Finding Exceptions Queue, Operations, and Decision Register

Verify:

- shell context
- URL query params
- visible filters
- table filters
- row scope where seeded data proves it

Screenshots may be saved under:

```text
specs/314-workspace-hub-navigation-context-contract/artifacts/screenshots/
```

## Rollout Considerations

- Hard cutover only; no compatibility layer.
- No env vars.
- No migrations.
- No queues or scheduler changes.
- No storage/volume changes.
- Staging validation should run focused tests and browser smoke before production promotion once production exists.

## Risk Controls

- Add registry contract tests so future workspace hubs cannot leak environment query params silently.
- Keep Environment CTA filters out of this spec except where they block sidebar/global distinction.
- Preserve environment-owned route behavior.
- Keep Provider Connections action authorization untouched.
- Record any remaining URL/filter drift as 315/316/317 follow-up, not hidden implementation scope.

## Spec Preparation Notes

- Candidate was directly supplied by the user and is supported by Spec 313.
- `docs/product/spec-candidates.md` currently says no safe automatic next-best-prep target remains, but this is an explicit manual promotion from completed Spec 313 audit evidence.
- Existing Specs 311, 312, and 313 are completed/historical context and are not modified by this preparation.
- The repository provides Bash helpers for feature creation and plan setup, but no local `tasks` or `analyze` command was found. Preparation analysis is performed by checklist and consistency checks in this package.
