---

description: "Tasks for Managed Tenant Onboarding Wizard V1 (Enterprise) (073)"
---

# Tasks: Managed Tenant Onboarding Wizard V1 (Enterprise)

**Input**: Design documents from `specs/073-unified-managed-tenant-onboarding-wizard/`
**Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/

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

---

## Phase 1: Setup (Shared Infrastructure)

**Purpose**: Confirm baseline environment is ready for implementing and testing runtime behavior changes.

- [x] T001 Confirm Sail is running using docker-compose.yml (command: `vendor/bin/sail up -d`)
- [x] T002 Run a baseline test subset 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 (capabilities, resumable session model, tenant status semantics).

- [x] T003 Define wizard capabilities (per-step/per-action) in app/Support/Auth/Capabilities.php
- [x] T004 [P] Map wizard capabilities to roles (least privilege) in app/Services/Auth/WorkspaceRoleCapabilityMap.php
- [x] T005 Implement server-side authorization checks for wizard actions in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (no role-string checks)
- [x] T006 Ensure Tenant lifecycle supports `draft|onboarding|active|archived` in app/Models/Tenant.php
- [x] T007 Update onboarding session schema to match data-model (safe state only) in app/Models/TenantOnboardingSession.php
- [x] T008 Update onboarding session migration constraints for idempotency in database/migrations/2026_02_04_090010_update_tenant_onboarding_sessions_constraints.php
- [x] T009 [P] Add foundational capability + tenant lifecycle tests in tests/Feature/Onboarding/OnboardingFoundationsTest.php

**Checkpoint**: Foundation ready — user story implementation can begin.

---

## Phase 3: User Story 1 — Single entry point onboarding (Priority: P1) 🎯 MVP

**Goal**: Provide `/admin/onboarding` as the sole onboarding entry point, redirect to workspace chooser if none selected, and implement Step 1 idempotent identification with strict 404/403 semantics.

**Independent Test**: Visit `/admin/onboarding` with and without a selected workspace, complete Step 1, and verify exactly one tenant/session is created and cross-workspace attempts behave as 404.

### Tests (write first)

- [x] T010 [P] [US1] Add entry-point routing tests in tests/Feature/Onboarding/OnboardingEntryPointTest.php
- [x] T011 [P] [US1] Add RBAC semantics tests (404 non-member, disabled UI + 403 action) in tests/Feature/Onboarding/OnboardingRbacSemanticsTest.php
- [x] T012 [P] [US1] Add idempotency + cross-workspace isolation tests in tests/Feature/Onboarding/OnboardingIdentifyTenantTest.php

### Implementation

- [x] T013 [US1] Make `/admin/onboarding` the canonical wizard route in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (set slug; remove workspace route parameter dependency)
- [x] T014 [US1] Resolve the current workspace from session context in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (redirect when missing; 404 when non-member)
- [x] T015 [US1] Keep page visible for members without capability (disable controls + tooltip) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T016 [US1] Implement Step 1 inputs per spec (tenant name, environment, Entra Tenant ID, optional domain/notes) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T017 [US1] Implement Step 1 idempotent upsert + onboarding session resume (deny-as-not-found if tenant exists in another workspace) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T018 [US1] Ensure no pre-activation tenant-scoped links are generated in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php

### Remove legacy entry points (must be true 404, no redirects)

- [x] T019 [US1] Remove tenant registration surface from app/Providers/Filament/AdminPanelProvider.php (drop `->tenantRegistration(...)` if present)
- [x] T020 [US1] Remove/404 legacy routes in routes/web.php (`/admin/new`, `/admin/register-tenant`, `/admin/managed-tenants/onboarding`)
- [x] T021 [P] [US1] Add legacy route regression tests in tests/Feature/Onboarding/OnboardingLegacyRoutesTest.php

**Checkpoint**: US1 complete — `/admin/onboarding` is canonical, legacy entry points are 404, and Step 1 is safe + idempotent.

