## Summary - add canonical managed-tenant onboarding draft routing with explicit draft identity and landing vs concrete draft behavior - implement draft lifecycle, authorization, attribution, picker UX, resume-stage resolution, and auditable cancel or completion semantics - add focused feature, unit, and browser coverage plus Spec 138 artifacts for the onboarding draft resume flow ## Validation - `vendor/bin/sail artisan test --compact tests/Feature/ManagedTenantOnboardingWizardTest.php tests/Feature/Audit/OnboardingDraftAuditTest.php tests/Feature/Onboarding/OnboardingDraftAccessTest.php tests/Feature/Onboarding/OnboardingDraftAuthorizationTest.php tests/Feature/Onboarding/OnboardingDraftLifecycleTest.php tests/Feature/Onboarding/OnboardingDraftMultiTabTest.php tests/Feature/Onboarding/OnboardingDraftPickerTest.php tests/Feature/Onboarding/OnboardingDraftRoutingTest.php tests/Feature/Onboarding/OnboardingRbacSemanticsTest.php tests/Feature/Onboarding/OnboardingVerificationClustersTest.php tests/Feature/Onboarding/OnboardingVerificationTest.php tests/Feature/Onboarding/OnboardingVerificationV1_5UxTest.php tests/Feature/Verification/VerificationReportViewerDbOnlyTest.php tests/Unit/Onboarding tests/Unit/VerificationReportSanitizerEvidenceKindsTest.php tests/Browser/OnboardingDraftRefreshTest.php tests/Browser/OnboardingDraftVerificationResumeTest.php` - passed: 69 tests, 251 assertions Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #167
113 lines
3.7 KiB
Markdown
113 lines
3.7 KiB
Markdown
# Data Model: Managed Tenant Onboarding Draft Identity & Resume Semantics
|
|
|
|
## Primary Entity: Onboarding Draft
|
|
|
|
### Backing Model
|
|
|
|
- Existing model: `App\Models\TenantOnboardingSession`
|
|
- Existing table: `managed_tenant_onboarding_sessions`
|
|
- UI language: `Onboarding draft`
|
|
|
|
## Ownership & Authorization Model
|
|
|
|
- The onboarding draft is a workspace-scoped workflow-coordination record, not a generic tenant-owned domain record.
|
|
- `workspace_id` is mandatory for every draft.
|
|
- `tenant_id` remains nullable under the constitution-approved onboarding exception because drafts can exist before tenant identification.
|
|
- Once `tenant_id` is attached, authorization must enforce both workspace entitlement and tenant entitlement for draft access.
|
|
- Before `tenant_id` is attached, workspace entitlement is sufficient.
|
|
|
|
## Entity Fields
|
|
|
|
### Existing or Required Core Fields
|
|
|
|
| Field | Type | Purpose |
|
|
|---|---|---|
|
|
| `id` | bigint | Stable draft identity used in canonical route binding |
|
|
| `workspace_id` | bigint | Workspace isolation boundary |
|
|
| `tenant_id` | bigint nullable | Managed tenant database record when identified |
|
|
| `entra_tenant_id` | string nullable | External tenant identity used before or during tenant materialization |
|
|
| `started_by_user_id` | bigint nullable | Attribution for who created the draft |
|
|
| `updated_by_user_id` | bigint nullable | Attribution for who last confirmed a change |
|
|
| `current_step` | string nullable | Diagnostic and audit marker only |
|
|
| `state` | json nullable | Confirmed non-secret draft state |
|
|
| `completed_at` | timestamp nullable | Marks the draft as completed |
|
|
| `cancelled_at` | timestamp nullable | Marks the draft as cancelled |
|
|
| `created_at` | timestamp | Created timestamp |
|
|
| `updated_at` | timestamp | Last persisted update timestamp |
|
|
|
|
### Recommended State Payload Keys
|
|
|
|
Confirmed draft state should continue to allow only non-secret, confirmed keys such as:
|
|
|
|
- `entra_tenant_id`
|
|
- `tenant_id`
|
|
- `tenant_name`
|
|
- `environment`
|
|
- `primary_domain`
|
|
- `notes`
|
|
- `provider_connection_id`
|
|
- `selected_provider_connection_id`
|
|
- `verification_operation_run_id`
|
|
- `verification_run_id`
|
|
- `bootstrap_operation_types`
|
|
- `bootstrap_operation_runs`
|
|
- `bootstrap_run_ids`
|
|
|
|
## Lifecycle Semantics
|
|
|
|
### Resumable
|
|
|
|
A draft is resumable when all of the following are true:
|
|
|
|
- It belongs to the current workspace.
|
|
- It is authorized for the current actor.
|
|
- It is not completed.
|
|
- It is not cancelled.
|
|
|
|
### Non-Resumable
|
|
|
|
A draft is non-resumable when any of the following are true:
|
|
|
|
- It is completed.
|
|
- It is cancelled.
|
|
- It is outside the current workspace.
|
|
- It is inaccessible due to authorization.
|
|
|
|
## Derived Projections
|
|
|
|
### Draft Stage
|
|
|
|
Derived from confirmed state, not only from `current_step`:
|
|
|
|
1. No identified tenant data: `identify`
|
|
2. Tenant identified but no provider connection selected: `connect-provider`
|
|
3. Provider connection selected but verification cannot proceed or is incomplete: `verify-access`
|
|
4. Verification complete but bootstrap pending: `bootstrap`
|
|
5. Bootstrap confirmed and ready for final review or activation: `review`
|
|
6. Completed: `completed`
|
|
7. Cancelled: `cancelled`
|
|
|
|
### Draft Summary Metadata
|
|
|
|
Used by the landing picker and header banner:
|
|
|
|
- Tenant display name
|
|
- External tenant identifier
|
|
- Environment
|
|
- Current stage label
|
|
- Started by display name
|
|
- Last updated by display name
|
|
- Last updated at
|
|
- Draft age
|
|
- Verification stale or blocked hint
|
|
|
|
## Sensitive Data Rule
|
|
|
|
The following values must never be stored in the draft payload for UI rehydration:
|
|
|
|
- Client secrets
|
|
- Raw credential material
|
|
- Temporary authorization tokens
|
|
- Any secret provider credential value
|
|
|
|
The draft may store references to related provider connections or verification runs, but not secrets. |