## Summary - retire the remaining tenant-scoped provider-connection legacy routes and update canonical verification and link behavior - complete the provider target-scope fallback cleanup so neutral shared scope data falls back to the managed environment when the raw connection tenant identifier is blank - stop mirroring workspace roles into managed-environment scope persistence and cut the targeted admin-panel test helpers over to the post-cutover context path - add and update the Spec 287 artifact package and targeted regression coverage for route retirement, provider-core neutralization, workspace-first RBAC, and helper cutover ## Validation - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections/LegacyRedirectTest.php tests/Feature/ProviderConnections/TenantlessListRouteTest.php tests/Feature/ProviderConnections/TenantlessListScopingTest.php tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php tests/Feature/Rbac/TriageReviewStateAuthorizationTest.php` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec281ProviderConnectionScopeSmokeTest.php tests/Browser/Spec285WorkspaceRbacEnvironmentAccessSmokeTest.php` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` ## Notes - Filament remains on Livewire v4 and provider registration stays unchanged in `apps/platform/bootstrap/providers.php`. - No new asset registration or deployment-step changes are included in this slice. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #346
18 KiB
Implementation Plan: Cutover Prerequisite Completion
Branch: 287-cutover-prerequisite-completion | Date: 2026-05-10 | Spec: spec.md
Input: Feature specification from specs/287-cutover-prerequisite-completion/spec.md
Summary
Complete the remaining runtime and test-harness seams that still block the later quality-gates / no-legacy package. The narrow implementation path retires the legacy provider-connection route family, finishes provider target-scope core neutralization on the shared provider seams, cleans environment-scope role persistence so workspace membership remains the only role-bearing truth, replaces tenant-panel-era test helpers with post-cutover admin or workspace helpers, and validates only those seams with targeted feature and browser coverage.
This plan is intentionally not a no-legacy guard package. Filament remains v5 on Livewire v4, provider registration remains in apps/platform/bootstrap/providers.php, no new asset or deployment step is introduced, no full-suite baseline is required, and Spec 288 remains the explicit follow-up for quality gates and no-legacy enforcement.
Inherited Baseline / Explicit Delta
Inherited baseline
- Spec
279already owns the managed-environment core cutover and remains historical baseline context only. - Spec
280already owns the workspace-first route and panel-shell convergence, but repo truth still shows a surviving legacy provider-connection route family inapps/platform/routes/web.php. - Spec
281already owns provider boundary groundwork, but repo truth still shows Microsoft-shaped shared target-scope and identity fields on platform-core provider seams. - Spec
282already owns governance-artifact retargeting and remains adjacent historical context only. - Spec
285already owns the workspace-first RBAC direction, but repo truth still shows incomplete environment-scope persistence cleanup where managed-environment membership records mirror workspace role values. - Spec
286already owns UI copy cleanup and remains explicitly out of scope for this package.
Explicit delta in this plan
- Retire the remaining legacy provider-connection route family instead of guarding it.
- Finish provider target-scope and identity neutralization on shared provider-core seams instead of leaving that work to a later enforcement slice.
- Complete the runtime cleanup that keeps workspace membership role-bearing and environment scope narrowing-only.
- Replace tenant-panel-era shared test helpers and the proof-command consumer tests
apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.phpandapps/platform/tests/Feature/Rbac/TriageReviewStateAuthorizationTest.phpwith post-cutover admin or workspace context helpers. - Keep proof targeted to changed seams only and hand global enforcement to Spec
288.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12.52
Primary Dependencies: Pest 4, Filament 5.2.1, Livewire 4.1.4, existing provider target-scope and access-scope services, shared Pest test helpers
Storage: no new persistence; the package completes behavior on existing route, provider-core, access-scope, and test-support seams
Testing: targeted Pest feature tests plus targeted browser validation
Validation Lanes: fast-feedback, confidence, browser
Target Platform: Laravel monolith in apps/platform
Project Type: web application
Performance Goals: keep validation limited to the changed seams; no full-suite or broad guard lane work
Constraints: no global guard suite, no full-suite baseline, no package execution, no guided operations, no UI copy cleanup, no provider capability expansion
Scale/Scope: one bounded prerequisite-completion slice immediately preceding Spec 288
Likely Affected Repo Surfaces
apps/platform/routes/web.phpapps/platform/app/Services/Providers/ProviderConnectionResolver.phpapps/platform/app/Services/Providers/ProviderIdentityResolver.phpapps/platform/app/Services/Providers/ProviderIdentityResolution.phpapps/platform/app/Services/Providers/PlatformProviderIdentityResolver.phpapps/platform/app/Services/Providers/ProviderOperationStartGate.phpapps/platform/app/Support/Providers/TargetScope/ProviderConnectionTargetScopeNormalizer.phpapps/platform/app/Support/Providers/TargetScope/ProviderConnectionTargetScopeDescriptor.phpapps/platform/app/Services/Auth/TenantMembershipManager.phpapps/platform/app/Services/Auth/ManagedEnvironmentAccessScopeResolver.phpapps/platform/app/Providers/Filament/AdminPanelProvider.phpapps/platform/app/Filament/Resources/TenantResource.phpapps/platform/app/Filament/Pages/TenantRequiredPermissions.phpapps/platform/app/Support/OperationRunLinks.phpapps/platform/app/Support/Providers/ProviderReasonTranslator.phpapps/platform/app/Support/Verification/VerificationLinkBehavior.phpapps/platform/tests/Pest.php- targeted feature tests in
apps/platform/tests/Feature/ProviderConnections/,apps/platform/tests/Feature/Auth/,apps/platform/tests/Feature/Rbac/,apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php, andapps/platform/tests/Feature/Rbac/TriageReviewStateAuthorizationTest.php - targeted browser tests in
apps/platform/tests/Browser/
Filament v5 / Surface Notes
- Livewire v4.0+ compliance: all touched surfaces remain on Filament v5 with Livewire v4.
- Provider registration location: provider registration remains in
apps/platform/bootstrap/providers.php; this package does not add a new panel or change provider registration location. - Global search rule: this slice introduces no new globally-searchable resource. Existing provider-connection resource behavior remains unchanged from a global-search standpoint.
- Destructive actions: no new destructive action is introduced. Any touched existing destructive actions must keep
->action(...),->requiresConfirmation(), and server authorization. - Asset strategy: no new asset registration or deployment step is planned.
Prerequisite Completion Fit
- Complete runtime truth first, then let Spec
288enforce that truth. - Prefer canonical replacement over compatibility routes, copied role persistence, or tenant-panel test-only fallbacks.
- Keep Microsoft-specific detail nested under provider-owned seams instead of the shared provider-core contract.
- Keep the package bounded to five named prerequisite areas and reject adjacent feature work.
- Use exact targeted validation commands across
spec.md,plan.md,tasks.md, andquickstart.md.
UI / Surface Guardrail Plan
- Guardrail scope: bounded runtime completion over existing provider-connection and provider-backed operator surfaces
- Native vs custom classification summary: existing native Filament provider-connection surfaces and shared provider summaries only; no new operator-facing page family
- Shared-family relevance: navigation, provider target-scope summaries, run-launch context, and test harness setup
- State layers in scope: route, page, detail, shared provider-core payloads, access-scope persistence, and test-support context helpers
- Audience modes in scope: operator-MSP, support-platform on existing provider surfaces only
- Decision/diagnostic/raw hierarchy plan: keep current provider-owned diagnostics nested; change only the shared contract and canonical route truth
- Raw/support gating plan: preserve existing provider-owned raw detail where current support or consent workflows genuinely need it
- One-primary-action / duplicate-truth control: no new action family is introduced; existing launch and open actions continue to own the workflow
- Handling modes by drift class or surface: implementation-required for the named seams; out of scope for global enforcement and copy cleanup
- Repository-signal treatment: direct runtime completion only; no broad source-scan or lint layer
- Special surface test profiles: standard-native-filament, global-context-shell
- Required tests or manual smoke: functional-core, targeted browser-smoke
- Exception path and spread control: provider-owned Microsoft detail only; no other exception expansion
- Active feature PR close-out entry: RuntimePrerequisite
Shared Pattern & System Fit
- Cross-cutting feature marker: yes
- Systems touched: provider route ownership, shared provider target-scope and identity resolution, workspace-first access persistence cleanup, and shared test helpers
- Shared abstractions reused: existing provider target-scope and identity helpers, existing workspace access resolver seams, and existing
tests/Pest.phphelper style - New abstraction introduced? why?: none
- Why the existing abstraction was sufficient or insufficient: the abstractions already exist; the incomplete cutover behavior inside them is the real remaining work
- Bounded deviation / spread control: Microsoft-specific profile detail remains nested only where provider-owned workflows still need it
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes, as shared provider-backed run context and canonical link truth only
- Central contract reused:
ProviderOperationStartGate, existing OperationRun context, and canonical operation links - Delegated UX behaviors: existing queued, blocked, and run-link semantics remain delegated; this slice changes only the prerequisite data and route truth they rely on
- Surface-owned behavior kept local: existing provider launch or open actions only
- Queued DB-notification policy:
N/A - Terminal notification path: existing central lifecycle mechanism
- Exception path: none
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes
- Provider-owned seams: consent/profile detail, Microsoft-specific identifiers, Graph-specific diagnostics, and provider-owned support metadata
- Platform-core seams: provider-connection route ownership, shared target-scope and identity outputs, provider-backed run context, and workspace-scoped launch truth
- Neutral platform terms / contracts preserved:
provider connection,target scope,scope kind,scope identifier,scope display name,workspace,managed environment - Retained provider-specific semantics and why: existing consent and support flows still need Microsoft tenant/profile data, but only as provider-owned nested detail
- Bounded extraction or follow-up path: Spec
288for no-legacy enforcement after this slice lands
Constitution Check
GATE: Must pass before implementation begins and again after design artifacts are complete.
- Inventory-first: PASS. No new inventory or snapshot truth is introduced.
- Read/write separation: PASS. The slice completes existing runtime seams without adding a new workflow surface.
- Graph contract path: PASS by preservation. No new Graph integration family or registry is introduced.
- Deterministic capabilities: PASS by preservation. Capability families do not expand.
- RBAC-UX: PASS. Workspace membership remains role-bearing and environment scope becomes narrowing-only on the completed seams.
- Workspace isolation: PASS. The package preserves workspace-first routing and entitlement boundaries.
- Managed-environment isolation: PASS. The package narrows environment scope instead of broadening it.
- Run observability: PASS. Existing OperationRun lifecycle and links remain central.
- OperationRun start UX: PASS. No new start or completion UX family is added.
- Data minimization: PASS. No new persistence or compatibility ledger is introduced.
- Test governance: PASS. Validation stays targeted and explicit.
- Proportionality / no premature abstraction: PASS. Existing seams are completed rather than wrapped in new frameworks.
- Persisted truth / behavioral state: PASS. No new persistence or state family is introduced.
- Provider boundary: PASS. Shared provider-core contracts become more neutral while provider-owned detail stays bounded.
Gate evaluation: PASS.
Post-design re-check: PASS while spec.md, plan.md, tasks.md, and quickstart.md keep the same literal proof commands, and research.md, data-model.md, contracts/cutover-prerequisite-completion.logical.openapi.yaml, and checklists/requirements.md keep the same seam inventory and Spec 288 follow-up boundary.
Test Governance Check
- Test purpose / classification by changed surface: Feature, Browser
- Affected validation lanes: fast-feedback, confidence, browser
- Why this lane mix is the narrowest sufficient proof: the changed seams are concrete runtime and test-support paths, so focused feature tests plus a narrow browser smoke are sufficient and honest
- Narrowest proving command(s):
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections/LegacyRedirectTest.php tests/Feature/ProviderConnections/TenantlessListRouteTest.php tests/Feature/ProviderConnections/TenantlessListScopingTest.php tests/Feature/Auth/WorkspaceFirstManagedEnvironmentAccessTest.php tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php tests/Feature/Rbac/TriageReviewStateAuthorizationTest.php)export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Browser/Spec281ProviderConnectionScopeSmokeTest.php tests/Browser/Spec285WorkspaceRbacEnvironmentAccessSmokeTest.php)export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail bin pint --dirty --format agent)
- Fixture / helper / factory / seed / context cost risks: moderate only because the shared tenant-panel helper is being replaced on
tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.phpandtests/Feature/Rbac/TriageReviewStateAuthorizationTest.php - Expensive defaults or shared helper growth introduced?: no; the helper cutover must reduce dependence on retired panel state rather than add new implicit defaults
- Heavy-family additions, promotions, or visibility changes: none
- Surface-class relief / special coverage rule:
standard-native-filamentandglobal-context-shellremain sufficient; no heavy-governance coverage is justified - Closing validation and reviewer handoff: rerun the exact commands above, verify Filament stays on Livewire v4, provider registration remains in
apps/platform/bootstrap/providers.php, no asset registration or deployment-step drift was added, no full-suite or guard-family work was added, and confirm Spec288remains the explicit follow-up - Budget / baseline / trend follow-up: contained feature-local increase only
- Review-stop questions: did the implementation widen into no-legacy guards, UI copy cleanup, package execution, guided operations, or provider capability expansion
- Escalation path:
document-in-featurefor contained seam follow-up,reject-or-splitfor scope expansion - Active feature PR close-out entry: RuntimePrerequisite
Review Checklist Status
- Review checklist artifact:
checklists/requirements.md - Review outcome class:
acceptable-special-case - Workflow outcome:
keep - Test-governance outcome:
keep - Resolution note: the package is implementation-ready as a bounded prerequisite-completion slice and no longer depends on a blocked-by-prerequisites posture
- Escalation rule: if implementation starts adding guard suites, full-suite baselines, or adjacent product features, stop and split the work out of
287
Rollout Considerations
- Retire the legacy provider-connection route family before widening targeted validation so the canonical route truth settles first.
- Complete provider target-scope neutralization before touching the browser proof so the live provider surfaces already speak the intended shared contract.
- Cut over the shared test helper before updating
apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.phpandapps/platform/tests/Feature/Rbac/TriageReviewStateAuthorizationTest.phpso targeted tests do not drift through two helper systems. - Keep Spec
288untouched during runtime completion; it should start from the completed baseline produced by this slice.
Risk Controls
- Reject any implementation that keeps legacy provider-connection aliases as compatibility routes for convenience.
- Reject any implementation that solves provider target-scope cleanup by hiding Microsoft-only fields in new platform-core wrappers instead of neutralizing the shared contract.
- Reject any implementation that preserves copied role-bearing state on environment-scope persistence after the cleanup.
- Reject any implementation that adds a global guard family, broad source-scan package, or full-suite baseline under this spec.
Research & Design Outputs
research.mdrecords the completion-first decisions, bounded runtime scope, rejected guard-suite alternative, and evidence anchors.data-model.mdcaptures the derived seam inventory, canonical replacements, and invariants.quickstart.mdgives reviewers the scope boundary, review scenarios, and exact targeted proof commands.contracts/cutover-prerequisite-completion.logical.openapi.yamlmodels the logical completion seams and the targeted validation contract.checklists/requirements.mdrecords the review outcome and bounded scope rules.
Project Structure
Documentation (this feature)
specs/287-cutover-prerequisite-completion/
├── checklists/
│ └── requirements.md
├── contracts/
│ └── cutover-prerequisite-completion.logical.openapi.yaml
├── data-model.md
├── plan.md
├── quickstart.md
├── research.md
├── spec.md
└── tasks.md
Source Code (repository root)
apps/platform/
├── app/
├── routes/
└── tests/
├── Browser/
├── Feature/
└── Pest.php
Structure Decision: keep the package inside the existing Laravel app, route, provider, access-service, and Pest test-support structure. No new base directory is needed.