## Summary - add derived onboarding readiness to the managed tenant onboarding workflow and multi-draft picker - keep provider-specific permission diagnostics secondary while preserving canonical `Open operation` and existing onboarding action semantics - add spec-kit artifacts for `240-tenant-onboarding-readiness` and align roadmap/spec-candidate planning notes - unify the required-permissions empty state copy to English ## Validation - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/RequiredPermissions/RequiredPermissionsEmptyStateTest.php` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - browser smoke exercised the onboarding picker, route-bound mismatch readiness state, canonical `Open operation` path, and local fixture cleanup ## Notes - branch includes the generated spec artifacts under `specs/240-tenant-onboarding-readiness/` - temporary browser smoke tenants/drafts/runs were cleaned from the local environment after validation Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #277
18 KiB
Implementation Plan: Self-Service Tenant Onboarding & Connection Readiness
Branch: 240-tenant-onboarding-readiness | Date: 2026-04-25 | Spec: /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/240-tenant-onboarding-readiness/spec.md
Input: Feature specification from /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/240-tenant-onboarding-readiness/spec.md
Note: This template is filled in by the /speckit.plan command. See .specify/scripts/ for helper scripts.
Summary
- Add one operator-facing, derived readiness summary to the existing managed-tenant onboarding workflow: the route-bound draft at
/admin/onboarding/{onboardingDraft}always shows full readiness, while the/admin/onboardinglanding surface adds compact readiness only when multiple resumable drafts exist and preserves the existing single-draft redirect behavior. - Reuse current onboarding draft lifecycle, provider connection summary, verification diagnostics, the existing 30-day permission freshness rule, and canonical OperationRun links instead of adding new persistence, readiness enums, or provider-generic onboarding frameworks.
- Keep the workflow DB-only at render time, workspace- and tenant-safe, and centered on one operator decision: what blocks this tenant now and what the next action is.
- Defer numeric completion scoring and any cross-surface readiness abstraction; later consumers must reuse the same derived onboarding truth instead of broadening this slice.
Technical Context
Language/Version: PHP 8.4 (Laravel 12)
Primary Dependencies: Laravel 12 + Filament v5 + Livewire v4 + Pest; existing onboarding services (OnboardingLifecycleService, OnboardingDraftStageResolver), provider connection summary, verification assist, and Ops-UX helpers
Storage: PostgreSQL via existing managed_tenant_onboarding_sessions, provider_connections, operation_runs, and stored permission-posture data; no new persistence planned
Testing: Pest feature + unit tests (Filament/Livewire feature coverage plus policy/unit coverage)
Validation Lanes: fast-feedback
Target Platform: Sail-backed Laravel admin panel under /admin
Project Type: web
Performance Goals: onboarding landing and draft routes remain DB-only at render/hydration, compose readiness in-request from existing records, and avoid outbound HTTP or new queue starts during page render
Constraints: preserve workspace isolation, linked-tenant entitlement checks, existing RBAC capability boundaries, provider-boundary neutrality in top-level wording, current destructive confirmation patterns, current OperationRun start UX, and no new tables/enums/frameworks for readiness
Scale/Scope: one workspace-scoped onboarding workflow surface, one derived readiness composition, and focused onboarding/policy coverage only
UI / Surface Guardrail Plan
- Guardrail scope: changed surfaces
- Native vs custom classification summary: native Filament + shared primitives
- Shared-family relevance: status messaging, action links, badges, embedded diagnostics, navigation
- State layers in scope: page + workflow-step + derived summary
- Handling modes by drift class or surface: review-mandatory
- Repository-signal treatment: review-mandatory
- Special surface test profiles: standard-native-filament
- Required tests or manual smoke: functional-core
- Exception path and spread control: existing guided-workflow exception for
ManagedTenantOnboardingWizard; no new surface exemption - Active feature PR close-out entry: Guardrail
Shared Pattern & System Fit
- Cross-cutting feature marker: yes
- Systems touched:
ManagedTenantOnboardingWizard, onboarding landing/draft picker,OnboardingLifecycleService,OnboardingDraftStageResolver,ProviderConnectionSurfaceSummary,VerificationAssistViewModelBuilder,TenantRequiredPermissionsViewModelBuilder,OperationRunLinks - Shared abstractions reused:
OnboardingLifecycleService,OnboardingDraftStageResolver,ProviderConnectionSurfaceSummary,VerificationAssistViewModelBuilder,TenantRequiredPermissionsViewModelBuilder,OperationRunLinks,OperationUxPresenter,ProviderOperationStartResultPresenter - New abstraction introduced? why?: none; readiness stays a thin derived composition on the existing workflow surface
- Why the existing abstraction was sufficient or insufficient: existing services already own checkpoint progression, provider connection wording, permission freshness, verification diagnostics, and canonical run links; the missing piece is a single operator-facing composition and action prioritization
- Bounded deviation / spread control: provider-specific consent and permission names remain inside existing diagnostic detail and provider-owned next steps; top-level readiness copy stays platform-neutral, and any shared builder extension must stay additive and behavior-preserving for non-onboarding consumers while onboarding-specific prioritization remains page-local
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes
- Central contract reused: shared OperationRun UX layer via
OperationRunLinks,OperationUxPresenter, and the existing onboardingtenantlessOperationRunUrl(...)helper - Delegated UX behaviors: queued toast, dedupe-or-blocked messaging, canonical
Open operationlink labeling, tenant/workspace-safe run URL resolution, and terminal lifecycle notifications remain delegated to shared Ops-UX paths - Surface-owned behavior kept local: readiness wording, freshness explanation, and next-action prioritization inside the onboarding workflow
- Queued DB-notification policy: unchanged explicit opt-in; this slice does not add queued or running DB notifications
- Terminal notification path: central lifecycle mechanism already used by reused verification/bootstrap actions
- Exception path: none
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes
- Provider-owned seams: consent diagnostics, missing-permission detail, provider-specific remediation next steps, target-scope identity detail
- Platform-core seams: readiness summary, checkpoint progress, next-action labels, freshness messaging, workflow routing
- Neutral platform terms / contracts preserved:
provider connection,readiness,diagnostics,next action,freshness,onboarding step - Retained provider-specific semantics and why: Microsoft permission names and consent language stay inside existing verification assist and provider summary detail because the operator needs exact remediation instructions for the supported provider
- Bounded extraction or follow-up path: none; if a second provider appears later, revisit only the provider-owned detail seam rather than the workflow shell
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
- Persisted truth / proportionality: PASS — readiness remains derived from existing onboarding, provider connection, operation-run, and permission-posture truth; no new table, enum, or state family is planned.
- Read/write separation / destructive actions: PASS — this slice changes operator understanding on an existing wizard; existing cancel/delete/complete actions retain current confirmation, audit, and authorization rules.
- Graph contract path / DB-only render: PASS — render and Livewire hydration stay DB-only, reusing stored provider connection, verification, and permission-posture data with no new Graph calls.
- RBAC / isolation: PASS — existing workspace membership, linked-tenant entitlement, and
Capabilities::*gates remain authoritative; non-members and wrong-scope actors stay 404, capability-denied members stay 403. - Ops-UX / OperationRun link semantics: PASS — existing verification/bootstrap starts and run links continue to use shared OperationRun UX and canonical tenantless route helpers; no new run-start path is introduced.
- Provider boundary / shared pattern reuse: PASS — provider-neutral readiness remains top-level, Microsoft-specific details stay contextual, and existing shared builders/helpers are reused before any local deviation.
- Test governance: PASS — proof stays in fast-feedback feature/unit coverage using existing onboarding fixtures; no new browser or heavy-governance family is required.
- Global search / panel registration: N/A — this slice changes a Filament page, not a global-searchable resource or panel provider.
Test Governance Check
- Test purpose / classification by changed surface: Feature (wizard + landing/picker rendering and behavior) plus targeted Unit/Policy coverage for isolation semantics and existing freshness helper behavior where directly reused
- Affected validation lanes: fast-feedback
- Why this lane mix is the narrowest sufficient proof: the workflow is server-driven Filament/Livewire UI backed by existing models and policies, so feature tests can prove readiness composition, next-action precedence, and deny semantics without browser automation
- Narrowest proving command(s):
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ManagedTenantOnboardingWizardTest.php;cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Onboarding/OnboardingDraftPickerTest.php tests/Feature/Onboarding/OnboardingDraftAuthorizationTest.php;cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Policies/TenantOnboardingSessionPolicyTest.php tests/Unit/TenantRequiredPermissionsFreshnessTest.php - Fixture / helper / factory / seed / context cost risks: reuse existing onboarding draft, workspace membership, tenant membership, provider connection, and operation-run fixtures; avoid adding browser fixtures or new provider mocks
- Expensive defaults or shared helper growth introduced?: no; any new test helpers should stay onboarding-local
- Heavy-family additions, promotions, or visibility changes: none
- Surface-class relief / special coverage rule: standard-native-filament guided-workflow exception already exists; add feature assertions to cover the readiness summary on both landing and draft routes
- Closing validation and reviewer handoff: rerun the targeted onboarding wizard, draft-picker/authorization, and policy/freshness tests after implementation; reviewers should verify one primary next action, correct 404 vs 403 semantics, and no render-time outbound HTTP
- Budget / baseline / trend follow-up: none expected beyond ordinary feature-local upkeep
- Review-stop questions: Does the slice stay in fast-feedback? Did any new fixture force browser/heavy coverage? Did the implementation introduce a second readiness taxonomy or persisted truth?
- Escalation path: document-in-feature if a shared helper needs a tiny extension; reject-or-split if implementation tries to add new persistence/frameworks or browser-lane proof
- Active feature PR close-out entry: Guardrail
- Why no dedicated follow-up spec is needed: the planned proof extends already-existing onboarding suites and does not add a new recurring test cost center
Implementation Close-Out — 2026-04-25
- Guardrail result: keep. The implementation stayed inside the existing guided onboarding page, reused current lifecycle/stage, provider summary, verification assist, permission freshness, and OperationRun link paths, and did not add persistence, enums, a readiness taxonomy, or a cross-surface framework.
- Fast-feedback proof:
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ManagedTenantOnboardingWizardTest.php tests/Feature/Onboarding/OnboardingDraftPickerTest.php tests/Feature/Onboarding/OnboardingDraftAuthorizationTest.php tests/Unit/Policies/TenantOnboardingSessionPolicyTest.php tests/Unit/TenantRequiredPermissionsFreshnessTest.phppassed with 55 tests and 212 assertions. - Provider-boundary / lane-cost decision: keep. Provider-specific permission and consent detail remains secondary and provider-owned; top-level readiness wording stays platform-neutral. No browser, heavy-governance, new fixture family, or follow-up spec is required.
- Explicit defers retained: numeric completion score and cross-surface readiness reuse remain deferred; future consumers should reuse this derived onboarding truth rather than broaden this slice.
Project Structure
Documentation (this feature)
specs/240-tenant-onboarding-readiness/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── checklists/
│ └── requirements.md
├── contracts/
│ └── onboarding-readiness.openapi.yaml
└── tasks.md
Source Code (repository root)
apps/platform/
├── app/
│ ├── Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
│ ├── Models/TenantOnboardingSession.php
│ ├── Services/Intune/TenantRequiredPermissionsViewModelBuilder.php
│ ├── Services/Onboarding/
│ │ ├── OnboardingDraftStageResolver.php
│ │ └── OnboardingLifecycleService.php
│ ├── Support/OperationRunLinks.php
│ ├── Support/Providers/TargetScope/ProviderConnectionSurfaceSummary.php
│ └── Support/Verification/VerificationAssistViewModelBuilder.php
└── tests/
├── Feature/ManagedTenantOnboardingWizardTest.php
├── Feature/Onboarding/OnboardingDraftAuthorizationTest.php
├── Feature/Onboarding/OnboardingDraftPickerTest.php
├── Unit/Policies/TenantOnboardingSessionPolicyTest.php
└── Unit/TenantRequiredPermissionsFreshnessTest.php
Structure Decision: Single Laravel web application. This feature remains confined to the existing onboarding wizard/landing workflow, existing onboarding + provider support services, and focused onboarding/policy tests.
Complexity Tracking
No constitution violations are required for this feature. The plan explicitly avoids new persistence, abstractions, readiness enums, or cross-surface frameworks.
Proportionality Review
N/A — the plan intentionally keeps readiness derived and local to the existing onboarding workflow. No new persisted entity, abstraction layer, enum/status family, or taxonomy is proposed.
Phase 0 — Research (output: research.md)
See: /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/240-tenant-onboarding-readiness/research.md
Goals:
- Confirm the narrowest existing sources of truth for onboarding readiness, draft landing metadata, provider summary, permission freshness, and canonical operation links.
- Resolve the freshness question by reusing the existing 30-day permission freshness rule plus current connection-change and selected-connection-mismatch signals rather than introducing a new onboarding-specific threshold or persisted freshness model.
- Confirm that landing-route behavior remains the same surface (single-draft redirect or multi-draft picker) so readiness context is added without creating a second onboarding register.
Phase 1 — Design & Contracts (outputs: data-model.md, contracts/, quickstart.md)
See:
/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/240-tenant-onboarding-readiness/data-model.md/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/240-tenant-onboarding-readiness/contracts/onboarding-readiness.openapi.yaml/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/240-tenant-onboarding-readiness/quickstart.md
Design focus:
- Add one derived readiness composition on
ManagedTenantOnboardingWizardand the existing draft picker using current draft lifecycle, provider connection summary, verification assist, the existing 30-day permission freshness rule, and explicit "check has not run yet" guidance where no evidence exists. - Keep landing-route behavior intact: a single resumable draft still redirects to the route-bound draft; a multi-draft landing view gains compact readiness snippets next to existing metadata.
- Define next-action precedence from existing truth only: identify tenant → connect provider → grant consent/fix permissions → run or rerun verification → review bootstrap → complete onboarding.
- Keep permission and consent detail secondary and provider-owned; keep
Open operationand consent links canonical and shared. - Keep onboarding-specific readiness wording and action prioritization local to the onboarding workflow; if a shared provider or verification builder needs extension, keep the change additive and regression-safe for existing non-onboarding consumers.
- Defer numeric completion score and any support-diagnostic or trial/demo-specific projection to later specs that reuse the same derived onboarding truth.
- Do not add new tables, readiness enums, global resources, or provider-generic onboarding abstractions.
Phase 1 — Agent Context Update
After Phase 1 artifacts are generated, update Copilot context from the plan:
/Users/ahmeddarrazi/Documents/projects/wt-plattform/.specify/scripts/bash/update-agent-context.sh copilot
Phase 2 — Implementation Outline (tasks created in /speckit.tasks)
- Extend onboarding landing and draft rendering to surface a derived readiness summary, freshness, and one primary next action from existing services/helpers.
- Reuse
OnboardingLifecycleServicesnapshot truth,OnboardingDraftStageResolver,ProviderConnectionSurfaceSummary,VerificationAssistViewModelBuilder, andTenantRequiredPermissionsViewModelBuilderto map existing records into operator-facing copy. - Add compact readiness metadata to the multi-draft picker and route-bound resume context without creating a new onboarding index resource.
- Preserve existing consent, verification, bootstrap, operation-link, and destructive header actions; only change prioritization, grouping emphasis, and explanatory copy.
- Expand targeted feature and policy tests for readiness states, freshness/mismatch handling, landing summary behavior, and 404 vs 403 regressions.
Constitution Check (Post-Design)
Re-check result: PASS. Design artifacts keep readiness derived, DB-only at render time, workspace/tenant safe, Ops-UX compliant, and constrained to existing onboarding + provider foundations.