150 lines
9.1 KiB
Markdown
150 lines
9.1 KiB
Markdown
# Implementation Plan: Managed Tenant Onboarding Draft Identity & Resume Semantics
|
|
|
|
**Branch**: `138-managed-tenant-onboarding-draft-identity` | **Date**: 2026-03-13 | **Spec**: [specs/138-managed-tenant-onboarding-draft-identity/spec.md](spec.md)
|
|
**Input**: Feature specification from `specs/138-managed-tenant-onboarding-draft-identity/spec.md`
|
|
|
|
## Summary
|
|
|
|
Harden the managed tenant onboarding wizard around explicit draft identity, canonical draft routing, deterministic DB-backed resume semantics, and enterprise-safe lifecycle handling.
|
|
|
|
The implementation reuses `TenantOnboardingSession` as the persisted onboarding draft backbone, adds explicit draft-route semantics, replaces resume heuristics with data-derived draft loading, introduces an onboarding landing or picker experience with explicit summary access, formalizes resumable versus non-resumable draft behavior, and adds browser-level regression coverage for refresh, multi-draft flows, and activation-guard persistence.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15
|
|
**Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Laravel Sail, Pest v4, PHPUnit v12
|
|
**Storage**: PostgreSQL via Laravel migrations and JSON-backed state on `managed_tenant_onboarding_sessions`
|
|
**Testing**: Pest feature, unit, Livewire, and browser tests via `vendor/bin/sail artisan test --compact`
|
|
**Target Platform**: Laravel web application with Filament admin pages and workspace-scoped authorization
|
|
**Project Type**: Web application
|
|
**Performance Goals**: Draft landing and draft-load routes remain DB-only at render time; resume-step derivation remains constant-time from confirmed persisted data; refresh must not trigger new remote verification work
|
|
**Constraints**: No secret rehydration; no new inline remote work during page render; non-members and cross-workspace requests remain deny-as-not-found; in-scope members lacking onboarding capability remain `403`; completed and cancelled drafts remain non-editable; confirmation is required for destructive lifecycle actions
|
|
**Scale/Scope**: Cross-cutting onboarding change touching routing, wizard initialization, draft persistence, authorization, audit logging, and browser regression coverage
|
|
|
|
### Filament v5 Implementation Notes
|
|
|
|
- **Livewire v4.0+ compliance**: Maintained. The managed tenant onboarding wizard remains a Livewire-backed Filament page and stays compatible with Livewire v4.
|
|
- **Provider registration location**: No new panel is introduced. Existing panel providers remain registered in `bootstrap/providers.php`.
|
|
- **Global search rule**: This feature does not introduce a new globally searchable resource. Existing global-search behavior remains unchanged.
|
|
- **Destructive actions**: Any new cancel-draft or terminate-draft controls must execute through confirmed Filament actions with server-side authorization.
|
|
- **Asset strategy**: No new Filament assets are planned. Existing deployment practice still includes `php artisan filament:assets`, but this feature does not add new asset registrations.
|
|
- **Testing plan**: Add focused feature or Livewire tests for landing and draft routes, unit tests for resume-step derivation and draft-query helpers, and mandatory browser tests for hard refresh and multi-draft selection.
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before implementation begins. Re-check after design changes.*
|
|
|
|
- Inventory-first: PASS. The feature hardens onboarding flow semantics and does not change inventory ownership.
|
|
- Read/write separation: PASS. Draft state persists only at explicit confirmation boundaries instead of keystroke autosave.
|
|
- Graph contract path: PASS. No new Graph call path is introduced.
|
|
- Deterministic capabilities: PASS. Access remains routed through canonical workspace and onboarding capability checks.
|
|
- Scope & ownership clarification: PASS WITH EXPLICIT EXCEPTION. `managed_tenant_onboarding_sessions` use the constitution-approved workflow exception for nullable `tenant_id`; workspace scope remains primary and tenant entitlement applies once a tenant is attached.
|
|
- Workspace isolation: PASS. Draft discovery and access remain scoped to the current workspace and fail closed on mismatch.
|
|
- Tenant isolation: PASS. Draft-linked tenant references remain validated against workspace context.
|
|
- RBAC-UX 404/403 semantics: PASS. Non-members and out-of-scope actors remain 404; established in-scope members without onboarding capability remain 403.
|
|
- Destructive confirmation standard: PASS WITH WORK. Any cancel-draft action must use `->requiresConfirmation()` plus server-side authorization.
|
|
- Ops-UX: PASS. Verification and bootstrap operations keep existing `OperationRun` semantics and are not moved to render-time execution.
|
|
- UI naming: PASS WITH WORK. Operator copy must consistently refer to `Onboarding draft`, `Resume onboarding draft`, and `Start new onboarding`.
|
|
- Filament UI action surface contract: PASS WITH WORK. The landing route requires a draft-selection surface with clear actions and safe empty states.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/138-managed-tenant-onboarding-draft-identity/
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
├── contracts/
|
|
│ └── onboarding-draft-resume.openapi.yaml
|
|
└── tasks.md
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
app/
|
|
├── Filament/
|
|
│ └── Pages/Workspaces/ManagedTenantOnboardingWizard.php
|
|
├── Http/
|
|
│ ├── Controllers/
|
|
│ │ └── TenantOnboardingController.php
|
|
│ └── Middleware/
|
|
│ └── EnsureWorkspaceSelected.php
|
|
├── Models/
|
|
│ ├── Tenant.php
|
|
│ └── TenantOnboardingSession.php
|
|
├── Policies/
|
|
├── Services/
|
|
│ ├── Audit/
|
|
│ └── Verification/
|
|
└── Support/
|
|
├── Auth/
|
|
└── Ui/
|
|
|
|
database/
|
|
├── factories/
|
|
└── migrations/
|
|
|
|
routes/
|
|
└── web.php
|
|
|
|
tests/
|
|
├── Browser/
|
|
├── Feature/
|
|
│ ├── Onboarding/
|
|
│ └── Audit/
|
|
└── Unit/
|
|
└── Onboarding/
|
|
```
|
|
|
|
**Structure Decision**: Keep the current Laravel and Filament structure. The existing onboarding page remains the primary UI surface; draft identity, route resolution, and resume derivation are extracted into small dedicated helpers or services rather than creating a second wizard stack.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|-----------|------------|-------------------------------------|
|
|
| N/A | N/A | N/A |
|
|
|
|
## Phase 0 — Research (complete)
|
|
|
|
- Output: [specs/138-managed-tenant-onboarding-draft-identity/research.md](research.md)
|
|
- Selected the hybrid model: explicit draft identity in URL, DB-backed confirmed state as source of truth, data-derived wizard resume.
|
|
- Rejected heuristic-only resume, creator-only draft visibility, autosave, and edit locking for v1.
|
|
- Confirmed current code hotspots: `ManagedTenantOnboardingWizard` currently auto-resumes only when one incomplete session exists and computes start step from live state instead of explicit draft-route identity.
|
|
|
|
## Phase 1 — Design & Contracts (complete)
|
|
|
|
- Output: [specs/138-managed-tenant-onboarding-draft-identity/data-model.md](data-model.md)
|
|
- Output: [specs/138-managed-tenant-onboarding-draft-identity/quickstart.md](quickstart.md)
|
|
- Output: [specs/138-managed-tenant-onboarding-draft-identity/contracts/onboarding-draft-resume.openapi.yaml](contracts/onboarding-draft-resume.openapi.yaml)
|
|
|
|
### Post-design Constitution Re-check
|
|
|
|
- PASS: Confirmed-state durability is preserved without autosaving transient edits.
|
|
- PASS: Workspace-scoped resume remains deny-as-not-found on mismatch, while in-scope capability denial remains 403.
|
|
- PASS WITH WORK: Draft cancellation and non-resumable handling require explicit policy and confirmed actions.
|
|
- PASS WITH WORK: Browser-level tests are mandatory because the trust gap is driven by real refresh behavior.
|
|
|
|
## Phase 2 — Implementation Planning
|
|
|
|
`tasks.md` covers:
|
|
|
|
- Route and model groundwork for explicit draft identity and lifecycle.
|
|
- Landing, redirect, picker, and canonical draft-route semantics.
|
|
- Data-derived resume logic, orientation banner behavior, and explicit summary or detail access from the picker.
|
|
- Explicit non-resumable handling, attribution, cancel rules, and refresh-safe activation-guard persistence.
|
|
- Feature, unit, and browser coverage for `404` versus `403`, refresh, multi-draft, multi-operator, and activation-guard behavior.
|
|
|
|
### Contract Implementation Note
|
|
|
|
- The contract describes internal route and action semantics for onboarding draft selection, loading, creation, update, cancellation, and completion.
|
|
- Existing Filament page handlers and route definitions may satisfy the contract as long as they preserve the documented authorization, resume, audit, and fail-closed semantics.
|
|
|
|
### Deployment Sequencing Note
|
|
|
|
- Schema changes, if required, remain additive and reversible.
|
|
- Draft lifecycle backfill or normalization must not run inside schema migrations unless it is purely deterministic and side-effect-free.
|
|
- Browser and focused feature coverage should pass before any rollout of the route switch from landing-only to canonical draft URLs. |