# Feature Specification: Workspace Hub Navigation Context Contract **Feature Branch**: `314-workspace-hub-navigation-context-contract` **Created**: 2026-05-16 **Status**: Draft **Input**: User-supplied Spec 314 draft plus Spec 313 audit results. **Runtime posture**: Hard cutover. No backwards compatibility layer. No legacy query alias support for sidebar/global workspace hub entry. ## Spec Candidate Check *(mandatory - SPEC-GATE-001)* - **Problem**: Workspace-scoped admin hubs can inherit stale Managed Environment context from shell state, remembered environment state, query params, Filament tenant state, Livewire table state, and persisted filters. - **Today's failure**: Spec 313 browser evidence shows operators can see "No environment selected" or "All environments" while rows remain environment-filtered. Provider Connections, Finding Exceptions Queue, Customer Review Workspace, Operations, Review Register, Governance Inbox, and Decision Register are the highest-risk surfaces. - **User-visible improvement**: Sidebar/global navigation into workspace hubs becomes deterministic: selected Workspace remains active, active Managed Environment context is cleared, URLs are clean, and rows are workspace-wide by default. - **Smallest enterprise-capable version**: One canonical workspace hub contract used by sidebar/global navigation and the affected workspace hub pages to strip environment query state and neutralize environment-like persisted filters on workspace hub entry. - **Explicit non-goals**: No Environment Dashboard CTA contract, no universal clear-filter contract, no product IA redesign, no route alias compatibility, no data migration, no seed/backfill work, no broad environment-page conversion. - **Permanent complexity imported**: A narrow workspace hub registry/contract and focused Pest/Livewire/Browser coverage. No new persisted tables, models, enums, status families, OperationRun types, or asset bundles. - **Why now**: Spec 313 completed browser verification and explicitly recommends Spec 314 first because sidebar/global workspace hub entry must be safe before Environment CTA filters and clear-filter semantics are standardized. - **Why not local**: Page-by-page URL fixes would keep context ownership fragmented. The failure crosses navigation generation, shell resolution, query parameters, resource `getUrl()` overrides, and persisted Filament table filters. - **Approval class**: Core Enterprise. - **Red flags triggered**: New registry abstraction; provider-adjacent Provider Connections scope; broad surface count. Defense: the abstraction is narrow, current-release, and required for workspace isolation and navigation safety across more than two concrete surfaces. - **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12** - **Decision**: approve. ## Spec Scope Fields *(mandatory)* - **Scope**: canonical-view. - **Primary routes**: - `/admin` - `/admin/workspaces/{workspace}/overview` - `/admin/workspaces/{workspace}/operations` - `/admin/provider-connections` - `/admin/finding-exceptions/queue` - `/admin/evidence/overview` - `/admin/reviews` - `/admin/reviews/workspace` - `/admin/governance/inbox` - `/admin/governance/decisions` - `/admin/audit-log` - `/admin/alerts` - `/admin/alerts/alert-deliveries` - `/admin/alerts/alert-rules` - `/admin/alerts/alert-destinations` - `/admin/settings/workspace` - `/admin/workspaces` - `/admin/workspaces/{workspace}/environments` - **Data ownership**: No ownership model changes. Workspace-owned and tenant-owned records keep existing ownership. Workspace hub views must enforce workspace membership and managed-environment entitlement before revealing tenant-owned rows. - **RBAC**: Workspace membership remains required. Existing capability checks remain in force. Non-member workspace/environment access remains deny-as-not-found. Member-but-missing-capability remains 403 where the current policy/capability contract uses 403. For canonical-view specs: - **Default filter behavior when tenant-context is active**: Sidebar/global workspace hub entry ignores active or remembered Managed Environment context and opens workspace-wide. Explicit Environment CTA filtering remains allowed only where already present and is standardized later in Spec 315. - **Explicit entitlement checks preventing cross-tenant leakage**: Workspace-wide data queries must include current workspace scope and must limit environment-bound rows to the Managed Environments the actor is entitled to access. ## Summary Implement the canonical Workspace Hub Navigation Context Contract for TenantPilot. Workspace-scoped hubs must open workspace-wide when reached through sidebar/global navigation. They must not inherit Managed Environment context through route/query params, Filament tenant state, remembered environment state, Livewire mounted state, persisted Filament table filters, or page-specific URL builders. Canonical behavior: ```text Sidebar / global navigation -> workspace-scoped hub -> workspace-wide state ``` Environment-specific filtering from Environment Dashboard CTAs is not productized in this spec. It belongs to Spec 315. ## Product Context TenantPilot is workspace-first. Workspace is the primary operating context. Managed Environment is a secondary operational context inside a Workspace. Workspace hubs are portfolio/workspace surfaces. They may display tenant-owned rows, but their entry point is workspace-wide and entitlement-filtered, not environment-owned. Environment pages remain environment-owned and are not converted by this spec. ## Cross-Cutting / Shared Pattern Reuse *(mandatory)* - **Cross-cutting feature?**: yes. - **Interaction class(es)**: navigation, shell/context state, table filter state, canonical links. - **Systems touched**: `WorkspaceSidebarNavigation`, `AdminPanelProvider`, `TenantPageCategory`, `NavigationScope`, `OperateHubShell`, `WorkspaceContext`, `CanonicalAdminTenantFilterState`, page/resource URL builders, and high-risk Filament pages/resources from Spec 313. - **Existing pattern(s) to extend**: existing workspace navigation builder, `TenantPageCategory::WorkspaceWideSurface`, `NavigationScope`, `WorkspaceContext`, and `CanonicalAdminTenantFilterState`. - **Shared contract / presenter / builder / renderer to reuse**: reuse existing navigation and shell/context helpers where safe; introduce one narrow `WorkspaceHubRegistry` only for workspace hub identity and environment-param/filter neutralization rules. - **Why the existing shared path is sufficient or insufficient**: existing paths know pieces of the contract but no single path answers whether a page is a workspace hub, whether environment params must be stripped, and whether environment-like persisted filters must be ignored on sidebar/global entry. - **Allowed deviation and why**: introduce a narrow registry because more than two concrete workspace hubs need the same decision and because isolation/navigation correctness is security-relevant current-release truth. - **Consistency impact**: all sidebar/global workspace hub URLs must use the same forbidden query-param list and the same remembered-environment bypass behavior. - **Review focus**: verify no page-specific `getUrl()` override or helper can inject environment params into sidebar/global workspace hub URLs. ## OperationRun UX Impact *(mandatory)* - **Touches OperationRun start/completion/link UX?**: no OperationRun start, completion, queuing, dedupe, status, outcome, terminal notification, or run lifecycle semantics are changed. - **Shared OperationRun UX contract/layer reused**: `OperationRunLinks::index()` may be adjusted only for clean workspace hub navigation; OperationRun start UX is not in scope. - **Delegated start/completion UX behaviors**: N/A. - **Local surface-owned behavior that remains**: existing Operations list and operation detail behavior remain. - **Queued DB-notification policy**: N/A. - **Terminal notification path**: N/A. - **Exception required?**: none. ## Provider Boundary / Platform Core Check *(mandatory)* - **Shared provider/platform boundary touched?**: yes, Provider Connections and provider-adjacent links are in scope. - **Boundary classification**: mixed. Provider Connections records are provider-adjacent, but the navigation context contract is platform-core. - **Seams affected**: Provider Connection list URL generation, provider connection environment prefilter behavior, `managed_environment_id` query semantics, remembered environment fallback. - **Neutral platform terms preserved or introduced**: Workspace, Managed Environment, provider connection, workspace hub. - **Provider-specific semantics retained and why**: Microsoft-specific provider details remain inside existing provider connection records/actions. This spec must not introduce Microsoft-shaped platform navigation truth. - **Why this does not deepen provider coupling accidentally**: the contract removes hidden environment/provider-specific query inference from workspace hub navigation instead of adding a provider framework. - **Follow-up path**: Spec 315 standardizes explicit Environment CTA filtering; Spec 317 removes remaining legacy tenant/environment naming and alias drift. ## UI / Surface Guardrail Impact *(mandatory)* | Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note | |---|---|---|---|---|---|---| | Workspace hub sidebar/global entry | yes | Native Filament navigation + existing shell | navigation / shell / table filters | shell, URL-query, page, session filters | no | State-contract hardening only; no redesign. | | Provider Connections / Integrations | yes | Native Filament Resource | navigation / provider connection list | URL-query, table query, remembered env | no | Must open workspace-wide from sidebar/global entry. | | Finding Exceptions Queue | yes | Native Filament Page | navigation / queue | URL-query, table filters, session filters | no | Sidebar/global entry must not use `tenant`. | | Operations | yes | Native Filament Page | monitoring state page | URL-query, table filters, shell | no | Sidebar/global entry must not carry `managed_environment_id`. | | Decision Register / Governance Inbox | yes | Native Filament Pages | governance navigation | URL-query, access check, filters | no | Clean workspace Decision Register URL must open for authorized users. | | Customer Reviews / Reviews / Evidence | yes | Native Filament Pages | reporting / evidence viewers | URL-query, table filters, session filters | no | Sidebar/global entry must neutralize stale environment filters. | ## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)* | Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction | |---|---|---|---|---|---|---|---| | Workspace hub sidebar/global navigation | Secondary Context | Operator moves between workspace work areas | Workspace selected, no environment selected, workspace-wide rows | Existing page diagnostics | Not a new decision surface; it ensures existing surfaces start from truthful scope | Workspace-first navigation | Removes hidden stale environment state from routine navigation. | | Critical workspace hubs | Existing role unchanged | Existing per-page decisions remain | Existing per-page content, now with correct default scope | Existing page details | Spec changes entry scope, not page purpose | Workspace hubs remain workspace-wide | Prevents operators from reconstructing hidden filters. | ## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)* | Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention | |---|---|---|---|---|---|---|---| | Workspace hub entry state | operator-MSP, support-platform | Workspace selected; no environment selected; no hidden environment filter | Existing filter controls and page diagnostics | Existing support/raw areas unchanged | Open selected workspace hub | Raw query/table state is not surfaced as a product feature | Shell and data scope must agree. | ## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)* | Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification | |---|---|---|---|---|---|---|---|---|---|---|---|---|---| | Workspace hub navigation contract | Navigation / Context | Workspace hub entry | Open hub workspace-wide | Existing page-defined model | Existing behavior | Existing page-defined placement | Existing page-defined placement | See registry table | Existing page-defined routes | Workspace active, Environment none | Workspace hub | No hidden environment filter from sidebar/global entry | none | ## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)* | Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions | |---|---|---|---|---|---|---|---|---|---|---| | Workspace hub entry state | MSP operator | Move from any page to a workspace hub without stale environment scope | Navigation/context contract | Which workspace context am I operating in? | Current workspace, no selected environment, workspace-wide list state | Existing page-specific diagnostics | Scope only | N/A | Open hub | None added or changed | ## Proportionality Review *(mandatory when structural complexity is introduced)* - **New source of truth?**: no persisted source of truth. - **New persisted entity/table/artifact?**: no. - **New abstraction?**: yes, a narrow workspace hub registry/contract. - **New enum/state/reason family?**: no. - **New cross-domain UI framework/taxonomy?**: no. - **Current operator problem**: sidebar/global navigation into workspace hubs can silently inherit stale environment context and show filtered rows under a workspace-wide shell. - **Existing structure is insufficient because**: page category, shell resolution, navigation builders, URL helpers, and table filter helpers each own partial state decisions; no single shared contract owns workspace hub identity and entry cleanup. - **Narrowest correct implementation**: one static/support registry listing workspace hub routes/pages and the environment-like query/filter keys to strip or ignore on sidebar/global entry. - **Ownership cost**: maintain hub membership when workspace hubs are added or reclassified; add contract tests that fail when a workspace hub URL leaks environment-like params. - **Alternative intentionally rejected**: page-by-page patches without a registry, because Spec 313 proves the same drift across Provider Connections, Operations, Finding Exceptions, Reviews, Evidence, Governance, Alerts, and Audit. - **Release truth**: current-release truth. Spec 313 browser evidence makes this a present safety issue, not future preparation. ### Compatibility posture This feature assumes a pre-production environment. Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope. Canonical replacement is preferred over preservation. No legacy `tenant`, `tenant_id`, `managed_environment_id`, `environment_id`, `tenant_scope`, or `tableFilters` behavior is preserved for sidebar/global workspace hub entry. ## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)* - **Test purpose / classification**: Feature, Filament/Livewire, and Browser. - **Validation lane(s)**: confidence for focused Feature/Livewire tests; browser for critical user flows; `git diff --check`; focused route/navigation tests. - **Why this classification and these lanes are sufficient**: URL generation and shell/data scope can be proven with Feature and Livewire tests; browser verification is required because Spec 313 showed persisted Filament table state, reload, and back/forward behavior can drift after hydration. - **New or expanded test families**: bounded Spec 314 navigation context tests and one focused browser smoke. No broad suite rebaseline. - **Fixture / helper cost impact**: tests may need explicit workspace, two Managed Environments, memberships, and rows for the covered pages. Helpers must stay feature-local or opt-in. - **Heavy-family visibility / justification**: Browser coverage is explicit and limited to critical flows inherited from Spec 313. - **Special surface test profile**: global-context-shell + monitoring-state-page + exception-coded-surface. - **Standard-native relief or required special coverage**: no styling/layout verification; special state-contract coverage required. - **Reviewer handoff**: reviewers must confirm lane fit, no hidden heavy helper defaults, and no broad browser family beyond the named Spec 314 smoke. - **Budget / baseline / trend impact**: none expected; document if browser lane expands materially. - **Escalation needed**: document-in-feature. - **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage. - **Planned validation commands**: - `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` ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Sidebar workspace hubs always open workspace-wide (Priority: P1) As an MSP operator working inside an active Managed Environment, I can click a workspace-scoped hub in the sidebar/global navigation and land on a workspace-wide version of that hub without hidden environment filters. **Why this priority**: This removes the most dangerous Spec 313 mismatch: shell says no environment selected while page data is still environment-filtered. **Independent Test**: From an Environment Dashboard state with a remembered environment, generate/open each registry workspace hub sidebar URL and assert it has no forbidden environment query params and renders with no active environment shell context. **Acceptance Scenarios**: 1. **Given** a selected Workspace and remembered Managed Environment, **When** the operator opens Provider Connections through sidebar/global navigation, **Then** the URL is clean and provider connection rows are workspace-wide across entitled environments. 2. **Given** a selected Workspace and active Environment Dashboard state, **When** the operator opens Finding Exceptions Queue, Operations, Decision Register, Customer Reviews, Reviews, Evidence, Governance Inbox, Audit Log, Alerts, Workspace Settings, or Manage Workspaces through sidebar/global navigation, **Then** no environment query params or environment-like table filters define the default scope. ### User Story 2 - Remembered environment is not a workspace hub data boundary (Priority: P1) As an MSP operator, my last used Managed Environment may still help the switcher, but it must not silently filter workspace hubs. **Why this priority**: Spec 313 shows remembered environment state can leak into links and shell decisions. **Independent Test**: Seed two environments in one workspace, remember Environment A, then open workspace hub URLs and assert Environment A is not used as a URL param, shell context, default table filter, or data query boundary. **Acceptance Scenarios**: 1. **Given** Environment A is remembered for a workspace, **When** sidebar/global Provider Connections URL is generated, **Then** it does not include `managed_environment_id`. 2. **Given** Environment A is remembered and rows exist for Environment A and B, **When** a workspace hub opens from sidebar/global navigation, **Then** entitled rows are not filtered to Environment A. ### User Story 3 - Persisted environment filters cannot override sidebar intent (Priority: P2) As an operator returning to a workspace hub after previous filtering, sidebar/global entry must be workspace-wide even if a page persisted an environment-like table filter earlier. **Why this priority**: Spec 313 found reload and back/forward behavior can revive stale filters. **Independent Test**: Persist an environment table filter for Customer Reviews, Finding Exceptions Queue, Evidence, Provider Connections, and Operations where applicable; navigate away; then enter through sidebar/global clean URL and assert environment-like persisted filters are absent or ignored. **Acceptance Scenarios**: 1. **Given** Customer Reviews was filtered to Environment A, **When** the operator enters Customer Reviews through sidebar/global navigation, **Then** the page opens workspace-wide and reload remains workspace-wide. 2. **Given** Evidence Overview or Finding Exceptions Queue had a persisted environment-like table filter, **When** the operator enters through workspace hub navigation, **Then** that filter does not define the default row scope. ### User Story 4 - Decision Register clean workspace URL is a valid workspace hub entry (Priority: P2) As an authorized workspace user, I can open Decision Register through its clean workspace URL without needing an environment filter. **Why this priority**: Spec 313 found the clean Decision Register route returned 403 while a filtered URL opened. **Independent Test**: Seed a workspace user with decision visibility and open `/admin/governance/decisions` without environment query params; assert it is not forbidden and does not require a Managed Environment query. **Acceptance Scenarios**: 1. **Given** an authorized workspace user with visible decision register access, **When** they open the clean Decision Register URL, **Then** the page opens without `managed_environment_id`. 2. **Given** no open decisions exist but the user is authorized to the workspace register, **When** they open the clean Decision Register URL, **Then** the page shows a truthful empty workspace state rather than requiring an environment filter. ### Edge Cases - A workspace hub direct URL is opened with forbidden query params. The page may still support explicit CTA filters until Spec 315, but sidebar/global navigation must not generate those params. - Browser back returns to an old filtered URL. This spec verifies sidebar/global re-entry and focused back/forward behavior; full universal clear-filter behavior belongs to Spec 316. - A page is actually environment-owned. It must not be put in the workspace hub registry; environment pages remain outside this spec. - A user lacks workspace membership. Existing deny-as-not-found behavior remains. - A user is a workspace member but lacks a capability needed for a hub. Existing capability semantics remain; this spec must not bypass authorization. ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: The implementation MUST create or formalize one canonical workspace hub registry/contract. - **FR-002**: The registry MUST identify whether a route/page is a workspace-scoped hub. - **FR-003**: The registry MUST identify whether sidebar/global navigation must clear active Managed Environment shell context for that hub. - **FR-004**: The registry MUST provide the forbidden sidebar/global query-param list: `tenant`, `tenant_id`, `managed_environment_id`, `environment_id`, `tenant_scope`, and `tableFilters`. - **FR-005**: The registry MUST provide the environment-like persisted filter keys to neutralize for workspace hub entry: `tenant`, `tenant_id`, `managed_environment_id`, `environment_id`, `environment`, and `tenant_scope`. - **FR-006**: Sidebar/global URLs for every registry workspace hub MUST be clean and MUST NOT include forbidden environment query params. - **FR-007**: Sidebar/global workspace hub entry MUST clear or bypass active Managed Environment shell context while preserving selected Workspace context. - **FR-008**: Remembered Managed Environment state MUST NOT be used as sidebar URL input, workspace hub default data filter, workspace hub authorization boundary, shell context, or fallback route parameter. - **FR-009**: Workspace hubs MUST NOT use `Filament::getTenant()` or remembered environment as a hidden default data boundary on sidebar/global entry. - **FR-010**: Environment-like persisted Filament table filters MUST NOT override sidebar/global workspace hub intent. - **FR-011**: Provider Connections sidebar/global entry MUST be workspace-wide and MUST NOT inject `managed_environment_id` from remembered context. - **FR-012**: Finding Exceptions Queue sidebar/global entry MUST be workspace-wide and MUST NOT use `tenant` query for sidebar/global entry. - **FR-013**: Operations sidebar/global entry MUST be workspace-wide and MUST NOT carry `managed_environment_id`, `tenant_scope`, or `tableFilters`. - **FR-014**: Decision Register clean workspace URL MUST open for authorized workspace users and MUST NOT require an environment filter. - **FR-015**: Customer Reviews, Reviews, Evidence, Governance Inbox, Audit Log, Alerts, Workspace Settings, Manage Workspaces, and Workspace Overview MUST honor the workspace-wide sidebar/global entry contract. - **FR-016**: Existing Environment Dashboard CTAs may keep explicit environment filters only where already present; this spec MUST NOT standardize CTA query naming or visible filter chips. - **FR-017**: Environment-owned pages MUST remain environment-owned and MUST NOT be forced workspace-wide by the registry. - **FR-018**: No legacy compatibility layer, alias adapter, dual query mapping, migration shim, backfill, or seeder change may be introduced for this contract. ### Workspace Hub Registry Contents | Registry entry | Route/page identity | Status in Spec 314 | |---|---|---| | Workspace Overview | `/admin`, `/admin/workspaces/{workspace}/overview` | include | | Operations | `/admin/workspaces/{workspace}/operations` | include | | Provider Connections / Integrations | `/admin/provider-connections` | include | | Finding Exceptions Queue | `/admin/finding-exceptions/queue` | include | | Evidence Overview | `/admin/evidence/overview` | include | | Review Register | `/admin/reviews` | include | | Customer Review Workspace | `/admin/reviews/workspace` | include | | Governance Inbox | `/admin/governance/inbox` | include | | Decision Register | `/admin/governance/decisions` | include | | Audit Log | `/admin/audit-log` | include | | Alerts landing | `/admin/alerts` | include | | Alert Deliveries | `/admin/alerts/alert-deliveries` | include | | Alert Rules | `/admin/alerts/alert-rules` | include | | Alert Destinations | `/admin/alerts/alert-destinations` | include | | Workspace Settings | `/admin/settings/workspace` | include | | Manage Workspaces | `/admin/workspaces` | include | | Managed Environments Landing | `/admin/workspaces/{workspace}/environments` | include as workspace environment catalog, not environment-owned dashboard | | Stored Reports | `/admin/workspaces/{workspace}/environments/{environment}/stored-reports` | exclude; Spec 313 found no workspace-wide reports hub | | Support Request action | modal/action only | exclude; no workspace-owned list route discovered in Spec 313 | | Environment Dashboard and child routes | `/admin/workspaces/{workspace}/environments/{environment}...` | exclude; environment-owned | ### Non-Functional Requirements - **NFR-001**: The implementation MUST preserve workspace isolation and managed-environment entitlement checks for every workspace-wide query. - **NFR-002**: The implementation MUST not introduce Graph calls, queued work, remote calls, or `OperationRun` lifecycle changes. - **NFR-003**: The implementation MUST use Laravel 12, Filament 5.2.1, Livewire 4.1.4, and Pest 4 conventions. - **NFR-004**: The implementation MUST prefer direct replacement over legacy compatibility, consistent with LEAN-001. - **NFR-005**: Browser verification MUST cover the critical Spec 313 flows after runtime changes. - **NFR-006**: Tests MUST stay focused and must not rebaseline broad navigation or browser suites. ### RBAC / Security Requirements - **SEC-001**: Workspace non-members remain deny-as-not-found. - **SEC-002**: Missing capability remains forbidden after workspace membership is established where current policies use 403. - **SEC-003**: UI visibility must not replace server-side authorization. - **SEC-004**: Provider Connections credential-adjacent actions are not changed, weakened, or newly exposed. - **SEC-005**: Workspace-wide pages must never reveal tenant-owned rows from environments outside the actor's entitlement. ### Auditability / Observability Requirements - **AUD-001**: No new audit events are required because this spec changes read/navigation context only. - **AUD-002**: Existing audit behavior for mutating actions must remain unchanged. - **AUD-003**: Implementation close-out must record exact tests, browser verification, and any remaining follow-up for Specs 315/316/317. ### Data / Truth Requirements - **DATA-001**: No migrations, seeders, data backfills, or persisted compatibility fields are in scope. - **DATA-002**: The registry is code truth for workspace hub identity, not database truth. - **DATA-003**: Environment-like persisted filter state is UI/session state only; it must not become a domain model. ## Out of Scope - Environment CTA explicit filter contract. - Universal clear-filter behavior. - Standardizing filter chips or visible scope chips. - Route alias compatibility. - Legacy `tenant`/`tenant_id` cleanup outside sidebar/global workspace hub entry. - Reclassifying all ambiguous pages. - Product IA redesign. - Application data migration, seed data, or backfill work. - New provider abstraction, provider registry, or multi-provider framework. - New destructive actions or mutating workflows. ## Acceptance Criteria ### Workspace Hub Registry - [ ] There is one canonical workspace hub registry/contract. - [ ] All workspace hubs from Spec 313 are represented or explicitly excluded with reason. - [ ] Registry distinguishes workspace hubs from environment-scoped pages. - [ ] Registry is used by sidebar/global navigation or the equivalent central contract. ### Sidebar URL Contract - [ ] Workspace hub sidebar/global URLs contain no `tenant`. - [ ] Workspace hub sidebar/global URLs contain no `tenant_id`. - [ ] Workspace hub sidebar/global URLs contain no `managed_environment_id`. - [ ] Workspace hub sidebar/global URLs contain no `environment_id`. - [ ] Workspace hub sidebar/global URLs contain no `tenant_scope`. - [ ] Workspace hub sidebar/global URLs contain no `tableFilters`. - [ ] Provider Connections no longer injects Environment query params from remembered context. - [ ] Finding Exceptions Queue no longer uses `tenant` query for sidebar/global entry. ### Shell / Data Scope Contract - [ ] Sidebar/global entry into workspace hubs clears active shell Managed Environment context. - [ ] Selected Workspace remains active. - [ ] Workspace hubs open workspace-wide by default. - [ ] Shell and data scope do not diverge on critical pages. - [ ] Remembered Environment is not used as workspace hub data scope. - [ ] `Filament::getTenant()` is not used as a hidden workspace hub default filter source. ### Persisted Filter Safety - [ ] Environment-like persisted table filters do not override sidebar/global workspace hub intent. - [ ] Customer Reviews sidebar/global entry does not restore stale Environment filter. - [ ] Finding Exceptions Queue sidebar/global entry does not restore stale Environment filter. - [ ] Evidence sidebar/global entry does not restore stale Environment filter. - [ ] Provider Connections sidebar/global entry does not restore stale Environment filter. ### Critical Page Fixes - [ ] Provider Connections workspace hub sidebar/global entry is workspace-wide. - [ ] Finding Exceptions Queue workspace hub sidebar/global entry is workspace-wide. - [ ] Operations sidebar/global entry is workspace-wide and does not carry `managed_environment_id`. - [ ] Decision Register clean workspace URL opens for authorized workspace users. - [ ] Customer Reviews sidebar/global entry no longer reload-restores stale Environment filter. - [ ] Evidence sidebar/global entry no longer silently uses stale Environment filter. ### Tests - [ ] Required tests added. - [ ] Existing relevant tests updated only if they asserted old broken behavior. - [ ] No broad test rebaseline. - [ ] Tests prove sidebar/global navigation contract. - [ ] Tests prove remembered Environment does not affect workspace hub sidebar/global URLs. - [ ] Tests prove persisted Environment filters do not override sidebar/global intent. ### Browser Verification - [ ] Focused browser verification performed for critical pages. - [ ] Screenshots saved for critical before/after flows where useful. - [ ] Reload behavior verified. - [ ] Back/forward behavior checked for high-risk pages. - [ ] Remaining mismatch documented as follow-up for Spec 315/316/317. ## Filament v5 Output Contract 1. **Livewire v4.0+ compliance**: The app uses Livewire 4.1.4 with Filament 5.2.1. Implementation must not introduce Livewire v3 references or APIs. 2. **Provider registration location**: Admin panel provider remains registered through `apps/platform/bootstrap/providers.php`; do not register providers in `bootstrap/app.php`. 3. **Global search**: Workspace hub registry work must not enable global search. Changed resources must keep existing global-search posture; Provider Connections currently disables global search. 4. **Destructive actions**: No destructive actions are added or changed. Any existing destructive action must retain `->action(...)`, `->requiresConfirmation()`, server-side authorization, audit logging, and tests. 5. **Asset strategy**: No new assets are expected. If implementation unexpectedly registers Filament assets, deployment must include `cd apps/platform && php artisan filament:assets`. 6. **Testing plan**: Feature/Livewire tests for URL/shell/data scope; focused browser smoke for critical flows; no broad UI restyling tests. ## Risks - Decision Register currently has data-dependent access behavior; the implementation must make clean workspace URL behavior truthful without hiding real authorization failures. - Persisted Filament filters may have page-specific session keys; implementation must avoid fragile one-off clearing where a shared helper can express the contract. - Provider Connections currently uses `managed_environment_id` as external id/slug in some paths and database id elsewhere; sidebar/global entry must not preserve this ambiguity. - Existing Environment CTA links may still pass explicit filters; implementation must not accidentally remove all CTA filtering before Spec 315. - Browser back/forward may revive old filtered URLs; this spec covers critical re-entry and high-risk flows, while full clear-filter semantics belong to Spec 316. ## Assumptions - Spec 313 is completed audit context and is the source of truth for page inventory and critical findings. - Specs 311 and 312 are completed historical dependencies and must not be rewritten. - There is no production data or production environment to preserve. - Workspace remains primary context; Managed Environment remains secondary context. - Provider Connections is workspace/provider-level for sidebar/global entry. - Decision Register is a workspace hub and clean workspace URL behavior is required. ## Follow-Up Spec Candidates - **315 - Environment CTA Explicit Filter Contract**: canonical environment filter query key, identifier type, visible scope chips, CTA behavior, and distinction from sidebar/global entry. - **316 - Workspace Hub Clear Filter Contract**: clear visible chip, query params, Livewire properties, Filament table filters, deferred filters, persisted/session state, reload safety. - **317 - Legacy Tenant / Environment Context Cleanup**: old `tenant` aliases, hidden `Filament::getTenant()` workspace hub usage, remembered environment as data boundary, stale tenant naming. - **318 - Browser Regression Coverage / No-Drift Guard**: durable browser/regression guard coverage for this context contract. ## Required Final Report When implementation completes, report: ```text Spec 314 completed. Changed behavior: ... Files changed: ... Workspace hub registry contents: ... Tests: - command: - result: Browser verification: ... Remaining follow-ups: - 315: - 316: - 317: Runtime files were changed: yes/no. No migrations were created. No seeders were changed. No backwards compatibility layer was introduced. No legacy query alias support was preserved for workspace hub sidebar/global entry. ```