- Ensure manual OperationRun inserts set workspace_id when events are disabled - Align ManagedTenantOnboardingWizard tests with /admin/onboarding semantics - Keep TenantFactory/creating hooks safe for make() vs create()
12 KiB
| 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.
- T001 Confirm Sail is running using docker-compose.yml (command:
vendor/bin/sail up -d) - 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).
- T003 Define wizard capabilities (per-step/per-action) in app/Support/Auth/Capabilities.php
- T004 [P] Map wizard capabilities to roles (least privilege) in app/Services/Auth/WorkspaceRoleCapabilityMap.php
- T005 Implement server-side authorization checks for wizard actions in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (no role-string checks)
- T006 Ensure Tenant lifecycle supports
draft|onboarding|active|archivedin app/Models/Tenant.php - T007 Update onboarding session schema to match data-model (safe state only) in app/Models/TenantOnboardingSession.php
- T008 Update onboarding session migration constraints for idempotency in database/migrations/2026_02_04_090010_update_tenant_onboarding_sessions_constraints.php
- 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)
- T010 [P] [US1] Add entry-point routing tests in tests/Feature/Onboarding/OnboardingEntryPointTest.php
- T011 [P] [US1] Add RBAC semantics tests (404 non-member, disabled UI + 403 action) in tests/Feature/Onboarding/OnboardingRbacSemanticsTest.php
- T012 [P] [US1] Add idempotency + cross-workspace isolation tests in tests/Feature/Onboarding/OnboardingIdentifyTenantTest.php
Implementation
- T013 [US1] Make
/admin/onboardingthe canonical wizard route in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (set slug; remove workspace route parameter dependency) - T014 [US1] Resolve the current workspace from session context in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (redirect when missing; 404 when non-member)
- T015 [US1] Keep page visible for members without capability (disable controls + tooltip) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- T016 [US1] Implement Step 1 inputs per spec (tenant name, environment, Entra Tenant ID, optional domain/notes) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- 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
- 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)
- T019 [US1] Remove tenant registration surface from app/Providers/Filament/AdminPanelProvider.php (drop
->tenantRegistration(...)if present) - T020 [US1] Remove/404 legacy routes in routes/web.php (
/admin/new,/admin/register-tenant,/admin/managed-tenants/onboarding) - 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)
- T022 [P] [US2] Add connection selection/creation tests in tests/Feature/Onboarding/OnboardingProviderConnectionTest.php
- T023 [P] [US2] Add secret-safety regression tests in tests/Feature/Onboarding/OnboardingSecretSafetyTest.php
Implementation
- T024 [US2] Implement workspace-owned ProviderConnection schema changes in database/migrations/2026_02_04_090020_make_provider_connections_workspace_owned.php
- T025 [US2] Update ProviderConnection model relationships + scoping in app/Models/ProviderConnection.php
- T026 [US2] Update ProviderConnection authorization for workspace scope in app/Policies/ProviderConnectionPolicy.php
- T027 [US2] Update ProviderConnection admin resource scoping in app/Filament/Resources/ProviderConnectionResource.php
- T028 [US2] Update Step 2 schema + persistence (no secrets in onboarding session state) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- 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)
- T030 [P] [US3] Add tenantless run viewer access tests in tests/Feature/Operations/TenantlessOperationRunViewerTest.php
- T031 [P] [US3] Add verification start + dedupe tests in tests/Feature/Onboarding/OnboardingVerificationTest.php
- T032 [P] [US3] Add owner-only activation + override audit tests in tests/Feature/Onboarding/OnboardingActivationTest.php
- T052 [P] [US3] Add Graph contract registry coverage tests (organization + service principal permission probes) in tests/Unit/GraphContractRegistryOnboardingProbesTest.php
Implementation — tenantless operation run viewer
- T033 [US3] Add OperationRun workspace scoping fields + idempotency indexes in database/migrations/2026_02_04_090030_add_workspace_id_to_operation_runs_table.php
- T034 [US3] Update OperationRun model for workspace relationship + nullable tenant_id in app/Models/OperationRun.php
- T035 [US3] Update run identity/dedupe logic for tenantless runs in app/Services/OperationRunService.php
- T036 [US3] Exempt
/admin/operations/{run}from forced workspace selection in app/Http/Middleware/EnsureWorkspaceSelected.php - T037 [US3] Prevent tenant auto-selection side effects for
/admin/operations/{run}in app/Support/Middleware/EnsureFilamentTenantSelected.php - T038 [US3] Authorize viewing runs by workspace membership (non-member → 404) in app/Policies/OperationRunPolicy.php
- 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
- T053 [US3] Register onboarding verification probe endpoints in config/graph_contracts.php (organization + service principal permission lookups)
- 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
- T040 [US3] Implement Step 3 start verification (OperationRun + queued job) with 403 on capability denial in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- T041 [US3] Implement active-run dedupe (queued/running) and persist run IDs in app/Models/TenantOnboardingSession.php
- T042 [US3] Implement DB-only “Refresh” and status mapping (Blocked/Needs attention/Ready) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- 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
- 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
- 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
- T043 [US3] Ensure “View run” links are tenantless
/admin/operations/{run}via app/Support/OperationRunLinks.php - T044 [US3] Implement optional bootstrap actions (per-action capability gating) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- T045 [US3] Implement activation gating (owner-only) + blocked override reason + audit in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- 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.
- T047 Add centralized badge mapping for onboarding/verification statuses in app/Support/Badges/Domains/
- T048 [P] Add badge mapping tests in tests/Feature/Badges/OnboardingBadgeSemanticsTest.php
- T049 [P] Add RBAC regression coverage for wizard actions in tests/Feature/Rbac/OnboardingWizardUiEnforcementTest.php
- T050 Run formatter on touched files using composer.json scripts (command:
vendor/bin/sail bin pint --dirty) - 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.