Files
stack/docs/requirements/onboarding-wizard.md
T
fred e58d0a5447
ci/woodpecker/pr/ci Pipeline was canceled
docs: onboarding-wizard contract revision 4 (sol re-review 2 residuals + N3/N4)
- F2: bootstrap-status closed two-field schema (epoch enum + pre-epoch-only
  mode), post-epoch mode-field absence witnessed, contract 6 \u00a72.2 amendment
  disclosed (\u00a77.9)
- F5/N4: contract 5 \u00a73.1 rank-6 mapping expansion disclosed naming the rows
  to amend (\u00a77.8); \u00a71.1 states which families are live vs amended
- F7: complete idempotency envelope \u2014 fence records operation/actor/scope/
  payload digest, re-authorized replay, collision refusal, no error replay,
  concurrent loser receives winner's recorded outcome; witnesses added
- N1/N3: post-epoch application phase replaced by a single bootstrap finalize
  command (one transaction: admin + epoch close + carried settings/registration/
  JIT/seed-parameter writes under the new admin); password-only v1 first admin
  (\u00a77.10); seed sequence derived from canonical state; \u00a76.11 uses the
  authentication-failure class
2026-08-26 20:21:55 -05:00

34 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).

Revision 3 (sol re-review: residual F2/F3/F5/F6/F7/F9, new N1/N2): the wizard is now explicitly a client-side composition with no server-side orchestrator, spanning six named command families, every operation an ordinary outbound Gateway call inside contract 5 §6.1's inventory scope (F5). First runs collect steps 12 without writing; the collected settings are applied immediately after the epoch transition under the first admin's platform authority, so no pre-admin write authority exists or is invented (N1). Pre-epoch mode branching reads the mode value from the unauthenticated bootstrap-status response, a disclosed one-field addition; post-epoch runs use contract 6's authenticated read (F2). The SSO display-name source is bound to identity §5's mapped name claim, with a canonical-name witness (F3). At-most-once seeding is fenced by a caller-supplied idempotency key recorded under a unique constraint in the same transaction as the mutation; correlation ids revert to pure trace linkage (F7). Re-run witnesses now cover every mutable family, assert the second-company grant is same-operation, and extend tab inheritance to re-run and explicit-choice machinery (F6). Eligibility is restated in identity §7.1's terms — deactivation is the better-auth ban, with no separate state (F9). Example-data seeding is mandatory; the skippability policy is removed (PRD §6.4) (N2). All drafting additions are consolidated in §7.

