TenantAtlas/specs/073-unified-managed-tenant-onboarding-wizard/research.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

63 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Research — Unified Managed Tenant Onboarding Wizard (073)
This document resolves planning unknowns and records key implementation decisions.
## Decisions
### 1) Managed Tenant model = existing `Tenant`
- **Decision:** Treat the existing `App\Models\Tenant` as the “Managed Tenant” concept.
- **Rationale:** The admin panel tenancy, membership model, and most operational flows already key off `Tenant`.
- **Alternatives considered:**
- Introduce a new `ManagedTenant` model/table.
- Keep `Tenant` as-is and build onboarding as “just another page”.
- **Why rejected:** A second tenant-like model would duplicate authorization, routing, and operational conventions.
### 2) Workspace-scoped uniqueness + stable route key
- **Decision:** Enforce uniqueness by `(workspace_id, tenant_id)` (where `tenant_id` is the Entra tenant ID), and ensure Filaments route tenant key stays globally unique.
- **Rationale:** The feature spec explicitly defines the uniqueness key, and cross-workspace safety requires first-class scoping.
- **Implementation note:** Today `tenants.external_id` is unique and is force-set to `tenant_id` in `Tenant::saving()`. If we allow the same `tenant_id` across workspaces, `external_id` must NOT be set to `tenant_id` anymore. Prefer a generated opaque stable `external_id` (UUID) and keep `tenant_id` strictly as the business identifier.
- **Alternatives considered:**
- Keep global uniqueness on `tenant_id` and keep using `external_id = tenant_id`.
- **Why rejected:** Conflicts with the clarified uniqueness key and complicates “deny-as-not-found” behavior via DB constraint errors.
### 3) Wizard route location = workspace-scoped (`/admin/w/{workspace}/...`)
- **Decision:** Mount onboarding at a workspace-scoped route: `/admin/w/{workspace}/managed-tenants/onboarding`.
- **Rationale:** This path is explicitly exempted from forced tenant selection in `EnsureFilamentTenantSelected`, allowing onboarding before a tenant exists.
- **Alternatives considered:**
- Tenant-scoped Filament routes (`/admin/t/{tenant}/...`).
- Reusing Filaments built-in tenant registration page (`tenantRegistration`).
- **Why rejected:** Tenant-scoped routes require a tenant to exist/selected; built-in registration is a legacy entry point we must remove.
### 4) Verification implementation = existing provider operation (`provider.connection.check`)
- **Decision:** Use `provider.connection.check` (module `health_check`) executed via `ProviderConnectionHealthCheckJob` as the onboarding verification run.
- **Rationale:** It already uses `OperationRun`, writes sanitized outcomes, and performs Graph calls off-request.
- **Alternatives considered:**
- New onboarding-specific operation type.
- **Why rejected:** Adds duplication without a clear benefit for v1.
### 5) Authorization surface = workspace capability (Owner+Manager)
- **Decision:** Add a dedicated workspace capability for onboarding (e.g., `workspace_managed_tenant.onboard`) and grant it to workspace Owner and Manager in `WorkspaceRoleCapabilityMap`.
- **Rationale:** The spec requires Owner+Manager; existing workspace capabilities dont exactly match this (e.g., `WORKSPACE_MANAGE` is Owner-only).
- **Alternatives considered:**
- Check workspace role strings (`owner/manager`) directly.
- Reuse an unrelated capability like `WORKSPACE_MEMBERSHIP_MANAGE`.
- **Why rejected:** Constitution forbids role-string checks in feature code; reusing unrelated capability broadens authorization implicitly.
### 6) Legacy entry points = removed/404 (no redirects)
- **Decision:** Remove/disable these entry points and ensure 404 behavior:
- `/admin/register-tenant` (Filament registration page)
- `/admin/managed-tenants*` legacy redirects
- `/admin/new` redirect
- `/admin/w/{workspace}/managed-tenants/onboarding` redirect stub
- **Rationale:** FR-001 requires wizard-only entry and “not found” behavior.
## Open Questions
- None. All technical unknowns required for planning are resolved.