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

12 KiB
Raw Blame History

description
Tasks for Unified Managed Tenant Onboarding Wizard (073)

Tasks: Unified Managed Tenant Onboarding Wizard (073)

Input: Design documents from specs/073-unified-managed-tenant-onboarding-wizard/

Tests: Required (Pest). Use vendor/bin/sail artisan test --compact ....

Phase 1: Setup

  • T001 Confirm Sail is running and DB is reachable using docker-compose.yml (command: vendor/bin/sail up -d)
  • T002 Confirm baseline tests pass for the branch using phpunit.xml and tests/ (command: vendor/bin/sail artisan test --compact)

Phase 2: Foundational (Blocking Prerequisites)

Purpose: Shared primitives required by all user stories (authz, data model, safety semantics).

  • T003 Add onboarding capability constant in app/Support/Auth/Capabilities.php
  • T004 Add onboarding capability mapping for Owner+Manager in app/Services/Auth/WorkspaceRoleCapabilityMap.php
  • T005 Implement Gate/Policy for onboarding authorization in app/Providers/AuthServiceProvider.php (enforce capabilities; no role-string checks)
  • T006 [P] Create TenantOnboardingSession model in app/Models/TenantOnboardingSession.php
  • T007 Create onboarding sessions migration in database/migrations/*_create_tenant_onboarding_sessions_table.php (unique workspace_id + tenant_id)
  • T008 Create tenant workspace binding migration in database/migrations/*_enforce_tenant_workspace_binding.php (ensure tenants.workspace_id is NOT NULL + FK; ensure tenants.tenant_id remains globally unique; deny cross-workspace duplicates)
  • T009 Verify tenant routing key strategy for v1: keep existing Filament tenant route-key stable (do NOT change external_id strategy in this feature); add a regression test that /admin/t/{tenant} continues to resolve the intended managed tenant
  • T010 [P] Add foundational authorization + data-model tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (capability known, mapping correct, migrations applied)

Checkpoint: Foundational complete — user story work can begin.


Phase 3: User Story 1 — Start Managed Tenant onboarding (Priority: P1) 🎯 MVP

Goal: Start or resume a workspace-scoped onboarding wizard and create exactly one Managed Tenant per global-unique tenant_id (Entra tenant ID), bound to exactly one workspace.

Independent Test: Start onboarding in an empty workspace and complete “Identify Managed Tenant”; assert exactly one tenant exists and a session is created/resumed.

  • T011 [P] [US1] Add wizard page class in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (Filament v5 / Livewire v4)
  • T012 [P] [US1] Add wizard view in resources/views/filament/pages/workspaces/managed-tenant-onboarding-wizard.blade.php
  • T013 [US1] Register wizard route in routes/web.php at /admin/w/{workspace}/managed-tenants/onboarding with ensure-workspace-member middleware and 404 semantics for non-members
  • T014 [US1] Implement wizard mount + workspace loading in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (abort 404 for non-member, 403 for missing onboarding capability)
  • T015 [US1] Implement Step 1 “Identify Managed Tenant” upsert in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (transactional; idempotent by workspace_id + tenant_id; tenant status pending)
  • T015b [US1] Enforce cross-workspace uniqueness in Step 1: if a tenant with the same tenant_id exists in a different workspace, deny-as-not-found (404) and do not create/update anything
  • T015c [US1] Membership bootstrap: after tenant upsert, ensure the initiating user has a Managed Tenant membership of role owner (create if missing); never allow tenant to end up with zero owners
  • T016 [US1] Persist/resume onboarding session in app/Models/TenantOnboardingSession.php (no secrets in state)
  • T017 [US1] Add audit events for onboarding start/resume in app/Services/Audit/WorkspaceAuditLogger.php (or existing audit service) and call from wizard actions
  • T018 [P] [US1] Add happy-path tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (owner/manager can start; tenant created; session created)
  • T019 [P] [US1] Add negative auth tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (non-member gets 404; member without capability gets 403)
  • T020 [P] [US1] Add idempotency tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (repeat step does not create duplicates)
  • T020b [P] [US1] Add tests asserting membership bootstrap: newly created tenant has exactly one owner membership for the initiator; attempting to remove/demote the last owner is blocked (can be a minimal service/policy-level assertion)
  • T020c [P] [US1] Add tests asserting cross-workspace protection: if tenant_id exists under another workspace, the wizard returns 404 and does not reveal the existence of that tenant

Remove legacy entry points (required by FR-001)

  • T021 [US1] Remove tenant registration from app/Providers/Filament/AdminPanelProvider.php (drop ->tenantRegistration(...))
  • T022 [US1] Remove /admin/register-tenant route from routes/web.php (must behave as not found)
  • T023 [US1] Replace legacy onboarding redirects with 404 in routes/web.php (/admin/managed-tenants, /admin/managed-tenants/onboarding, /admin/new, workspace onboarding redirect stub)
  • T024 [US1] Remove RegisterTenant references in app/Filament/Pages/ChooseTenant.php and app/Filament/Pages/Workspaces/ManagedTenantsLanding.php
  • T025 [P] [US1] Add regression tests in tests/Feature/ManagedTenantOnboardingWizardTest.php asserting legacy endpoints return 404 (no redirects)

Checkpoint: US1 complete — wizard is the only entry point; onboarding start is safe + idempotent.


Phase 4: User Story 2 — Configure a connection and verify access (Priority: P2)

Goal: Attach or create a Provider Connection and start verification as an OperationRun without leaking secrets.

Independent Test: Select/create connection, start verification, assert an OperationRun is created and job is dispatched; assert no secret material is returned.

  • T026 [US2] Implement Step 2 connection selection in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (auto-select default connection; allow switching)
  • T027 [US2] Implement connection creation path in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php using app/Models/ProviderConnection.php and app/Services/Providers/CredentialManager.php (never display stored secrets)
  • T028 [US2] Persist selected connection id in app/Models/TenantOnboardingSession.php state (non-secret)
  • T029 [US2] Implement “Start verification” action using app/Services/Providers/ProviderOperationStartGate.php with operation type provider.connection.check
  • T029b [US2] Enforce/verify dedupe: clicking “Start verification” twice while an active run exists must return the active OperationRun (no second run created); add a focused test (Bus::fake + assert single run)
  • T030 [US2] Ensure verification enqueues app/Jobs/ProviderConnectionHealthCheckJob.php and stores operation_run_id in onboarding session state
  • T031 [US2] Add “View run” navigation to app/Filament/Resources/OperationRunResource.php (link from wizard action notification)
  • T032 [P] [US2] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for connection default selection + switching
  • T033 [P] [US2] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for verification run creation + job dispatch (Bus::fake)
  • T034 [P] [US2] Add secret-safety tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (no secret fields appear in response/session/run failure summary)

Checkpoint: US2 complete — verification is observable via OperationRun and secrets are safe.


Phase 5: User Story 3 — Resume and complete onboarding (Priority: P3)

Goal: Resume an onboarding session, run optional bootstrap actions, and complete onboarding to activate the tenant.

Independent Test: Start onboarding, leave incomplete, resume as a different authorized owner/manager, complete verification + bootstrap, then mark tenant active.

  • T035 [US3] Implement session resume logic in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (load by workspace_id + tenant_id; shared resumability)
  • T036 [US3] Implement Step gating in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (cannot complete until verification succeeded)
  • T037 [US3] Implement optional bootstrap actions in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (start operations listed in app/Services/Providers/ProviderOperationRegistry.php)
  • T038 [US3] Persist bootstrap operation_run_ids in app/Models/TenantOnboardingSession.php state
  • T039 [US3] Implement completion: set tenant status active, set onboarding session completed_at, redirect to tenant dashboard (app/Filament/Pages/TenantDashboard.php)
  • T040 [P] [US3] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for resume by different authorized actor
  • T041 [P] [US3] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for completion and tenant status transition pendingactive
  • T042 [P] [US3] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for bootstrap run creation (one OperationRun per selected action)

Checkpoint: US3 complete — onboarding is resumable and completes safely.


Phase 6: Polish & Cross-Cutting Concerns

  • T043 Add Managed Tenant status badge mapping via BadgeCatalog/BadgeRenderer in app/Support/Badges/* (BADGE-001) and add mapping test in tests/Feature/Badges/TenantStatusBadgeTest.php
  • T044 Verify/extend audit coverage for FR-016: use stable audit action IDs (enum/registry), ensure redaction, and add at least one concrete feature test asserting audit rows for onboarding start + verification start (no secrets in payload)
  • T045 Verify last-owner protections cover both workspace + tenant memberships; extend policies if needed in app/Policies/* and add regression tests in tests/Feature/Rbac/*
  • T046 Run formatter on touched files (command: vendor/bin/sail bin pint --dirty)
  • T047 Run targeted test suite for onboarding (command: vendor/bin/sail artisan test --compact tests/Feature/ManagedTenantOnboardingWizardTest.php)

Post-spec hardening (Filament-native UX)

  • T048 Refactor onboarding page to a Filament-native Wizard schema (replace header-action modals + step cards; persist per-step progress; keep strict RBAC and existing action methods)
  • T049 Fix tenant identify UX: entering an existing tenant GUID must not surface a raw 404 modal; bind legacy unscoped tenants to the current workspace when safely inferable and add a regression test

Dependencies & Execution Order

User Story completion order

  1. US1 (P1) depends on Phase 2 only.
  2. US2 (P2) depends on US1 (tenant/session + wizard scaffold).
  3. US3 (P3) depends on US2 (verification state + run linking).

Dependency graph

  • Phase 1 → Phase 2 → US1 → US2 → US3 → Polish

Parallel execution examples

US1 parallel work

  • [P] T011 and T012 can be implemented in parallel (page class vs blade view).
  • [P] T018T020 can be written in parallel (distinct test cases).

US2 parallel work

  • [P] T032T034 can be written in parallel (selection tests vs run tests vs secret-safety tests).

US3 parallel work

  • [P] T040T042 can be written in parallel (resume tests vs completion tests vs bootstrap tests).

Implementation Strategy (MVP)

  • MVP scope is US1 only: wizard-only entry point + idempotent tenant identification + resumable session skeleton + required authorization semantics + tests.