TenantAtlas/specs/073-unified-managed-tenant-onboarding-wizard/research.md
Ahmed Darrazi 7b0a383182 feat: unified managed tenant onboarding wizard
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).
2026-02-03 18:27:39 +01:00

3.9 KiB
Raw Blame History

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.