This commit is contained in:
@@ -0,0 +1,189 @@
|
|||||||
|
# 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`, §§2–4), 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.
|
||||||
|
|
||||||
|
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 enforcement 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 existing audited 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.
|
||||||
|
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, mode) and MUST persist the
|
||||||
|
explicit-choice records other contracts mandate (registration mode,
|
||||||
|
identity §2.2; per-provider JIT enablement, identity §4.1) — those are
|
||||||
|
settings writes, not private wizard state.
|
||||||
|
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).
|
||||||
|
|
||||||
|
## 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 chosen at bootstrap and recorded as an explicit operator
|
||||||
|
choice. Changing it later is conversion (contract 6), not a wizard
|
||||||
|
re-run.
|
||||||
|
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.
|
||||||
|
|
||||||
|
## 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 or 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
|
||||||
|
wizard also presents registration mode (identity §2.2) and, when SSO
|
||||||
|
is configured, per-provider JIT with its allowlist warning (identity
|
||||||
|
§4.1, §4.3) — each recorded as an explicit choice, none silently
|
||||||
|
defaulted.
|
||||||
|
4. **Initial hierarchy and seeding.** Creates the first company (naming
|
||||||
|
the initial `owner` grant in the same audited operation, contract 2
|
||||||
|
§4.3), an initial estate, an initial project, and an initial workspace
|
||||||
|
with seeded example data (D4, D11). All through hierarchy commands
|
||||||
|
(contract 1 §5.1); seeded examples are ordinary workspace content
|
||||||
|
created by ordinary commands, attributable in audit to the wizard run
|
||||||
|
actor.
|
||||||
|
5. **Minimal agent enrollment.** One harness, API-key login, agent name
|
||||||
|
and persona (D11). Enrollment specifics belong to the agent-enrollment
|
||||||
|
command family; this contract binds only that the step exists, is
|
||||||
|
skippable, and uses that family.
|
||||||
|
|
||||||
|
Steps deferred beyond v1 (user onboarding profile, connectors, comms,
|
||||||
|
voice-matching) appear in `docs/ROADMAP.md` per D11. Note for the profile
|
||||||
|
step when it lands: sensitive profile categories are custody-bound to the
|
||||||
|
user's own brain (D14, contract 7); the v1 wizard collects none of them,
|
||||||
|
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.** Step 4 on re-run MUST NOT duplicate: the
|
||||||
|
initial company/estate/project/workspace are created at most once per
|
||||||
|
bootstrap epoch, keyed by recorded seed identity (the created node
|
||||||
|
ids), not by name matching. 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 step
|
||||||
|
granularity: each step's apply either commits through its command (and
|
||||||
|
is then visible as current state to the resumed run) or leaves nothing
|
||||||
|
(identity §3.5 for the bootstrap step). There is no wizard-level
|
||||||
|
transaction spanning steps and no compensating rollback of completed
|
||||||
|
steps.
|
||||||
|
|
||||||
|
## 5. Seeding authority (resolves contract 2 review NEW-1)
|
||||||
|
|
||||||
|
1. During the bootstrap epoch, the wizard's authority to create the first
|
||||||
|
company is the bootstrap writer's (identity §3): there is no earlier
|
||||||
|
user to authorize it. The first company creation names the first admin
|
||||||
|
(or the operator-designated initial user) as initial `owner` (contract
|
||||||
|
2 §4.3).
|
||||||
|
2. **Post-bootstrap top-level company creation** — the "N companies" flow
|
||||||
|
— is decided by the ruling below: any ACTIVE 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. 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. **No-new-writers witness:** the wizard modules appear in no
|
||||||
|
class-table writer allowlist (contract 1 §6.3b) and hold no direct DB
|
||||||
|
access; a static assertion that wizard code reaches state only through
|
||||||
|
Gateway command clients.
|
||||||
|
2. **Re-run witnesses:** complete the wizard, then re-run it to
|
||||||
|
completion making no changes — assert zero new hierarchy nodes, zero
|
||||||
|
new users, zero duplicated example content, and the bootstrap epoch
|
||||||
|
still completed (identity §8's epoch witnesses cover the transition
|
||||||
|
itself). Then a re-run that adds a second company succeeds and leaves
|
||||||
|
the first company and its content untouched (row-count and content
|
||||||
|
assertions).
|
||||||
|
3. **Seed-audit witness:** every node, grant, and example item created by
|
||||||
|
a wizard run has its command audit event (contract 1 §5.2, contract 2
|
||||||
|
§4.4) attributing the wizard-run actor; the first-company event names
|
||||||
|
the initial owner grant in the same audited operation.
|
||||||
|
4. **Explicit-choice witnesses:** after a completed run, registration
|
||||||
|
mode, per-provider JIT flags, mode (Standalone/Enterprise), and
|
||||||
|
component choices each read back as recorded values; the identity
|
||||||
|
contract's defaults (registration `closed`, JIT off) hold for any
|
||||||
|
choice the run did not explicitly make.
|
||||||
|
5. **Gating-independence witness:** with any wizard-completion marker
|
||||||
|
deleted (§1.4), authorization and registration gating behave
|
||||||
|
identically — proving no gate reads wizard state.
|
||||||
|
6. **Interrupted-run witness:** kill a run between steps; assert no
|
||||||
|
stranded partial outcome (identity §8 covers the bootstrap step; for
|
||||||
|
step 4, either the node set committed with its audit events or is
|
||||||
|
absent) and that a resumed run completes against the committed state.
|
||||||
|
|
||||||
|
## Ruling request
|
||||||
|
|
||||||
|
Ratify sections 1–6 as written, with one decision embedded:
|
||||||
|
|
||||||
|
- Decision (§5.2): post-bootstrap, any ACTIVE platform user 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).
|
||||||
Reference in New Issue
Block a user