Files
stack/docs/requirements/onboarding-wizard.md
T

18 KiB
Raw Blame History

Onboarding Wizard Contract (D4)

Status: DRAFT — awaiting ratification (webui-audit S2, contract 3 of 9). Authority: PRD D4 (Part I §6), D11 v1 slice (Part I §9), D8 architecture gate (Part I §8), the identity account-lifecycle contract (docs/requirements/identity-lifecycle.md, §§24), and the RBAC grant model contract (docs/requirements/rbac-grant-model.md, §4.3). This document turns D4 into a concrete contract: what the wizard is architecturally, its v1 step model, mode branching, re-run/idempotency semantics, and what it seeds under whose authority.

Revision 2 (sol review F1F9): first-company authority repaired — the bootstrap writer creates only the admin and closes the epoch; step 4 runs as the new admin through the ordinary top-level company command (F1). Mode is an install-time input the wizard reads, never writes (F2). The initial user's name restored from the PRD step list, and enrollment skippability flagged as a §12.1 drafting addition (F3). Explicit-choice obligations restated as wizard-run presentation rules that leave identity's defaults untouched, with a submitted-vs-canonical witness (F4). The D8 witness bound to contract 5's mapping and authorization-parity probes (F5). Witness coverage extended to the mode branch, reconfigurability, canonical-state drift, second-company actor semantics, exact seed sets, tab inheritance, and enrollment (F6). Step 4's at-most-once semantics grounded in same-transaction audit reconciliation with per-mutation failure injection (F7). The custody note reduced to a cross-reference (F8). Creation eligibility defined in identity terms with an actor matrix (F9).

Scope: the Gateway-backed product onboarding wizard. Out of scope: the host-local install wizard (mosaic wizard, which drives host install and gateway bootstrap and is not this artifact — audit REPORT.md layer 3); Enterprise mode conversion (contract 6); custody semantics (contract 7); the deferred-beyond-v1 steps themselves (connectors, comms integrations, voice-matching, M365 — D11 defers them; they bind here only through the extensibility rule §2.4).

1. Placement and architecture

  1. The wizard is a product surface over the Gateway command API — a web UI flow (and equivalently scriptable command sequence) that composes Gateway commands. It is subject to the D8 hard rule like every other webUI surface: no wizard operation reaches the database or filesystem directly, and no wizard-only privileged write path exists. Concretely, the wizard is contract 5's rank-6 family, composing the rank-1 hierarchy commands and the rank-4 enrollment command (contract 5 §3.1): those families are built first, and every wizard operation is a row in contract 5's mapping.
  2. The wizard introduces no new mutation surface. Every state change it performs is an existing command with its own contract: user and epoch writes under the identity contract §3, hierarchy writes under contract 1 §5, grant writes under contract 2 §4, settings writes under their owning command family. The one exception is the bootstrap epoch transition, where the wizard drives the bootstrap writer defined by identity §3 — that writer's constraints (§3.1–§3.6) bind unchanged; this contract adds nothing to them.
  3. Wizard state derives from canonical state. Each step renders the system's current configuration (read through the same commands) and applies deltas; the wizard does not keep an answer file whose contents can drift from reality. The wizard MAY persist run bookkeeping (started/completed timestamps); bookkeeping is a cache, never the source of truth for any decision (§4.3 defines the reconciliation rule that makes this concrete for seeding).
  4. If a wizard-completion marker is stored, it is presentational only (which entry screen to show). No authorization or gating decision may read it: gating state lives where its owning contract puts it (bootstrap epoch in bootstrap_state, registration mode in settings, mode in the contract-6 mode record).

2. Modes and extensibility

  1. The wizard differs by mode (D4): Standalone and Enterprise share one skeleton; Enterprise makes personal data optional and moves focus to business structure, RBAC, and external systems.
  2. v1 ships the Standalone flow only (D11). The mode branch point and skeleton MUST still exist in v1 — mode is a property of the flow, not a fork of it — but no Enterprise-only step ships, and mode conversion is contract 6.
  3. Mode is an install-time input, not a wizard output. The deployment mode is recorded canonically at bootstrap and owned by contract 6 (§2 there): the wizard reads the recorded mode and branches on it; it never writes mode and never derives it from feature state. Changing mode later is conversion (contract 6), not a wizard re-run. In v1 a recorded mode of enterprise is refused at bootstrap (contract 6 §5), so the wizard's Enterprise branch is unreachable in v1; a wizard invoked against an unsupported or unreadable mode record produces a single bounded refusal (contract 5 §4.2 precondition class), never a partial flow.
  4. Extensibility: new wizards attach as tabs (D4). Attaching a wizard tab is a registration of additional steps against the same skeleton, inheriting this contract's rules (§1 architecture, §3 step contract, §4 re-runnability). A tab cannot opt out of them: tab steps are subject to the same §6 witnesses as the built-in steps.

3. v1 step model (Standalone)

