TenantAtlas/specs/073-unified-managed-tenant-onboarding-wizard/plan.md
ahmido b6343d5c3a feat: unified managed tenant onboarding wizard (#88)
Implements workspace-scoped managed tenant onboarding wizard (Filament v5 / Livewire v4) with strict RBAC (404/403 semantics), resumable sessions, provider connection selection/creation, verification OperationRun, and optional bootstrap. Removes legacy onboarding entrypoints and adds Pest coverage + spec artifacts (073).

## Summary
<!-- Kurz: Was ändert sich und warum? -->

## Spec-Driven Development (SDD)
- [ ] Es gibt eine Spec unter `specs/<NNN>-<feature>/`
- [ ] Enthaltene Dateien: `plan.md`, `tasks.md`, `spec.md`
- [ ] Spec beschreibt Verhalten/Acceptance Criteria (nicht nur Implementation)
- [ ] Wenn sich Anforderungen während der Umsetzung geändert haben: Spec/Plan/Tasks wurden aktualisiert

## Implementation
- [ ] Implementierung entspricht der Spec
- [ ] Edge cases / Fehlerfälle berücksichtigt
- [ ] Keine unbeabsichtigten Änderungen außerhalb des Scopes

## Tests
- [ ] Tests ergänzt/aktualisiert (Pest/PHPUnit)
- [ ] Relevante Tests lokal ausgeführt (`./vendor/bin/sail artisan test` oder `php artisan test`)

## Migration / Config / Ops (falls relevant)
- [ ] Migration(en) enthalten und getestet
- [ ] Rollback bedacht (rückwärts kompatibel, sichere Migration)
- [ ] Neue Env Vars dokumentiert (`.env.example` / Doku)
- [ ] Queue/cron/storage Auswirkungen geprüft

## UI (Filament/Livewire) (falls relevant)
- [ ] UI-Flows geprüft
- [ ] Screenshots/Notizen hinzugefügt

## Notes
<!-- Links, Screenshots, Follow-ups, offene Punkte -->

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.fritz.box>
Reviewed-on: #88
2026-02-03 17:30:15 +00:00

164 lines
8.8 KiB
Markdown

# Implementation Plan: Unified Managed Tenant Onboarding Wizard (073)
**Branch**: `073-unified-managed-tenant-onboarding-wizard` | **Date**: 2026-02-03 | **Spec**: specs/073-unified-managed-tenant-onboarding-wizard/spec.md
**Input**: Feature specification from `specs/073-unified-managed-tenant-onboarding-wizard/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.
## Summary
Deliver a single, resumable onboarding wizard for Managed Tenants that: (1) identifies/upserts a managed tenant within the current workspace, (2) attaches or configures a Provider Connection, (3) runs verification asynchronously as an `OperationRun` with sanitized outcomes, and (4) optionally kicks off bootstrap operations.
Implementation approach: reuse existing primitives (`App\Models\Tenant`, Provider Connections, `provider.connection.check` operation type, workspace + tenant isolation middleware, canonical capability registries) and replace legacy tenant registration/redirect entry points with a single workspace-scoped wizard route.
## Technical Context
<!--
ACTION REQUIRED: Replace the content in this section with the technical details
for the project. The structure here is presented in advisory capacity to guide
the iteration process.
-->
**Language/Version**: PHP 8.4.x (Composer constraint: `^8.2`)
**Primary Dependencies**: Laravel 12, Filament 5, Livewire 4+, Pest 4, Sail 1.x
**Storage**: PostgreSQL (Sail) + SQLite in tests where applicable
**Testing**: Pest (via `vendor/bin/sail artisan test`)
**Target Platform**: Web app (Sail for local dev; container-based deploy on Linux)
**Project Type**: Web application (Laravel monolith)
**Performance Goals**: Onboarding UI renders DB-only; all Graph calls occur in queued work tracked by `OperationRun`; avoid N+1 via eager loading for any list/detail.
**Constraints**: Tenant isolation (404 vs 403 semantics); no secret material ever returned to the UI/logs; idempotent run-start and onboarding session resume; destructive-like actions require confirmation.
**Scale/Scope**: Workspace-scoped onboarding; expected low volume but high correctness/safety requirements.
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
GATE RESULT: PASS (no planned constitution violations).
- Inventory-first: onboarding writes only tenant metadata + configuration pointers; no inventory/snapshot side effects.
- Read/write separation: onboarding creates/updates records and starts operations; all mutating actions are authorized, audited, and tested.
- Graph contract path: verification uses existing `GraphClientInterface` methods (e.g., `getOrganization()`), and runs only in queued jobs.
- Deterministic capabilities: use `App\Support\Auth\Capabilities` + `WorkspaceRoleCapabilityMap`; add a dedicated onboarding capability granted to Owner+Manager.
- RBAC-UX semantics: workspace membership enforced via `ensure-workspace-member`; tenant membership enforced via `EnsureFilamentTenantSelected` / `DenyNonMemberTenantAccess` with deny-as-not-found (404). Missing capability returns 403.
- Destructive confirmation: any archive/delete/credential-rotation actions involved in onboarding must be `->action(...)->requiresConfirmation()`.
- Run observability: verification + optional bootstrap actions start via `OperationRun` and enqueue only; monitoring pages remain DB-only.
- Data minimization: onboarding session stores only non-secret fields; run failures store reason codes + sanitized messages.
- BADGE-001: introduce/extend Managed Tenant status badges via `BadgeCatalog` domain mapping (no per-page mapping).
## Project Structure
### Documentation (this feature)
```text
specs/073-unified-managed-tenant-onboarding-wizard/
├── 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)
<!--
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
for this feature. Delete unused options and expand the chosen structure with
real paths (e.g., apps/admin, packages/something). The delivered plan must
not include Option labels.
-->
```text
app/
├── Filament/
│ ├── Pages/
│ │ └── Workspaces/
│ │ ├── ManagedTenantsLanding.php
│ │ └── (new) ManagedTenantOnboardingWizard.php
│ └── Pages/Tenancy/
│ └── RegisterTenant.php # legacy entry point to remove/disable
├── Http/Controllers/
│ └── TenantOnboardingController.php # legacy admin-consent helper; evaluate usage
├── Jobs/
│ └── ProviderConnectionHealthCheckJob.php # verification via OperationRun
├── Models/
│ ├── Tenant.php
│ ├── ProviderConnection.php
│ └── (new) TenantOnboardingSession.php
└── Services/
├── Auth/
│ ├── WorkspaceCapabilityResolver.php
│ └── WorkspaceRoleCapabilityMap.php
├── Providers/
│ ├── ProviderOperationRegistry.php
│ └── ProviderGateway.php
└── Graph/
└── GraphClientInterface.php
database/migrations/
├── (new) *_add_workspace_scoped_unique_tenant_id.php
└── (new) *_create_tenant_onboarding_sessions_table.php
routes/web.php
tests/Feature/
└── (new) ManagedTenantOnboardingWizardTest.php
```
**Structure Decision**: Laravel web application (monolith). Onboarding wizard is a Filament page mounted on a workspace-scoped route under `/admin/w/{workspace}/...` (no tenant context required to start).
## Complexity Tracking
> **Fill ONLY if Constitution Check has violations that must be justified**
| 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] |
No constitution violations are anticipated for this feature.
## Phase 0 — Outline & Research (complete)
Outputs:
- `research.md`: decisions + rationale + alternatives (no unresolved clarifications).
Key research conclusions:
- Reuse `App\Models\Tenant` as “Managed Tenant” (no new base concept), but introduce `pending` status for the onboarding lifecycle.
- Replace legacy onboarding/registration routes (`/admin/register-tenant`, redirects under `/admin/managed-tenants/*`) with a single workspace-scoped onboarding wizard.
- Use existing provider verification operation type (`provider.connection.check`) executed via `ProviderConnectionHealthCheckJob` with `OperationRun` tracking.
## Phase 1 — Design & Contracts (complete)
Outputs:
- `data-model.md`: entities, fields, relationships, validation, state transitions.
- `contracts/*`: documented HTTP routes + action contracts (OpenAPI-style where applicable).
- `quickstart.md`: dev notes, env vars, how to run tests.
Design highlights:
- Data model
- Tenants: change status lifecycle to include `pending`, ensure `workspace_id` is NOT NULL + FK, and enforce global uniqueness of `tenant_id` (Entra tenant ID) bound to exactly one workspace.
- Onboarding sessions: new table/model for resumable state (strictly non-secret) keyed by `(workspace_id, tenant_id)`.
- Authorization
- Introduce a workspace capability for onboarding (e.g., `workspace_managed_tenant.onboard`) and map it to Owner+Manager via `WorkspaceRoleCapabilityMap`.
- Enforce server-side authorization for every mutation and operation-start; 404 for non-members and cross-workspace access; 403 for members missing capability.
- Runs
- Verification is a queued `OperationRun` using `provider.connection.check`.
- Optional bootstrap actions become separate `OperationRun` types (only if they exist in the ProviderOperationRegistry).
## Phase 2 — Implementation Plan (to be executed by /speckit.tasks)
This plan intentionally stops before creating `tasks.md`.
Proposed sequencing for tasks:
1) Introduce `TenantOnboardingSession` model + migration, and add workspace-scoped uniqueness for tenants.
2) Implement `ManagedTenantOnboardingWizard` page mounted at `/admin/w/{workspace}/managed-tenants/onboarding`.
3) Wire verification start to existing `ProviderConnectionHealthCheckJob` / `provider.connection.check` operation.
4) Remove/disable legacy entry points (`RegisterTenant`, redirect routes) and ensure “not found” behavior.
5) Add Pest feature tests for: 404 vs 403 semantics, idempotency, resumability, and sanitized run outcomes.