# Implementation Plan: Managed Tenant Onboarding Wizard v1 **Branch**: `069-managed-tenant-onboarding-wizard` | **Date**: 2026-01-31 | **Spec**: [spec.md](spec.md) **Input**: Feature specification from [specs/069-managed-tenant-onboarding-wizard/spec.md](spec.md) ## Summary Implement a tenant-plane onboarding wizard under `/admin` that: - renders DB-only (no outbound HTTP during render/mount) - persists resumable onboarding sessions (non-secret payload) - triggers verification via enqueue-only `OperationRun` records - enforces RBAC-UX semantics (non-member 404; member missing capability 403 + disabled UI) - redirects/removes legacy onboarding entry points (notably `/admin/new`) ## Technical Context **Language/Version**: PHP 8.4.x **Primary Dependencies**: Laravel 12, Filament v5, Livewire v4 **Storage**: PostgreSQL (Sail) **Testing**: Pest v4 **Target Platform**: Web app (tenant-plane `/admin`, platform-plane `/system`) **Project Type**: Laravel monolith **Performance Goals**: - Wizard step render: DB-only - Operation starts: authorize + create/reuse `OperationRun` + enqueue only **Constraints**: - No outbound HTTP during render/mount (DB-only render). - Verification/health checks must be enqueue-only and observable via `OperationRun`. - Capability checks must use the canonical registry `App\\Support\\Auth\\Capabilities` (no raw strings). - Credential secrets must be encrypted at rest and must never be displayed back to the user. **Scale/Scope**: Admin workflow; correctness + auditability prioritized. ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first: Wizard renders from stored state only (tenant fields + last run summaries), not live Graph. - Graph contract path: Any Graph verification work (when implemented) must go through the existing Graph abstraction and contract registry. - RBAC-UX: tenant-plane `/admin` only; non-member access is 404; member missing capability is 403; UI disabled state is not authorization. - Run observability: all verification actions create/reuse an `OperationRun` and enqueue work; no synchronous external calls. - Data minimization: onboarding session payload excludes secrets; failures are stable codes + sanitized messages. Status: PASS. ## Project Structure ### Documentation (this feature) ```text specs/069-managed-tenant-onboarding-wizard/ ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md └── contracts/ └── onboarding-wizard.md ``` ### Source Code (repository root) ```text app/ ├── Filament/ # Filament resources/pages ├── Models/ # Eloquent models ├── Providers/Filament/ # Panel providers ├── Services/ # OperationRun + provider gates + auth resolvers └── Support/ # RBAC helpers, middleware, capability registry bootstrap/ └── providers.php # Laravel 11+ provider registration config/ └── graph_contracts.php database/ └── migrations/ routes/ └── web.php tests/ ├── Feature/ └── Unit/ ``` **Structure Decision**: Laravel monolith; Filament v5 discovery conventions for pages/resources. ## Phase 0 — Outline & Research Output: [research.md](research.md) All NEEDS CLARIFICATION items: none remaining. ## Phase 1 — Design & Contracts Outputs: - [data-model.md](data-model.md) - [contracts/onboarding-wizard.md](contracts/onboarding-wizard.md) - [quickstart.md](quickstart.md) Agent context update required after these artifacts: - Run `.specify/scripts/bash/update-agent-context.sh copilot` Constitution re-check (post-design): PASS. ## Phase 2 — Task Planning (produced by `/speckit.tasks`) Planned task groups: 1. Data layer: `tenant_onboarding_sessions` migration + model. 2. Wizard UI: tenant-plane Filament page with 5 steps (DB-only render). 3. RBAC mapping (canonical registry): - Start/resume onboarding (spec: `managed_tenants.create`) → `Capabilities::TENANT_MANAGE` - Manage onboarding fields/credentials (spec: `managed_tenants.manage`) → `Capabilities::TENANT_MANAGE` - View tenant + wizard (spec: `managed_tenants.view`) → `Capabilities::TENANT_VIEW` - Enqueue provider connection checks / verification runs (spec: `operations.run`) → `Capabilities::PROVIDER_RUN` - Enqueue inventory sync (optional) → `Capabilities::TENANT_INVENTORY_SYNC_RUN` 4. Operations: enqueue-only verification action(s) backed by `OperationRunService`. 5. Legacy routes: redirect `/admin/new` to the existing “Choose tenant” entry point (`/admin/choose-tenant`). 6. Tests (Pest): resume/dedupe, RBAC 404/403 behavior, and run creation/dedupe. ## Complexity Tracking N/A — no constitution violations require justification. | Violation | Why Needed | Simpler Alternative Rejected Because | |-----------|------------|-------------------------------------| | [e.g., 4th project] | [current need] | [why 3 projects insufficient] | | [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |