## Summary - add canonical onboarding lifecycle and checkpoint fields plus optimistic locking versioning for managed tenant onboarding drafts - introduce centralized onboarding lifecycle and mutation services and route wizard mutations through version-checked writes - convert Verify Access and Bootstrap into live checkpoint-driven wizard states with conditional polling and updated browser/feature/unit coverage - add Spec Kit artifacts for feature 140, including spec, plan, tasks, research, data model, quickstart, checklist, and logical contract ## Validation - branch was committed and pushed cleanly - focused tests and formatting were updated during implementation work - full validation was not re-run as part of this final git/PR step ## Notes - base branch: `dev` - feature branch: `140-onboarding-lifecycle-operation-checkpoints-concurrency-mvp` - outstanding follow-up items, if any, remain tracked in `specs/140-onboarding-lifecycle-operation-checkpoints-concurrency-mvp/tasks.md` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #169
129 lines
6.2 KiB
Markdown
129 lines
6.2 KiB
Markdown
# Data Model: Onboarding Lifecycle, Operation Checkpoints & Concurrency MVP
|
|
|
|
## Entity: TenantOnboardingSession
|
|
|
|
Existing persisted workflow record for managed tenant onboarding drafts.
|
|
|
|
### Fields
|
|
|
|
| Field | Type | Required | Notes |
|
|
|---|---|---|---|
|
|
| `id` | bigint | yes | Primary key |
|
|
| `workspace_id` | foreign key | yes | Workspace ownership and authorization boundary |
|
|
| `tenant_id` | foreign key nullable | conditional | May remain null before tenant identification, per constitution exception |
|
|
| `entra_tenant_id` | string | yes | Current draft identity key for resumable uniqueness |
|
|
| `current_step` | string nullable | no | Existing UI-oriented step breadcrumb; no longer canonical workflow truth |
|
|
| `state` | json nullable | no | Detailed persisted step data and run references |
|
|
| `started_by_user_id` | foreign key nullable | no | Draft creator |
|
|
| `updated_by_user_id` | foreign key nullable | no | Last mutating actor |
|
|
| `completed_at` | timestamp nullable | no | Terminal historical marker |
|
|
| `cancelled_at` | timestamp nullable | no | Terminal historical marker |
|
|
| `version` | bigint or integer | yes | Starts at `1`, increments on every relevant successful mutation |
|
|
| `lifecycle_state` | controlled string or enum | yes | Canonical workflow state |
|
|
| `current_checkpoint` | controlled string or enum nullable | no | Governing checkpoint for forward progress |
|
|
| `last_completed_checkpoint` | controlled string or enum nullable | no | Last satisfied checkpoint |
|
|
| `reason_code` | string nullable | no | Machine-readable lifecycle precision |
|
|
| `blocking_reason_code` | string nullable | no | Machine-readable explicit blocker |
|
|
| `created_at` | timestamp | yes | Existing audit chronology |
|
|
| `updated_at` | timestamp | yes | Existing audit chronology |
|
|
|
|
### Relationships
|
|
|
|
- Belongs to `Workspace`
|
|
- Belongs to `Tenant` when identified
|
|
- Belongs to `startedByUser`
|
|
- Belongs to `updatedByUser`
|
|
- References relevant verification and bootstrap `OperationRun` records through IDs stored in `state`
|
|
|
|
### Validation Rules
|
|
|
|
- `version >= 1`
|
|
- `lifecycle_state` must be one of the controlled lifecycle values
|
|
- `current_checkpoint` and `last_completed_checkpoint` must be null or one of the controlled checkpoint values
|
|
- `blocking_reason_code` must be null unless the workflow is actually blocked from forward progress
|
|
- `completed_at` and `cancelled_at` remain mutually exclusive terminal markers
|
|
- Terminal records (`completed_at` or `cancelled_at` set) are non-editable
|
|
|
|
## Entity: OnboardingLifecycleState
|
|
|
|
Controlled value set used for canonical workflow truth.
|
|
|
|
### Values
|
|
|
|
| Value | Meaning |
|
|
|---|---|
|
|
| `draft` | No active governing checkpoint run and not yet ready for activation |
|
|
| `verifying` | Relevant verification run is queued or running |
|
|
| `action_required` | Operator intervention is required before safe progression |
|
|
| `bootstrapping` | One or more selected bootstrap runs are queued or running |
|
|
| `ready_for_activation` | All gating conditions are satisfied and the workflow awaits final activation |
|
|
| `completed` | Activation succeeded and the draft is historical |
|
|
| `cancelled` | Draft was intentionally cancelled and is historical |
|
|
|
|
## Entity: OnboardingCheckpoint
|
|
|
|
Controlled checkpoint precision used for progression and UI state.
|
|
|
|
### Values
|
|
|
|
| Value | Meaning |
|
|
|---|---|
|
|
| `identify` | Tenant identity or workspace-scoped start state |
|
|
| `connect_provider` | Provider selection or connection management checkpoint |
|
|
| `verify_access` | Verify Access checkpoint |
|
|
| `bootstrap` | Optional bootstrap checkpoint |
|
|
| `complete_activate` | Final activation checkpoint |
|
|
|
|
## Entity: OnboardingReasonCode
|
|
|
|
Machine-readable precision for non-terminal workflow state.
|
|
|
|
### Expected starter values
|
|
|
|
- `verification_blocked_permissions`
|
|
- `verification_failed`
|
|
- `provider_connection_changed`
|
|
- `verification_result_stale`
|
|
- `bootstrap_failed`
|
|
- `bootstrap_partial_failure`
|
|
- `owner_activation_required`
|
|
|
|
This list is intentionally controlled and should be extended centrally rather than spread through page code.
|
|
|
|
## Entity: RelevantCheckpointRun
|
|
|
|
Derived relationship between a draft and the `OperationRun` records that currently govern progression.
|
|
|
|
### Verification invariants
|
|
|
|
- The verification run must match the currently selected provider connection.
|
|
- A queued or running verification run implies `lifecycle_state = verifying`.
|
|
- A terminal verification run only allows progression when it is current for the selected connection and satisfies readiness conditions.
|
|
|
|
### Bootstrap invariants
|
|
|
|
- Bootstrap run references remain stored in `state` as selected run metadata.
|
|
- One or more queued or running relevant bootstrap runs imply `lifecycle_state = bootstrapping`.
|
|
- Any blocking bootstrap failure moves the workflow to `action_required`.
|
|
|
|
## State Transition Model
|
|
|
|
| From | Trigger | To | Notes |
|
|
|---|---|---|---|
|
|
| `draft` | verification started | `verifying` | Relevant verification run created or reused |
|
|
| `verifying` | verification succeeds and no bootstrap selected | `ready_for_activation` | Verification must be current for selected connection |
|
|
| `verifying` | verification succeeds and bootstrap started | `bootstrapping` | Selected bootstrap runs become active |
|
|
| `verifying` | verification blocked, failed, stale, or mismatched | `action_required` | `reason_code` and optional `blocking_reason_code` set |
|
|
| `action_required` | blocker resolved by rerun or reset | `verifying`, `bootstrapping`, `ready_for_activation`, or `draft` | Chosen by centralized lifecycle recalculation |
|
|
| `bootstrapping` | all selected bootstrap runs complete successfully | `ready_for_activation` | No remaining blocker allowed |
|
|
| `bootstrapping` | selected bootstrap run fails in blocking way | `action_required` | Failure reason preserved |
|
|
| any editable state | cancel action | `cancelled` | Terminal and immutable |
|
|
| `ready_for_activation` | activation succeeds | `completed` | Terminal and immutable |
|
|
|
|
## Concurrency Contract
|
|
|
|
- Every relevant mutation must carry an expected `version`.
|
|
- The write path must compare expected version to persisted version inside the same transaction or atomic update.
|
|
- On mismatch, no lifecycle field, checkpoint field, JSON state, or related run reference may be partially written.
|
|
- Conflict rejection keeps the user on the wizard and returns a visible refresh-required error.
|