The v1 wizard consists of exactly these steps, in order, each backed by the named authority:

  1. System and company name. System name is a settings write. Company name feeds step 4's company creation.
  2. Component choices. Mosaic Comms/Matrix vs external; Mosaic SSO/Authentik vs external; Mosaic DB/PostgreSQL vs external; vector DB (D4). v1 records the choices as settings and configures what is installable in-product; component provisioning beyond that is host tooling, out of scope here.
  3. Initial user. Email, password, and display name, or SSO (PRD §6 step list: "email/password/name/SSO"), per identity §3: the first-admin transition is atomic, one per bootstrap epoch, and the SSO variant runs inside the bootstrap transaction (identity §3.6). The submitted display name lands on the canonical account record (identity §2); no field of the PRD's step list is dropped. The wizard also presents the applicable mandatory choices — registration mode (identity §2.2) and, for each configured SSO provider, that provider's JIT enablement with its allowlist warning (identity §4.1, §4.3). The wizard MUST obtain an explicit submission for each applicable mandatory choice and MUST refuse step completion while one is unsubmitted. This is a presentation-and-submission obligation on wizard runs only: identity's own defaults (registration closed, JIT off) continue to govern everything a wizard run never touches, and this contract creates no new stored-record obligation beyond those identity itself defines.
  4. Initial hierarchy and seeding. Runs strictly after step 3's epoch transition, authenticated as the newly created admin. The bootstrap writer (identity §3) creates only the first account and closes the epoch; it has no hierarchy authority and creates no hierarchy node. The first company is created by the ordinary top-level company command under §5.2's eligibility policy, with the new admin as actor, naming the admin as initial owner in the same audited operation (contract 2 §4.3). The initial estate, initial project, and initial workspace with seeded example data (D4, D11) follow through hierarchy commands (contract 1 §5.1) under the admin's owner authority (contract 2 §4.3). Seeded examples are ordinary workspace content created by ordinary commands, attributable in audit to the acting admin with the wizard run's correlation ids (contract 5 §4.3).
  5. Minimal agent enrollment. One harness, API-key login, agent name and persona (D11). Enrollment specifics belong to the rank-4 agent-enrollment command family; this contract binds only that the step exists, uses that family, and is skippable. Skippability is a drafting addition under PRD §12.1 (the PRD step list does not mark the step optional); it is ratified with this contract.

Steps deferred beyond v1 (user onboarding profile, connectors, comms, voice-matching) appear in docs/ROADMAP.md per D11. The deferred profile step's custody semantics are contract 7's (D14); the v1 wizard collects no sensitive category, so v1 ships no custody surface.

4. Re-runnability and idempotency (D4 "no lock-in")

  1. Re-run is a first-class operation. After completion, running the wizard again re-opens every step against current state (§1.3) for reconfiguration. Nothing about completion locks the wizard.
  2. The bootstrap epoch does not re-open (identity §3.4). On re-run, step 3 shows the existing admin/registration/JIT configuration and allows changing the mutable parts through their normal commands; "setup already completed" is a stable state, and factory reset — a future, explicitly destructive operation — is the only path to a new epoch.
  3. Idempotent seeding, reconciled from canonical state. Step 4 on re-run MUST NOT duplicate: the initial company/estate/project/ workspace and the example data are created at most once per bootstrap epoch. The at-most-once key is a deterministic per-mutation correlation id derived from the bootstrap epoch and the seed role (e.g. epoch id + "seed-company"), submitted as the command's correlation id (contract 5 §4.3) and therefore recorded in the mutation's audit event in the same transaction as the mutation itself (contract 1 §5.2). Before applying any seed mutation, the wizard reconciles against the audit/command log for its epoch's seed correlation ids and skips every mutation whose event exists. Wizard bookkeeping of seed node ids is a cache of this record, never the source of truth: losing it cannot cause duplication. A re-run offers to create additional hierarchy nodes (PRD: users can create N companies, N estates, N projects) but never re-creates or resets the originals, and never touches user content added since. Example-data seeding is likewise at-most-once per epoch and is skippable.
  4. Interrupted runs strand nothing. The wizard is resumable at the granularity of a single command: each mutation either commits through its command with its same-transaction audit event, or leaves nothing (identity §3.5 for the bootstrap step). Step 4 is a sequence of individually atomic commands, not one transaction: an interruption between them leaves a prefix of committed seed nodes, and the §4.3 reconciliation rule makes the resumed run complete exactly the remaining suffix, without duplication and without compensating rollback of completed commands. There is no wizard-level transaction spanning steps.

