TenantAtlas/specs/069-tenant-onboarding-wizard-v2/data-model.md
2026-02-01 01:20:10 +01:00

93 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Data Model: Managed Tenant Onboarding Wizard UI (v2) (069)
This is a Phase 1 design artifact. It describes the entities needed to implement evidence-driven onboarding, collaboration locks, and task execution history.
## Context / Scope Mapping
For v2, this plan maps the specs **Workspace / Managed Tenant** concepts to the existing `App\Models\Tenant` model.
## Entities
### OnboardingSession (new)
Represents a resumable onboarding state machine and collaboration surface.
**Identity**
- `tenant_id` (FK → `tenants.id`) + `status != completed` should have at most one “active” session per tenant (policy decision; optional enforcement).
**Fields (suggested)**
- `id` (bigint)
- `tenant_id` (FK → `tenants.id`)
- `provider_connection_id` (FK → `provider_connections.id`, nullable)
- `status` (string: `draft|in_progress|completed|abandoned`)
- `current_step` (smallint: 15)
- `assigned_to_user_id` (FK → `users.id`, nullable)
- `locked_by_user_id` (FK → `users.id`, nullable)
- `locked_until` (timestamp, nullable)
- `completed_at` (timestamp, nullable)
- `metadata` (jsonb; whitelisted UI metadata only)
- timestamps
**Validation / invariants**
- If `provider_connection_id` is set, it must belong to the same `tenant_id`.
- `locked_until` should be short-lived (e.g., 510 minutes) and renewed by activity.
**State transitions**
- `draft → in_progress → completed`
- `draft|in_progress → abandoned` (explicit action)
### OnboardingEvidence (new)
Stores evidence that drives UI statuses and provides historical visibility.
**Identity**
- Many evidence rows per tenant and per task type.
**Fields (suggested)**
- `id` (bigint)
- `tenant_id` (FK → `tenants.id`)
- `onboarding_session_id` (FK → `onboarding_sessions.id`, nullable)
- `provider_connection_id` (FK → `provider_connections.id`, nullable)
- `task_type` (string; stable key, e.g. `onboarding.permissions.verify`)
- `status` (string: `ok|warn|fail|unknown`)
- `reason_code` (string, nullable; stable code aligned with RunFailureSanitizer)
- `message` (string, nullable; sanitized, never secrets)
- `payload` (jsonb; whitelisted + sanitized evidence payload)
- `operation_run_id` (FK → `operation_runs.id`, nullable)
- `recorded_at` (timestamp)
- `recorded_by_user_id` (FK → `users.id`, nullable)
- timestamps
**Indexes (suggested)**
- `(tenant_id, task_type, recorded_at desc)`
- `(tenant_id, task_type)` for “latest evidence per type” query patterns
**Validation / invariants**
- `message` must be sanitized/redacted (no tokens/secrets/PII dumps).
- `payload` is not a raw provider response; store only what the UI needs.
### ProviderConnection / ProviderCredential (existing)
v2 uses the existing provider connection model:
- `provider_connections` is tenant-scoped.
- `provider_credentials.payload` is encrypted and must never be rendered.
**v2 scope**
- `provider_credentials.type = client_secret` only.
### OperationRun (existing)
Provider-affecting onboarding tasks must be executed via `OperationRun` + queued jobs.
**Concurrency rule**
- For onboarding tasks, identity must include at least `{ tenant_id, task_type }` so there is at most one active run per `(tenant, task_type)`.
## Derived Views / Queries
- **Latest evidence per task**: `where tenant_id = ? and task_type = ? order by recorded_at desc limit 1`.
- **Task history**: `where tenant_id = ? and task_type = ? order by recorded_at desc`.
## Notes
- If we later introduce a real Workspace/ManagedTenant hierarchy, `tenant_id` can evolve into `workspace_id`, and the evidence/session tables can add `managed_tenant_id` without changing the core model.