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
3.9 KiB
3.9 KiB
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\Tenantas the “Managed Tenant” concept. - Rationale: The admin panel tenancy, membership model, and most operational flows already key off
Tenant. - Alternatives considered:
- Introduce a new
ManagedTenantmodel/table. - Keep
Tenantas-is and build onboarding as “just another page”.
- Introduce a new
- 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)(wheretenant_idis the Entra tenant ID), and ensure Filament’s 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_idis unique and is force-set totenant_idinTenant::saving(). If we allow the sametenant_idacross workspaces,external_idmust NOT be set totenant_idanymore. Prefer a generated opaque stableexternal_id(UUID) and keeptenant_idstrictly as the business identifier. - Alternatives considered:
- Keep global uniqueness on
tenant_idand keep usingexternal_id = tenant_id.
- Keep global uniqueness on
- 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 Filament’s built-in tenant registration page (
tenantRegistration).
- Tenant-scoped Filament routes (
- 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(modulehealth_check) executed viaProviderConnectionHealthCheckJobas 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 inWorkspaceRoleCapabilityMap. - Rationale: The spec requires Owner+Manager; existing workspace capabilities don’t exactly match this (e.g.,
WORKSPACE_MANAGEis Owner-only). - Alternatives considered:
- Check workspace role strings (
owner/manager) directly. - Reuse an unrelated capability like
WORKSPACE_MEMBERSHIP_MANAGE.
- Check workspace role strings (
- 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/newredirect/admin/w/{workspace}/managed-tenants/onboardingredirect stub
- Rationale: FR-001 requires wizard-only entry and “not found” behavior.
Open Questions
- None. All technical unknowns required for planning are resolved.