---

## Phase 4: User Story 2 — Provider connection selection/creation (Priority: P2)

**Goal**: Allow selecting an existing workspace-owned provider connection or creating a new one, without ever re-displaying secrets.

**Independent Test**: Complete Step 2 in both modes (existing vs new), verify the onboarding session stores only non-secret state, and verify the provider connection is workspace-scoped and bound to the managed tenant by default.

### Tests (write first)

- [x] T022 [P] [US2] Add connection selection/creation tests in tests/Feature/Onboarding/OnboardingProviderConnectionTest.php
- [x] T023 [P] [US2] Add secret-safety regression tests in tests/Feature/Onboarding/OnboardingSecretSafetyTest.php

### Implementation

- [x] T024 [US2] Implement workspace-owned ProviderConnection schema changes in database/migrations/2026_02_04_090020_make_provider_connections_workspace_owned.php
- [x] T025 [US2] Update ProviderConnection model relationships + scoping in app/Models/ProviderConnection.php
- [x] T026 [US2] Update ProviderConnection authorization for workspace scope in app/Policies/ProviderConnectionPolicy.php
- [x] T027 [US2] Update ProviderConnection admin resource scoping in app/Filament/Resources/ProviderConnectionResource.php
- [x] T028 [US2] Update Step 2 schema + persistence (no secrets in onboarding session state) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T029 [US2] Store provider_connection_id in onboarding session safe state in app/Models/TenantOnboardingSession.php

**Checkpoint**: US2 complete — Provider connections are workspace-owned, default-bound to one tenant, and secrets are never re-shown.

---

## Phase 5: User Story 3 — Verification + tenantless run viewing + activation (Priority: P3)

**Goal**: Start verification as an `OperationRun`, render DB-only reports with correct status mapping, and support tenantless viewing at `/admin/operations/{run}` without requiring selected workspace or tenant context.

**Independent Test**: Start verification from the wizard, dedupe active runs, open `/admin/operations/{run}` without a selected workspace, and enforce membership-based 404 semantics.

### Tests (write first)

- [x] T030 [P] [US3] Add tenantless run viewer access tests in tests/Feature/Operations/TenantlessOperationRunViewerTest.php
- [x] T031 [P] [US3] Add verification start + dedupe tests in tests/Feature/Onboarding/OnboardingVerificationTest.php
- [x] T032 [P] [US3] Add owner-only activation + override audit tests in tests/Feature/Onboarding/OnboardingActivationTest.php
- [x] T052 [P] [US3] Add Graph contract registry coverage tests (organization + service principal permission probes) in tests/Unit/GraphContractRegistryOnboardingProbesTest.php

### Implementation — tenantless operation run viewer

- [x] T033 [US3] Add OperationRun workspace scoping fields + idempotency indexes in database/migrations/2026_02_04_090030_add_workspace_id_to_operation_runs_table.php
- [x] T034 [US3] Update OperationRun model for workspace relationship + nullable tenant_id in app/Models/OperationRun.php
- [x] T035 [US3] Update run identity/dedupe logic for tenantless runs in app/Services/OperationRunService.php
- [x] T036 [US3] Exempt `/admin/operations/{run}` from forced workspace selection in app/Http/Middleware/EnsureWorkspaceSelected.php
- [x] T037 [US3] Prevent tenant auto-selection side effects for `/admin/operations/{run}` in app/Support/Middleware/EnsureFilamentTenantSelected.php
- [x] T038 [US3] Authorize viewing runs by workspace membership (non-member → 404) in app/Policies/OperationRunPolicy.php
- [x] T039 [US3] Implement tenantless `/admin/operations/{run}` viewer page + route with membership-based 404 semantics (app/Filament/Pages/Operations/TenantlessOperationRunViewer.php, routes/web.php)

### Implementation — verification + report + activation

