TenantAtlas/specs/320-workspace-owned-analysis-surface-registration-shell-cutover/plan.md
ahmido ec9649897a feat: cut over workspace-owned analysis shell context (#375)
## 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
2026-05-16 23:16:53 +00:00

288 lines
18 KiB
Markdown

# 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](/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/320-workspace-owned-analysis-surface-registration-shell-cutover/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:
```text
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 `WorkspaceHubRegistry` would 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`, `WorkspaceHubRegistry` query cleaning, `WorkspaceHubEnvironmentFilter`, `CanonicalAdminEnvironmentFilterState`, and current route/link helpers.
- **New abstraction introduced? why?**: none preferred. If necessary, add the narrowest possible `AdminSurfaceScope` classification for workspace-owned analysis surfaces to force environmentless shell without implying full workspace-hub behavior.
- **Why the existing abstraction was sufficient or insufficient**: `WorkspaceHubRegistry` works for registered hubs; generic `WorkspaceScoped` is 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:assets` deployment 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=AdminSurfaceScope`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHubRegistry`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceOwnedAnalysis`
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=BaselineCompareEnvironmentRouteContract`
- `cd 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 `WorkspaceScoped` with 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)
```text
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)
```text
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**: `WorkspaceScoped` restores remembered Environment; `WorkspaceHubRegistry` is 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:
- `AdminSurfaceScope` classification for in-scope paths.
- Shell resolution with remembered Environment present.
- Clean URL opens without active Environment.
- Legacy alias rejection.
- Optional `environment_id` filter 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_id` filter 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:
```text
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:assets` deployment 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.