# 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/onboarding` landing 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 onboarding `tenantlessOperationRunUrl(...)` helper
- **Delegated UX behaviors**: queued toast, dedupe-or-blocked messaging, canonical `Open operation` link 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.php` passed 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)

```text
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)

```text
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 `ManagedTenantOnboardingWizard` and 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 operation` and 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 `OnboardingLifecycleService` snapshot truth, `OnboardingDraftStageResolver`, `ProviderConnectionSurfaceSummary`, `VerificationAssistViewModelBuilder`, and `TenantRequiredPermissionsViewModelBuilder` to 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.
