--- 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 - [X] T001 Confirm Sail is running and DB is reachable using docker-compose.yml (command: `vendor/bin/sail up -d`) - [X] 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). - [X] T003 Add onboarding capability constant in app/Support/Auth/Capabilities.php - [X] T004 Add onboarding capability mapping for Owner+Manager in app/Services/Auth/WorkspaceRoleCapabilityMap.php - [X] T005 Implement Gate/Policy for onboarding authorization in app/Providers/AuthServiceProvider.php (enforce capabilities; no role-string checks) - [X] T006 [P] Create TenantOnboardingSession model in app/Models/TenantOnboardingSession.php - [X] T007 Create onboarding sessions migration in database/migrations/*_create_tenant_onboarding_sessions_table.php (unique workspace_id + tenant_id) - [X] 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) - [X] 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 - [X] 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. - [X] T011 [P] [US1] Add wizard page class in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (Filament v5 / Livewire v4) - [X] T012 [P] [US1] Add wizard view in resources/views/filament/pages/workspaces/managed-tenant-onboarding-wizard.blade.php - [X] 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 - [X] T014 [US1] Implement wizard mount + workspace loading in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (abort 404 for non-member, 403 for missing onboarding capability) - [X] 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`) - [X] 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 - [X] 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 - [X] T016 [US1] Persist/resume onboarding session in app/Models/TenantOnboardingSession.php (no secrets in state) - [X] T017 [US1] Add audit events for onboarding start/resume in app/Services/Audit/WorkspaceAuditLogger.php (or existing audit service) and call from wizard actions - [X] T018 [P] [US1] Add happy-path tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (owner/manager can start; tenant created; session created) - [X] T019 [P] [US1] Add negative auth tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (non-member gets 404; member without capability gets 403) - [X] T020 [P] [US1] Add idempotency tests in tests/Feature/ManagedTenantOnboardingWizardTest.php (repeat step does not create duplicates) - [X] 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) - [X] 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) - [X] T021 [US1] Remove tenant registration from app/Providers/Filament/AdminPanelProvider.php (drop `->tenantRegistration(...)`) - [X] T022 [US1] Remove `/admin/register-tenant` route from routes/web.php (must behave as not found) - [X] 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) - [X] T024 [US1] Remove RegisterTenant references in app/Filament/Pages/ChooseTenant.php and app/Filament/Pages/Workspaces/ManagedTenantsLanding.php - [X] 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. - [X] T026 [US2] Implement Step 2 connection selection in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (auto-select default connection; allow switching) - [X] 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) - [X] T028 [US2] Persist selected connection id in app/Models/TenantOnboardingSession.php `state` (non-secret) - [X] T029 [US2] Implement “Start verification” action using app/Services/Providers/ProviderOperationStartGate.php with operation type `provider.connection.check` - [X] 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) - [X] T030 [US2] Ensure verification enqueues app/Jobs/ProviderConnectionHealthCheckJob.php and stores `operation_run_id` in onboarding session state - [X] T031 [US2] Add “View run” navigation to app/Filament/Resources/OperationRunResource.php (link from wizard action notification) - [X] T032 [P] [US2] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for connection default selection + switching - [X] T033 [P] [US2] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for verification run creation + job dispatch (Bus::fake) - [X] 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. - [X] T035 [US3] Implement session resume logic in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (load by workspace_id + tenant_id; shared resumability) - [X] T036 [US3] Implement Step gating in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (cannot complete until verification succeeded) - [X] T037 [US3] Implement optional bootstrap actions in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (start operations listed in app/Services/Providers/ProviderOperationRegistry.php) - [X] T038 [US3] Persist bootstrap `operation_run_id`s in app/Models/TenantOnboardingSession.php `state` - [X] T039 [US3] Implement completion: set tenant status `active`, set onboarding session `completed_at`, redirect to tenant dashboard (app/Filament/Pages/TenantDashboard.php) - [X] T040 [P] [US3] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for resume by different authorized actor - [X] T041 [P] [US3] Add tests in tests/Feature/ManagedTenantOnboardingWizardTest.php for completion and tenant status transition `pending` → `active` - [X] 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 - [X] 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 - [X] 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) - [X] 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/* - [X] T046 Run formatter on touched files (command: `vendor/bin/sail bin pint --dirty`) - [X] T047 Run targeted test suite for onboarding (command: `vendor/bin/sail artisan test --compact tests/Feature/ManagedTenantOnboardingWizardTest.php`) ### Post-spec hardening (Filament-native UX) - [X] 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) - [X] 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] T018–T020 can be written in parallel (distinct test cases). ### US2 parallel work - [P] T032–T034 can be written in parallel (selection tests vs run tests vs secret-safety tests). ### US3 parallel work - [P] T040–T042 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.