- [x] T053 [US3] Register onboarding verification probe endpoints in config/graph_contracts.php (organization + service principal permission lookups)
- [x] T054 [US3] Refactor verification probe calls to resolve endpoints via GraphContractRegistry (no ad-hoc Graph paths; fail safe if contract missing) in app/Services/Graph/MicrosoftGraphClient.php and app/Services/Providers/ProviderGateway.php
- [x] T040 [US3] Implement Step 3 start verification (OperationRun + queued job) with 403 on capability denial in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T041 [US3] Implement active-run dedupe (queued/running) and persist run IDs in app/Models/TenantOnboardingSession.php
- [x] T042 [US3] Implement DB-only “Refresh” and status mapping (Blocked/Needs attention/Ready) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T055 [US3] Render a stored verification report in Step 3 (clear empty-state + secondary “Open run details” link) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T056 [US3] Enhance tenantless operation run viewer UI (context + failures + timestamps + refresh) in app/Filament/Pages/Operations/TenantlessOperationRunViewer.php and resources/views/filament/pages/operations/tenantless-operation-run-viewer.blade.php
- [x] T057 [P] [US3] Add UI regression tests for wizard report and tenantless viewer details in tests/Feature/Onboarding/OnboardingVerificationTest.php and tests/Feature/Operations/TenantlessOperationRunViewerTest.php
- [x] T043 [US3] Ensure “View run” links are tenantless `/admin/operations/{run}` via app/Support/OperationRunLinks.php
- [x] T044 [US3] Implement optional bootstrap actions (per-action capability gating) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T045 [US3] Implement activation gating (owner-only) + blocked override reason + audit in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- [x] T046 [US3] Add required audit events (stable action IDs; no secrets) in app/Services/Audit/WorkspaceAuditLogger.php

**Checkpoint**: US3 complete — verification is observable + deduped, runs are viewable tenantlessly, and activation is safe + audited.

---

## Phase 6: Polish & Cross-Cutting Concerns

**Purpose**: Centralize badge semantics, harden RBAC-UX, and run formatting/tests.

- [x] T047 Add centralized badge mapping for onboarding/verification statuses in app/Support/Badges/Domains/
- [x] T048 [P] Add badge mapping tests in tests/Feature/Badges/OnboardingBadgeSemanticsTest.php
- [x] T049 [P] Add RBAC regression coverage for wizard actions in tests/Feature/Rbac/OnboardingWizardUiEnforcementTest.php
- [x] T050 Run formatter on touched files using composer.json scripts (command: `vendor/bin/sail bin pint --dirty`)
- [x] T051 Run targeted test suites using phpunit.xml (command: `vendor/bin/sail artisan test --compact tests/Feature/Onboarding tests/Feature/Operations`)

**Verification note**: Full suite re-run post-fixes is green (984 passed, 5 skipped).

---

## Dependencies & Execution Order

### Phase Dependencies

- Setup (Phase 1) → Foundational (Phase 2) → US1 (Phase 3) → US2 (Phase 4) → US3 (Phase 5) → Polish (Phase 6)

### User Story Dependencies

- US1 (P1) depends on Phase 2 only.
- US2 (P2) depends on US1 (managed tenant + onboarding session in place).
- US3 (P3) depends on US2 (provider connection exists) and adds OperationRun viewer changes.

### Parallel Opportunities

- [P] tasks can be executed in parallel (different files, minimal coupling).
- Within each story: tests can be authored in parallel before implementation.

---

## Parallel Example: US1

Run in parallel:

- T010 (entry point routing tests) in tests/Feature/Onboarding/OnboardingEntryPointTest.php
- T011 (RBAC semantics tests) in tests/Feature/Onboarding/OnboardingRbacSemanticsTest.php
- T012 (idempotency tests) in tests/Feature/Onboarding/OnboardingIdentifyTenantTest.php

---

## Implementation Strategy

### MVP First

MVP scope is US1 only: `/admin/onboarding` canonical entry point + Step 1 idempotent identification + strict 404/403 semantics + legacy routes 404 + tests.