Revision 4 (sol re-review 2: residual F2/F5/F7/N1, new N3/N4): the post-epoch application phase is replaced by a single bootstrap finalize command — step 3 submits the first-admin fields and every collected value (settings, registration mode, applicable JIT choices, seed parameters) in one command on identity §3's bootstrap surface, executed server-side in one transaction that creates the admin, closes the epoch, and commits the carried values under the new admin's authority; after it, every collected value is canonical state, so an interrupted run resumes from canonical state alone (N1, N3). The v1 first admin is password-only; identity §3.6's SSO variant is not composed by the v1 wizard (N1's SSO ordering). The bootstrap-status response is a closed two-field schema (epoch state plus a pre-epoch-only mode field), with the contract 6 §2.2 amendment disclosed (F2). The idempotency envelope is completed: fence rows record operation, actor, scope, and payload digest; replay is re-authorized; changed-payload collision is refused; only committed outcomes are recorded; the concurrent loser receives the winner's recorded outcome (F7). §7 now names the contract 5 §3.1 rank-6 mapping rows the composition expansion amends (F5, N4).

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, and it is a client-side composition with no server-side wizard orchestrator: every wizard operation is an ordinary outbound Gateway call issued from the wizard's web modules (or the equivalent scripted sequence), so contract 5 §6.1's outbound-call inventory, scoped to those modules, sees the wizard's complete operation set. The composed operations span six existing families: the rank-1 hierarchy commands and the rank-4 enrollment command (contract 5 §3.1 — built first), the settings command family (steps 12), the identity bootstrap and registration surface (step 3, including the §3.3 finalize command), the mode reads (contract 6 §2.2 post-epoch; the §2.3 bootstrap-status field pre-epoch), and the ordinary content commands used for example seeding (step 4). Two of these families (ranks 1 and 4) are in contract 5 §3.1's live rank-6 composition row; the other four are added by the disclosed §7.8 mapping amendment, without which their operations are unmapped and blocked under contract 5 §5.
  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. Values a first run has collected but not yet committed by the §3.3 finalize command are transient run state, not a persisted answer file; after finalize every collected value is canonical state, and no transient value is needed to resume (§4.4). The wizard MAY persist run bookkeeping (started/completed timestamps); bookkeeping is a cache, never the source of truth for any decision. The §4.3 idempotency fence is command-layer canonical state, not wizard bookkeeping — losing bookkeeping never affects it.
  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. During the bootstrap epoch no authenticated account exists, so contract 6 §2.2's authenticated read surface is unreachable there; the pre-epoch flow instead branches on the mode value reported by the unauthenticated bootstrap-status response of the bootstrap surface (identity §3), which evaluates the mode record server-side. The bootstrap-status response is a closed two-field schema: epoch — one field whose value set is exactly the bootstrap epoch states identity §3 defines for bootstrap_state, closed to that enumeration — and mode — the recorded mode value, present only while the epoch is open and absent from the response schema once the epoch has completed. No other field exists in the response. The unauthenticated pre-epoch mode disclosure is a disclosed amendment to contract 6 §2.2's authenticated-read rule (§7.9); post-epoch, §2.2's authenticated-only rule holds unchanged and the bootstrap-status response carries no mode field. Post-epoch wizard runs read mode through contract 6 §2.2 unchanged. 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 value; company name feeds step 4's company creation. On a first run this step collects and validates only — the collected values are committed by step 3's finalize command (§3.3). On a re-run (an authenticated admin exists) it applies directly through the settings commands.
  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 (first run: collected, committed by step 3's finalize command §3.3; re-run: applied directly) and configures what is installable in-product; component provisioning beyond that is host tooling, out of scope here.
  3. Initial user and finalize. Email, password, and display name (PRD §6 step list: "email/password/name/SSO"), per identity §3: the first-admin transition is atomic and one per bootstrap epoch. The v1 first admin is password-only. A step-2 SSO choice cannot yield a canonically configured provider before the epoch closes, so an SSO-authenticated first admin is not constructible in this flow; the v1 wizard does not compose identity §3.6's SSO variant, and the PRD step list's SSO option is satisfied post-epoch (providers configured and JIT-enabled after finalize; identity §5 governs every SSO-created account). This is a disclosed sequencing decision (§7.10). The password path's canonical users.name MUST equal the submitted display name; any SSO-created account's name is bound to identity §5's mapped name claim (witness §6.5); 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 SSO provider canonically configured at finalize time, that provider's JIT enablement with its allowlist warning (identity §4.1, §4.3); a provider configured after finalize receives its JIT choice at configuration time under identity §4.1's default. The wizard MUST obtain an explicit submission for each applicable mandatory choice and MUST refuse finalize 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. Finalize rule (first runs): step 3 ends in a single bootstrap finalize command on identity §3's bootstrap surface — a disclosed extension of that surface (§7.3) — carrying the first-admin fields and every collected value: the step-1 system name, the step-1 company name (recorded as the §3.4 seed parameter), the step-2 component choices, the registration-mode submission, and the applicable JIT submissions. The command executes in one transaction: it creates the admin and closes the epoch exactly as identity §3 defines, then — with the new admin existing inside the same transaction, holding the RBAC §1.1 platform authority those writes require — commits every carried value through the ordinary settings and identity configuration writes, each attributed in audit to the new admin. Either the whole transaction commits or none of it exists (identity §3.5's atomicity extends over the carried writes). Before finalize the run holds collected values only: no canonical write of any kind occurs pre-epoch, and no pre-admin write authority exists or is invented (witness §6.11). After finalize, every collected value is canonical state; no transient value is needed to resume (§4.4, witness §6.7).
  4. Initial hierarchy and seeding. Runs strictly after step 3's finalize transaction, authenticated as the newly created admin. The bootstrap writer (identity §3) creates only the first account, closes the epoch, and commits the §3.3 carried values; it has no hierarchy authority and creates no hierarchy node. The seed sequence is derived entirely from canonical state: the seed parameter the finalize command recorded (the company name) and the fixed example set (§4.3). A resumed run — including a fresh client holding none of the original run's transient state — reconstructs the same ordered sequence and the same deterministic §4.3 keys from that canonical state alone. 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, carrying the run's trace correlation ids (contract 5 §4.3) and the §4.3 idempotency keys.
  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 disclosed in §7 and 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, fenced at the command layer. 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 mechanism is an idempotency key, a disclosed drafting addition to contract 5's §4 command envelope ratified with this contract (§7): a mutating command MAY carry a caller-supplied idempotency key. The complete envelope:

    • Fence row. The command layer records, in a uniqueness-constrained fence table in the same transaction as the mutation and its audit event: the key, the operation identifier, the acting principal, the mutation's authorization scope (the target company, or the platform scope for top-level operations), a digest of the canonicalized request payload, and a reference to the committed outcome. Fence uniqueness is the pair (operation identifier, key).
    • Replay. A submission whose (operation, key) pair is recorded is first authorized exactly as a fresh submission would be — an actor who is not authorized receives the authorization refusal, never the recorded outcome. If authorization passes and the recorded actor, scope, and payload digest all equal the submission's, the command executes nothing and returns the recorded outcome.
    • Collision. A submission whose (operation, key) pair is recorded but whose actor, scope, or payload digest differs is refused with a single bounded conflict error (contract 5 §4.2); it executes nothing and discloses nothing of the recorded outcome.
    • No error replay. The fence row commits only with its mutation, so only committed outcomes are ever recorded. A failed or refused submission records no fence row; a retry executes afresh. There is no recorded-error state.
    • Concurrency. Two submissions with the same (operation, key) pair serialize on the fence's unique constraint: exactly one executes. The loser waits for the winner's transaction to resolve; if it committed, the loser is handled as a replay (authorization first, then the recorded outcome, or the collision refusal on mismatch); if it aborted, no fence row exists and the loser executes. The loser never performs a second mutation and is never left without a defined response.

    The wizard submits deterministic keys derived from the bootstrap epoch and the seed role (e.g. epoch id + "seed-company") for every seed mutation. Correlation ids (contract 5 §4.3) remain pure trace linkage and carry no idempotency semantics. Wizard bookkeeping of seed node ids remains a cache (§1.3): losing it cannot cause duplication, because the fence is canonical command-layer state. 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; the example set is fixed and its seeding is not skippable (PRD §6.4: a completed first run contains the fixed example set).

  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 and fence row, or leaves nothing (identity §3.5, extended over the carried writes, for the §3.3 finalize command). A run interrupted before finalize has written nothing; its collected values are re-entered. A run interrupted after finalize resumes from canonical state alone: every collected value was committed by the finalize transaction, and the remaining work — the step 45 command sequence — is derivable from it (§3.4). 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 fence makes the resumed run complete exactly the remaining suffix — the run re-derives the full ordered seed sequence from canonical state and re-submits it with the same deterministic keys, already-committed mutations return their recorded outcomes, and only the remainder executes, 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 (identity §7.1 — deactivation on this platform IS the better-auth ban; no separate deactivated state exists). 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 outbound-call inventory scoped to the wizard modules — an inventory that is complete for the wizard because §1.1 forbids a server-side wizard orchestrator, and the witness statically asserts that prohibition (no server-side module composes wizard operations). The inventoried operation set is asserted equal, in both directions, to the §1.1 declared family list. 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 — a pre-epoch flow resolves its step set from the bootstrap-status mode field (§2.3), a post-epoch run from contract 6 §2.2's authenticated read; the bootstrap-status response matches §2.3's closed two-field schema exactly while the epoch is open, and after the epoch completes contains the epoch field only — the mode field absent from the response (closed-field assertion on the response schema in both phases); post-epoch, an unauthenticated mode read through any surface is refused (contract 6 §2.2, as amended by §7.9, holds); 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 one value in each mutable family — the system name (settings), a component choice (settings), registration mode, and a configured provider's JIT enablement — and each canonical value reflects the change; a run that skipped enrollment enrolls an agent on re-run through the rank-4 family and the enrollment exists canonically. 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 and names the creator as owner in the same audited operation — asserted on the single audit event naming both the creation and the grant (contract 2 §4.3–§4.4), not merely on the grant row's existence — 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 idempotency keys or trace correlation ids. Every seeded node, grant, and example item has its command audit event (contract 1 §5.2, contract 2 §4.4) committed in the same transaction as its mutation and §4.3 fence row, attributed to 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); canonical users.name equals the declared source — for the first admin (password path), the submitted display name; for an SSO-created account (a post-epoch JIT-provisioned user), the identity §5 mapped name claim (each asserted against the captured submission or captured assertion); 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 at each point of a run — inside the finalize transaction (after admin creation but before the carried writes commit: assert nothing exists — no account, the epoch still open, canonical settings untouched, no fence row, no audit event), after the committed finalize 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 and fence row; nothing else exists), and a resumed run completes exactly the remaining mutations with no duplication (identity §8 covers the epoch transition; §4.3–§4.4 define the fence the witness exercises). The resume after the committed finalize MUST be performed by a fresh client holding none of the original run's transient state, deriving the remaining seed sequence from canonical state alone (§3.4). Deleting the bookkeeping cache between failure and resume MUST NOT change the outcome. Idempotency-fence witnesses (§4.3): re-submitting a committed seed command with its same key, actor, and payload executes nothing and returns the recorded outcome (asserted by mutation-count and audit-event-count equality); the same key with a changed payload digest is refused with the single bounded conflict and executes nothing; a replay by an actor who has since lost eligibility (identity §7.1 ban) receives the authorization refusal, not the recorded outcome; a submission that failed before commit leaves no fence row and its retry executes; two concurrent resumed runs executing the seed sequence yield exactly one seed set — per key, exactly one mutation and one audit event exist, and the losing submission received the winner's recorded 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 and for a banned account (identity §7.1's deactivation-as-ban) (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, its mutations appear in the §6.1 mapping inventory, a tab re-run making no changes produces zero new mutations (§6.3 style), and a tab declaring a mandatory choice is refused while it is unsubmitted (§6.5 style) — 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.
  11. Pre-epoch authority and finalize witness (§3.3): during a first run, before finalize, canonical state is untouched (settings-state comparison against the pre-run capture), and an injected settings-write attempt from the unauthenticated pre-epoch flow is refused with contract 5 §4.2's authentication-failure class (the caller is unauthenticated, not an authorized-but-refused actor); the finalize command commits the admin, the epoch transition, and every carried value in one transaction, each carried write attributable in audit to the new admin; the §6.7 inside-finalize injection covers the atomicity negative.

7. Drafting additions (PRD §12.1 disclosure)

Proposed drafting additions, visible here for ratification, each severable; the step list, mode branching, re-runnability, and seeding obligations themselves are traced to PRD D4/D11 and the named sibling contracts and are not additions:

  1. Enrollment-step skippability (§3.5) — the PRD step list does not mark the step optional.
  2. The unauthenticated bootstrap-status mode disclosure — the closed two-field response schema (epoch state plus the recorded mode value, the latter present during the bootstrap epoch only) (§2.3).
  3. The bootstrap finalize command (§3.3) — an extension of identity §3's bootstrap surface: one transaction carrying the first-admin fields, the collected settings, registration-mode, and JIT values, and the §3.4 seed parameter, committing the carried writes under the new admin's authority with identity §3.5's atomicity extended over them. Severable from the rest of this contract.
  4. The idempotency-key field and its same-transaction uniqueness fence, with the §4.3 replay, collision, no-error-replay, and concurrency rules — an addition to contract 5 §4's command envelope, proposed and ratified here, severable from the rest of this contract.
  5. The presentation-and-submission obligation for applicable mandatory choices on wizard runs (§3.3).
  6. The no-server-side-orchestrator architectural constraint (§1.1).
  7. The wizard-completion-marker presentational-only rule (§1.4).
  8. The contract 5 §3.1 rank-6 mapping expansion (§1.1): the rank-6 composition row, which today names only the rank-1 hierarchy and rank-4 enrollment families, is amended to name all six composed families — adding the settings command family, the identity bootstrap and registration surface (including the §3.3 finalize command), the mode reads (contract 6 §2.2 and the §2.3 bootstrap-status field), and the ordinary content commands used for example seeding — with one mapping row per newly named family. Without this amendment those operations are unmapped and blocked under contract 5 §5.
  9. The contract 6 §2.2 amendment permitting the single unauthenticated pre-epoch mode disclosure through the §2.3 bootstrap-status field; post-epoch, §2.2's authenticated-only rule is unchanged.
  10. The password-only v1 first admin (§3.3): identity §3.6's SSO variant is not composed by the v1 wizard; the PRD step list's SSO option is satisfied post-epoch.

Ruling request

Ratify sections 17 as written, with one decision embedded:

  • Decision (§5.2): post-bootstrap, any eligible platform user (authenticated, not banned — identity §2/§7.1) 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).