## Summary - add a shared workspace hub registry for canonical workspace-scoped navigation entry - keep sidebar and global workspace hub URLs free of inherited environment query and filter state - add focused feature and browser coverage for workspace hub shell and data-scope contracts ## Validation - 54 focused feature tests passed (205 assertions) - 1 browser smoke test passed (361 assertions) - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `git diff --check` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #369
471 lines
37 KiB
Markdown
471 lines
37 KiB
Markdown
# 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.
|
|
```
|