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

3.6 KiB
Raw Blame History

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.