5. Seeding authority (resolves contract 2 review NEW-1)

  1. During the bootstrap epoch, the bootstrap writer's authority (identity §3) covers exactly what identity §3 defines: creating the first account and closing the epoch. It creates no hierarchy node. The first company is created post-epoch by the first admin through the ordinary top-level company command (§5.2), naming that admin as initial owner (contract 2 §4.3). No operator-designated third party, service actor, or wizard-privileged writer exists in this flow.
  2. Post-bootstrap top-level company creation — the "N companies" flow — is decided by the ruling below: any eligible platform user MAY create a top-level company and MUST name an initial owner grant in the same audited operation (contract 2 §4.3); the creator naming themselves is the default. Eligible means, in identity-contract terms: an authenticated account (identity §2) that is not banned and not deactivated (identity §5). No further role or grant is required. Until that ruling, deny-by-default holds (contract 2 §3.1): no implicit creation authority exists.
  3. Child-node creation inside the wizard (estate, project, workspace under the seeded company) follows contract 2 §4.3 unchanged: parent owner authority, no automatic grant needed.

6. Verification requirements

Binding on the implementing PRs:

  1. D8 mapping witness: every Gateway call the wizard makes resolves to a contract 5 mapping row (asserted by contract 5 §6.1's inventory scoped to the wizard surface); wizard modules appear in no class-table writer allowlist (contract 1 §6.3b) and hold no direct database or filesystem access (static assertion, plus a runtime probe that a wizard-context filesystem/database access attempt is refused). Authorization parity: for each mutating wizard operation, the same actor invoking the underlying command directly receives the same authorization outcome as through the wizard — probed for at least one allowed and one refused actor per operation.
  2. Mode witnesses: the branch point exists (the flow resolves its step set from the canonical mode record, read through contract 6's read surface); v1 with mode standalone yields the §3 step set; a simulated unsupported or unreadable mode record yields one bounded precondition refusal (§2.3) and no partial flow; wizard sources contain no mode write and no feature-state mode derivation.
  3. Re-run witnesses: complete the wizard, then re-run it to completion making no changes — assert zero new hierarchy nodes, zero new users, zero new grants, zero duplicated example content, and the bootstrap epoch still completed (identity §8's epoch witnesses cover the transition itself). Reconfigurability: a re-run changes a mutable value (registration mode) and the canonical setting reflects it. Canonical-state drift: mutate state outside the wizard (a rename through the hierarchy command), then re-run — the wizard renders the current canonical value, not a stored answer. Second company: a re-run creating a second company succeeds with the running user as actor, names the creator as owner by default (grant row asserted), and leaves the first company's exact node and content set untouched (row-set and content-digest assertions).
  4. Seed-set witness: after a first completed run, the created seed set is exactly the declared set — one company, one estate, one project, one workspace, the example content (fixed digest), the one §4.3 owner grant, and no other node or grant attributable to the run's correlation ids. Every seeded node, grant, and example item has its command audit event (contract 1 §5.2, contract 2 §4.4) carrying the deterministic seed correlation id (§4.3) and the acting admin; the first-company event names the initial owner grant in the same audited operation.
  5. Explicit-choice witness: a run submitting explicit values completes, and each canonical value equals the value the run submitted (asserted against the captured submissions, not by reading the canonical store twice); a run with an applicable mandatory choice unsubmitted is refused at step 3 (§3.3); identity's defaults are asserted for a provider the run never touched (registration closed, JIT off — identity §2.2, §4.1).
  6. Gating-independence witness: with any wizard-completion marker deleted (§1.4), authorization and registration gating behave identically — proving no gate reads wizard state.
  7. Interrupted-run witness: inject failure after each internal mutation of a run — after the bootstrap transaction, after each individual seed command (company, estate, project, workspace, each example item), and after the bookkeeping cache write — and for each injection point assert: no stranded partial outcome (every committed command has its same-transaction audit event; nothing else exists), and a resumed run completes exactly the remaining mutations with no duplication (identity §8 covers the bootstrap step; §4.3–§4.4 define the reconciliation the witness exercises). Deleting the bookkeeping cache between failure and resume MUST NOT change the outcome.
  8. Actor-matrix witness (§5.2): post-bootstrap top-level company creation succeeds for an ordinary authenticated non-admin user (positive), and is refused for an unauthenticated caller, a banned account, and a deactivated account (negatives), with contract 2's error classes.
  9. Tab-inheritance witness: a registered test tab's steps are subject to the same assertions — its modules fail the §6.1 static assertion if they access the database directly, and its mutations appear in the §6.1 mapping inventory — proving §2.4 is enforced by machinery, not convention.
  10. Enrollment witness: the enrollment step exists, invokes only the rank-4 family, and a run that skips it completes with zero enrollment-family mutations.

Ruling request

Ratify sections 16 as written, with one decision embedded:

  • Decision (§5.2): post-bootstrap, any eligible platform user (authenticated, not banned, not deactivated — identity §2/§5) may create a top-level company, naming an initial owner grant (default: self) in the same audited operation. Basis: PRD Part I §4 "Users can create N companies, N estates, N projects" read as end-user capability, not admin-only. Alternative if rejected: top-level creation stays deny-by-default and becomes a platform-admin-granted capability in a later contract — nothing in this contract or contract 2 breaks either way, because deny-by-default is the resting state (contract 2 §3.1).