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

4.2 KiB
Raw Blame History

Research: Managed Tenant Onboarding Wizard UI (v2) (069)

This document resolves Phase 0 unknowns and captures the design decisions used by plan.md.

Decision 1 — Scope mapping ("Workspace" vs current app tenant)

Decision: For v2, interpret Workspace scope and Managed Tenant from the spec as the existing Filament tenant model: App\Models\Tenant.

Rationale:

  • The current apps authorization plane, routing, and multi-tenancy are already built around Tenant.
  • Provider connections are already tenant-scoped (provider_connections.tenant_id).
  • Introducing a new Workspace/ManagedTenant hierarchy would expand the change surface (routing, policies, membership model, UI) beyond what is needed to ship the wizard + task board.

Alternatives considered:

  • Add a new workspaces model/table with managed_tenants underneath it.
    • Rejected for Phase 1: would require reworking tenancy, membership, policies, and navigation.

Decision 2 — Evidence as the status source-of-truth

Decision: Step/task badges are derived from stored evidence rows; any "status" fields elsewhere are treated as derived cache.

Rationale:

  • Matches FR-006 and prevents UI from being dependent on ephemeral job output.
  • Enables stable audit/troubleshooting and deterministic rendering (Monitoring pages remain DB-only).

Alternatives considered:

  • Cache the current status directly on Tenant.
    • Rejected: easy to drift from reality and makes history/audit harder.

Decision 3 — Task catalog representation

Decision: Implement onboarding tasks as a small, explicit catalog (PHP enum or config-backed list) that defines:

  • task_type (stable key)
  • prerequisites
  • which OperationRun type/job implements the task
  • which evidence type(s) it writes

Rationale:

  • Keeps task definitions centralized and testable.
  • Supports the task board UX (show prerequisites, last status, rerun).

Alternatives considered:

  • Store task definitions in the database.
    • Rejected for Phase 1: adds complexity/migrations and makes review harder.

Decision 4 — Concurrency + idempotency for task starts

Decision: Enforce "one active run per (managed_tenant_id, task_type)" by:

  • Using OperationRunService::ensureRunWithIdentity(...) with an identity payload that includes at least { tenant_id, task_type }.
  • Maintaining/using an active-run unique constraint for the computed identity hash.

Rationale:

  • Aligns with the constitution (DB-level active run dedupe) and existing provider start-gate patterns.
  • Prevents double-click duplicates and conflicting task runs.

Alternatives considered:

  • Application-only mutexes/locks.
    • Rejected: insufficient without DB-level protection.

Decision 5 — Collaboration locking model

Decision: Add session-level locking fields to onboarding sessions:

  • locked_by_user_id
  • locked_until

Rationale:

  • Simple, explainable behavior.
  • Supports takeover/handoff and prevents silent overwrites.

Alternatives considered:

  • Per-step/per-task fine-grained locks.
    • Rejected for Phase 1: higher complexity with limited user value.

Decision 6 — Legacy (v1) onboarding migration path

Decision: Provide a migration bridge that can:

  • Create a Provider Connection for a tenant if the legacy Tenant credential fields exist.
  • Move credentials into provider_credentials (encrypted) and stop rendering the legacy credential fields in the onboarding UI.

Rationale:

  • Satisfies FR-021 without requiring a full backfill of historical run output.
  • Aligns with the repos existing secure credential patterns (ProviderCredential + CredentialManager).

Alternatives considered:

  • Keep using Tenant.app_client_secret for v2.
    • Rejected: conflicts with ProviderConnection-first direction and increases leak risk.

Decision 7 — Filament implementation shape

Decision: Implement wizard + task board as Filament Pages/Actions.

Rationale:

  • Matches current admin UI architecture.
  • Allows capability-gated actions with consistent RBAC UX patterns.

Alternatives considered:

  • Standalone Blade controllers for v2 onboarding.
    • Rejected: splits patterns and complicates authorization/testing conventions.