## Summary - cut over workspace-owned analysis and library surfaces to workspace shell ownership instead of inheriting remembered environment shell context - update the affected findings pages, scope resolution, navigation helpers, and related Blade views to keep environment focus explicit instead of implicit - add and update Spec 320 artifacts plus focused regression coverage for findings navigation context, workspace hub registration, and admin surface scope behavior ## Guardrails - Filament remains on v5 with Livewire v4 compliance unchanged - provider registration remains in apps/platform/bootstrap/providers.php - no new globally searchable resources were introduced or changed - no new destructive actions were introduced or changed - no Filament assets were added or changed, so the deploy requirement for filament:assets is unchanged ## Testing - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/FindingsAssignmentHygieneReportTest.php tests/Feature/Findings/FindingsIntakeQueueNavigationContextTest.php tests/Feature/Findings/FindingsIntakeQueueTest.php tests/Feature/Findings/MyFindingsInboxNavigationContextTest.php tests/Feature/Findings/MyWorkInboxTest.php tests/Feature/Navigation/WorkspaceHubRegistryTest.php tests/Unit/Support/OperateHub/OperateHubShellResolutionTest.php tests/Unit/Tenants/AdminSurfaceScopeTest.php` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #375
18 KiB
Implementation Plan: Workspace-Owned Analysis Surface Registration & Shell Cutover
Branch: 320-workspace-owned-analysis-surface-registration-shell-cutover | Date: 2026-05-16 | Spec: spec.md
Input: Feature specification from /specs/320-workspace-owned-analysis-surface-registration-shell-cutover/spec.md
Preparation status: Specification artifacts only. No runtime implementation has been performed by this preparation step.
Summary
Spec 320 hard-cuts workspace-owned analysis/library pages away from remembered Environment shell inheritance:
Workspace-owned analysis surface
-> clean workspace route
-> Workspace shell only
-> no active Environment shell
-> no remembered Environment fallback
-> optional Environment filter only through canonical environment_id + visible chip
The implementation must classify the audited workspace-owned analysis surfaces from Spec 318, especially Baselines/Baseline Profiles, Baseline Snapshots, Baseline Compare Matrix, My Findings, Findings Intake, Findings Hygiene, and Cross-environment Compare. Baseline Compare remains Environment-owned from Spec 319. Alerts/Audit Log filter decisions remain Spec 321.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12.52.0
Primary Dependencies: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, Laravel Sail
Storage: PostgreSQL; no schema changes planned
Testing: Pest 4 / PHPUnit 12, Filament/Livewire tests, focused browser smoke
Validation Lanes: fast-feedback, confidence, browser
Target Platform: apps/platform Laravel/Filament admin panel, local Sail, staging/production through Dokploy
Project Type: Web application
Performance Goals: No material performance change. Classification and shell resolution must remain cheap request-time logic.
Constraints: No migrations, seeders, packages, env vars, queues, scheduler, storage, deployment assets, compatibility routes, redirects, or legacy query alias support.
Scale/Scope: Focused shell/context classification for workspace-owned analysis surfaces plus targeted regressions for Specs 314-319.
UI / Surface Guardrail Plan
- Guardrail scope: route/shell/query/copy/navigation behavior for existing operator-facing workspace-owned analysis pages.
- Native vs custom classification summary: Existing Filament Resources/Pages and Blade views. No styling redesign.
- Shared-family relevance: navigation, shell context, breadcrumbs, filter chips, clear actions, OperationRun links.
- State layers in scope: shell, page, record/detail, URL query, Filament table filter state, Livewire referer classification.
- Audience modes in scope: operator-MSP and support-platform.
- Decision/diagnostic/raw hierarchy plan: Workspace ownership must be default-visible; Environment context may appear as data/filter state only.
- Raw/support gating plan: no raw/support evidence exposure change.
- One-primary-action / duplicate-truth control: The shell is the single ownership signal; page filters/selectors do not become shell ownership.
- Handling modes by drift class or surface: hard-stop for remembered Environment shell on in-scope clean URLs; review-mandatory for any newly discovered workspace analysis route.
- Repository-signal treatment: Spec 318 M2/M4 are implementation inputs; pages outside those findings are inspect-only unless repo evidence proves same mismatch.
- Special surface test profiles:
global-context-shell. - Required tests or manual smoke: classifier tests, URL/query tests, Livewire/Feature render tests, browser smoke for workspace origin, Environment origin, reload, and back/forward.
- Exception path and spread control: A distinct workspace-owned analysis classifier is allowed only if
WorkspaceHubRegistrywould overstate hub/filter behavior. Document the choice in implementation close-out. - Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage.
Shared Pattern & System Fit
- Cross-cutting feature marker: yes.
- Systems touched:
AdminSurfaceScope,WorkspaceHubRegistry,WorkspaceSidebarNavigation,WorkspaceHubEnvironmentFilter,WorkspaceHubFilterStateResetter,WorkspaceScopedEnvironmentRoutes,ManagedEnvironmentLinks,OperateHubShell, baseline resources/pages, findings analysis pages, cross-environment compare page, tests, browser smoke artifacts. - Shared abstractions reused: existing workspace hub shell contract,
AdminSurfaceScope,WorkspaceHubRegistryquery cleaning,WorkspaceHubEnvironmentFilter,CanonicalAdminEnvironmentFilterState, and current route/link helpers. - New abstraction introduced? why?: none preferred. If necessary, add the narrowest possible
AdminSurfaceScopeclassification for workspace-owned analysis surfaces to force environmentless shell without implying full workspace-hub behavior. - Why the existing abstraction was sufficient or insufficient:
WorkspaceHubRegistryworks for registered hubs; genericWorkspaceScopedis insufficient because it allows remembered Environment restore. - Bounded deviation / spread control: Do not introduce a general surface taxonomy beyond the audited route list. Do not register pages as hubs unless they truly satisfy hub/filter/clear behavior.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes, as regression only for existing baseline capture/compare actions.
- Central contract reused:
OperationUxPresenter,OpsUxBrowserEvents,OperationRunLinks, current services/jobs. - Delegated UX behaviors: existing queued toast, run link, browser event, authorization, and audit behavior remain unchanged.
- Surface-owned behavior kept local: existing initiation inputs/actions on Baseline Profile and Baseline Compare Matrix.
- Queued DB-notification policy: N/A.
- Terminal notification path: Existing central lifecycle only.
- Exception path: none.
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes.
- Provider-owned seams: Microsoft/Intune baseline content, provider IDs, Graph-backed snapshot evidence, compare strategy internals.
- Platform-core seams: Workspace/Environment route ownership, shell classification, query key semantics, navigation ownership language.
- Neutral platform terms / contracts preserved: Workspace, Environment, workspace-owned analysis surface, workspace hub, filtered workspace hub, Environment-owned page.
- Retained provider-specific semantics and why: Baseline content remains Microsoft/Intune-shaped because it is current provider implementation truth.
- Bounded extraction or follow-up path: Spec 321 and Spec 322 remain follow-ups; no provider abstraction work here.
Constitution Check
GATE: Must pass before implementation. Re-check after runtime changes.
- Inventory-first: no inventory/snapshot truth change. Baseline snapshots remain immutable evidence/artifacts.
- Read/write separation: no new write behavior. Existing capture/compare/preflight actions keep confirmation, authorization, audit, and OperationRun semantics.
- Graph contract path: no new Graph calls; page render must remain DB-only.
- Deterministic capabilities: existing capability checks remain; route/shell classification must be testable.
- RBAC-UX: non-member / not entitled Workspace or Environment access remains deny-as-not-found where applicable; member missing capability follows existing behavior.
- Workspace isolation: current Workspace remains the primary shell and authorization boundary.
- Tenant/Environment isolation: Environment-owned rows remain scoped by accessible environments; optional filters must resolve only inside current Workspace and entitlement.
- Run observability: existing baseline operation runs remain observable; no new operation type.
- Test governance: lane purpose, heavy/browser visibility, fixture cost, and reviewer handoff are explicit.
- Proportionality: possible classifier addition is justified by current browser-proven shell mismatch and bounded route list.
- No premature abstraction: prefer extending existing classifier/registry paths over a new framework.
- Persisted truth: no tables/entities/artifacts added.
- Behavioral state: no new business state/status/reason family.
- UI semantics: no new badge/status taxonomy; direct shell/page/filter truth only.
- Shared pattern first: reuse workspace hub and shell resolution contracts.
- Provider boundary: no provider tenant ID alias or fallback becomes platform shell truth.
- V1 explicitness / few layers: hard cutover, no compatibility layer.
- Filament-native UI: no ad-hoc styling or published internals.
- Filament v5 / Livewire v4: Livewire 4.1.4 satisfies Filament v5 requirement; no Livewire v3 APIs.
- Provider registration: Laravel 12 panel providers remain in
apps/platform/bootstrap/providers.php; no provider registration work planned. - Global search: no global search behavior should change. Baseline Profile and Baseline Snapshot global search remain disabled unless implementation explicitly verifies a safe View/Edit route and updates tests.
- Destructive/high-impact actions: no new destructive action. Existing archive/capture/compare/preflight actions must keep
->action(...), confirmation where required, authorization, audit, notifications, and tests. - Asset strategy: no Filament assets planned; no new
filament:assetsdeployment requirement.
Test Governance Check
- Test purpose / classification by changed surface: Unit for classifier/registry; Feature/Livewire for shell/access/filter behavior; Browser for integrated shell/sidebar/reload/history.
- Affected validation lanes: fast-feedback, confidence, browser.
- Why this lane mix is the narrowest sufficient proof: The defect is both classification logic and browser-visible shell drift.
- Narrowest proving command(s):
cd apps/platform && ./vendor/bin/sail artisan test --filter=AdminSurfaceScopecd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHubRegistrycd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceOwnedAnalysiscd apps/platform && ./vendor/bin/sail artisan test --filter=BaselineCompareEnvironmentRouteContractcd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHubEnvironmentFilterContract- focused Spec 320 browser smoke.
- Fixture / helper / factory / seed / context cost risks: workspace/environment/member plus small baseline/finding fixtures; keep any full browser fixture explicit and named.
- Expensive defaults or shared helper growth introduced?: no. If a helper is needed, make expensive setup opt-in.
- Heavy-family additions, promotions, or visibility changes: explicit browser smoke only; no broad discovery guard in this spec.
- Surface-class relief / special coverage rule:
global-context-shell. - Closing validation and reviewer handoff: prove clean URLs, filtered URLs, legacy aliases, remembered fallback rejection, Baseline Compare regression, Decision Register regression, and browser screenshots.
- Budget / baseline / trend follow-up: none expected; document if browser smoke runtime grows materially.
- Review-stop questions: Are any workspace-owned analysis URLs still generic
WorkspaceScopedwith remembered restore? Did any page get registered as a hub without supporting hub/filter/clear behavior? Did legacy aliases return? - Escalation path: document-in-feature.
- Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage.
- Why no dedicated follow-up spec is needed: This is the dedicated follow-up for Spec 318 M2/M4. Alerts/Audit and durable browser guard already have 321/322.
Project Structure
Documentation (this feature)
specs/320-workspace-owned-analysis-surface-registration-shell-cutover/
+-- spec.md
+-- plan.md
+-- tasks.md
+-- checklists/
+-- requirements.md
Source Code (likely affected during later implementation)
apps/platform/app/
+-- Support/Navigation/
| +-- AdminSurfaceScope.php
| +-- WorkspaceHubRegistry.php
| +-- WorkspaceSidebarNavigation.php
+-- Support/OperateHub/OperateHubShell.php
+-- Support/ManagedEnvironmentLinks.php
+-- Filament/Resources/
| +-- BaselineProfileResource.php
| +-- BaselineSnapshotResource.php
+-- Filament/Pages/
| +-- BaselineCompareMatrix.php
| +-- CrossEnvironmentComparePage.php
| +-- Findings/
| +-- MyFindingsInbox.php
| +-- FindingsIntakeQueue.php
| +-- FindingsHygieneReport.php
+-- Filament/Concerns/WorkspaceScopedEnvironmentRoutes.php
apps/platform/tests/
+-- Unit/Tenants/AdminSurfaceScopeTest.php
+-- Unit/Support/OperateHub/OperateHubShellResolutionTest.php
+-- Feature/Navigation/WorkspaceHubRegistryTest.php
+-- Feature/Navigation/WorkspaceHubEnvironmentFilterContractTest.php
+-- Feature/Filament/
| +-- BaselineCompareEnvironmentRouteContractTest.php
| +-- BaselineProfile*.php
| +-- BaselineSnapshot*.php
+-- Feature/Findings/
| +-- MyFindingsInboxNavigationContextTest.php
| +-- FindingsIntakeQueueNavigationContextTest.php
+-- Browser/
+-- Spec320WorkspaceOwnedAnalysisSurfaceSmokeTest.php
Structure Decision: Use existing Laravel/Filament app structure. Do not create new base folders. Add test files only where the existing test families already live, or extend existing focused files when lower churn is clearer.
Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
Possible new AdminSurfaceScope value |
Generic WorkspaceScoped allows remembered Environment restore; workspace hubs already force environmentless shell but not every analysis page is a hub |
Blindly adding every page to WorkspaceHubRegistry could falsely imply hub/filter/clear behavior |
Proportionality Review
- Current operator problem: Workspace-owned pages can appear Environment-owned in the shell with no filter chip or route ownership.
- Existing structure is insufficient because:
WorkspaceScopedrestores remembered Environment;WorkspaceHubRegistryis reserved for hub-like surfaces. - Narrowest correct implementation: Classify a route list or narrow scope category as workspace-owned analysis and make it force environmentless shell.
- Ownership cost created: Focused classifier tests, URL/filter tests, browser smoke, and implementation close-out documentation.
- Alternative intentionally rejected: Keep generic fallback, add legacy aliases, or add all pages to workspace hub registry regardless of actual hub behavior.
- Release truth: Current-release cleanup before production.
Implementation Phases
Phase 0 - Repo Verification
Re-read Spec 318 artifacts and current code paths. Confirm the final in-scope list before runtime edits:
- Baselines/Baseline Profiles.
- Baseline Profile view/edit/create if applicable.
- Baseline Compare Matrix.
- Baseline Snapshots.
- My Findings, Findings Intake, Findings Hygiene.
- Cross-environment Compare.
- Any other Spec 318 unregistered workspace analysis surface still present in routes/navigation.
Phase 1 - Tests First
Add focused tests that fail on current remembered Environment inheritance:
AdminSurfaceScopeclassification for in-scope paths.- Shell resolution with remembered Environment present.
- Clean URL opens without active Environment.
- Legacy alias rejection.
- Optional
environment_idfilter behavior where supported. - Baseline Compare and Decision Register regressions.
Phase 2 - Classification / Registry Cutover
Implement the narrowest classifier mechanism:
- Prefer existing registry/classifier extensions.
- Add a distinct workspace-owned analysis surface classification only if needed.
- Ensure
forcesEnvironmentlessShellContext()returns true for these paths. - Ensure
allowsRememberedEnvironmentRestore()is false for these paths. - Preserve Workspace state and authorization.
Phase 3 - Page / Link / Copy Alignment
Update only in-scope surfaces:
- Sidebar/global/workspace links emit clean workspace URLs unless explicit
environment_idfilter is supported. - Environment-origin links do not carry active Environment shell ownership.
- Headers, breadcrumbs, empty states, and copy use workspace/library/work-queue wording.
- Existing Environment columns, selectors, badges, and filters remain data/filter state.
Phase 4 - Regression and Browser Proof
Run focused tests and browser smoke:
- Baselines workspace origin, environment origin, reload.
- Baseline Snapshots workspace origin, environment origin, reload.
- Baseline Compare Matrix direct/reload/back-forward.
- My Findings/Intake/Hygiene and Cross-environment Compare direct/from Environment context.
- Baseline Compare Environment-owned regression.
- Decision Register workspace hub/filtered hub regression.
Save screenshots under:
specs/320-workspace-owned-analysis-surface-registration-shell-cutover/artifacts/screenshots/
Phase 5 - Close-Out
Document:
- classification outcomes for Baselines/Baseline Snapshots.
- unregistered workspace analysis pages fixed or excluded.
- whether any page was reclassified Environment-owned.
- how remembered Environment inheritance was prevented.
- tests and browser verification.
- no migrations/packages/env vars/queues/scheduler/storage/assets.
- no backwards compatibility or legacy alias support.
Rollout Considerations
- No database migration or data backfill.
- No production compatibility burden because pre-production hard cutover is the standing policy.
- No Dokploy runtime change.
- No new
filament:assetsdeployment step. - Staging validation should run focused tests and browser smoke before promotion.
Risk Controls
- Keep route list explicit and tested.
- Do not generalize classifier beyond audited need.
- Do not add Environment filter feature work unless a page already has product need and visible chip/clear behavior can be proven.
- Replace old tests that assert broken remembered fallback; do not keep them as compatibility coverage.
- Keep Spec 321 and Spec 322 out of scope.