# Implementation Plan: Managed Tenant Onboarding Wizard UI (v2) (069) **Branch**: `069-tenant-onboarding-wizard-v2` | **Date**: 2026-01-31 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `specs/069-tenant-onboarding-wizard-v2/spec.md` **Note**: This plan is produced by `/speckit.plan`. It intentionally stops before `tasks.md` (that is `/speckit.tasks`). ## Summary Build a ProviderConnection-first onboarding experience for Managed Tenants: - A guided 5-step wizard for first-time setup. - A persistent task board (visible starting Step 4) for reruns, recovery, and operational status. - Evidence-driven status rendering (step/task status comes from stored evidence, not ephemeral job output). - Collaboration support (session locking + takeover/handoff) with strict RBAC semantics. Key design decisions are captured in [research.md](./research.md). ## Terminology & Routing - **Managed Tenant** maps to `App\Models\Tenant` (current Filament tenant scope). - Feature UI lives in the **tenant plane** (`/admin/t/{tenant}`), not the platform plane (`/system`). - Concurrency keys use `tenant_id` meaning the internal tenant primary key (`tenants.id`). ## Phasing ### Phase 1 (this spec’s implementation target) - Introduce onboarding session + evidence storage. - Define a task catalog that maps onboarding tasks to existing provider operations and/or new OperationRun-backed operations. - Implement wizard + task board pages with evidence-driven badges and safe failure summaries. - Enforce concurrency rule: one active run per `(tenant_id, task_type)`. ### Phase 2 (explicitly out-of-scope for Phase 1) - Real-time collaborative editing (presence indicators, typing, etc.). - Multi-provider onboarding (beyond Microsoft-first ProviderConnection patterns already in the repo). ## Technical Context **Language/Version**: PHP 8.4.x (project targets Laravel 12) **Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Tailwind CSS v4 **Storage**: PostgreSQL (use JSONB for evidence payloads where appropriate) **Testing**: Pest v4 (Feature tests + Livewire/Filament component tests) **Target Platform**: Containerized web app (Sail local dev; Dokploy staging/prod) **Project Type**: Web application (Laravel monolith) **Performance Goals**: 95% of “start task” actions confirm queued within 2 seconds (aligns with SC-001) **Constraints**: No secrets in UI/logs/run records; no external calls at render time; OperationRun-backed jobs are enqueue-only from UI **Scale/Scope**: Multi-tenant admin UI; repeatable provider-backed tasks; frequent reruns; strong isolation between tenants ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first: onboarding statuses are derived from stored evidence (last observed), not from snapshots or transient job state. - Read/write separation: provider-affecting actions are only triggered explicitly by the user (task actions), with audit logging and tests. - Graph contract path: any new Graph calls remain behind `GraphClientInterface` and contract registry (`config/graph_contracts.php`). - Deterministic capabilities: onboarding actions reference the canonical capability registry (no raw strings, no role checks in feature code). - RBAC-UX: tenant isolation via deny-as-not-found for non-members; member-but-missing-capability is forbidden; enforce server-side for every mutation/operation start. - Run observability: every onboarding task start creates/reuses an `OperationRun` and enqueues work; Monitoring pages remain DB-only. - Automation: run idempotency + active-run dedupe enforced at DB level; handle 429/503 with retry/backoff in jobs. - Data minimization: evidence payloads are whitelisted/sanitized; failures store reason codes + sanitized messages only. - Badge semantics (BADGE-001): step/task status uses `BadgeCatalog`/`BadgeRenderer` (no ad-hoc mappings). No constitution violations are required for this feature. ## Project Structure ### Documentation (this feature) ```text specs/069-tenant-onboarding-wizard-v2/ ├── plan.md # This file (/speckit.plan command output) ├── research.md # Phase 0 output (/speckit.plan command) ├── data-model.md # Phase 1 output (/speckit.plan command) ├── quickstart.md # Phase 1 output (/speckit.plan command) ├── contracts/ # Phase 1 output (/speckit.plan command) └── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan) ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ ├── Pages/ │ └── Resources/ ├── Http/ │ └── Controllers/ ├── Jobs/ ├── Models/ ├── Policies/ ├── Services/ └── Support/ database/ └── migrations/ resources/ ├── css/ ├── js/ └── views/ routes/ └── web.php tests/ ├── Feature/ └── Unit/ ``` **Structure Decision**: Laravel monolith. Wizard/task board implemented as Filament Pages + actions; provider calls run in queued jobs tracked by `OperationRun`. ## Complexity Tracking No constitution violations are required for this feature.