diff --git a/docs/requirements/onboarding-wizard.md b/docs/requirements/onboarding-wizard.md new file mode 100644 index 00000000..67153aa2 --- /dev/null +++ b/docs/requirements/onboarding-wizard.md @@ -0,0 +1,1948 @@ +# 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. + +Revision 2 (sol review F1–F9): 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 1–2 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). + +Revision 5 (sol re-review 3: residual F2/F7/N1/N3, new N5/N6): the +finalize command is now honestly scoped as the wizard's **single +disclosed server-side composed transaction** — a bounded, severable +amendment to the §1.1 client-side-composition rule, reachable only +while the epoch is open, executing under the bootstrap writer's +amended authority (never by authenticating the caller as the created +admin), with a dedicated finalize-write inventory witness proving its +internal write set equals the §3.3 carried-value list; §1.2 and §5.1 +no longer claim identity §3 binds unchanged (N1, N5). The epoch field's +wire values are pinned to the closed token pair `open`/`completed` +(identity §3 names the states but no wire enumeration; the pin is +disclosed) (F2). The company-name seed parameter gains an owning +record: the declared `bootstrap.seed-company-name` settings value, +committed by finalize and read through the ordinary settings surface +(N3). The §6.7 fence witnesses add the different-actor collision, the +different-scope collision, and the aborted-winner concurrency case +(F7). The password-only first admin is restated as a disclosed PRD +deviation (deferment) of the initial-user SSO option, not as its +satisfaction (N6). + +Revision 6 (sol re-review 4: residual F7, new N7): the seed parameter +becomes **immutable seed provenance** — `bootstrap.seed-company-name` +is written exactly once by the finalize transaction and any later +write to it is refused, so a re-run's re-derived seed sequence is +byte-stable and replays cleanly against the §4.3 fence instead of +colliding with it; the current company name's canonical home is the +company row (renamed through the ordinary hierarchy command), and the +wizard renders the row, never the provenance value (N7). §6.3 gains +the changed-name re-run and rename-then-re-run witnesses plus the +immutability refusal probe, with a mutated-digest collision control +(N7). §6.7 adds the two missing envelope witnesses: the same raw key +under two different operations executes both independently +(pair-uniqueness, not global key-uniqueness), and a fresh +authorization refusal records no fence row so an authorized retry +executes afresh (F7). + +Revision 7 (sol re-review 5: residual F6, new N8): the fence gains a +**replay mode** — each keyed submission declares `actor-bound` +(default) or `shared`, recorded in the fence row; a shared row replays +for any freshly authorized actor whose scope and payload digest match, +while an actor-bound row keeps the revision-6 actor-equality rule, and +a declared-mode mismatch is a collision. Every §3.4 seed submission +declares shared, reconciling actor-bound replay with re-runnability: +the seed set is a per-epoch singleton, so a fresh-authorized second +admin's no-change re-run replays the first run's recorded outcomes +instead of colliding (N8). §6.7's different-actor witness splits into +the actor-bound refusal and the shared replay, plus a mode-mismatch +collision and a shared-row lost-eligibility refusal; §6.3 adds the +second-admin re-run witness (N8). §6.3's changed-name case now +continues through step 4 with the bookkeeping cache deleted — original +digests asserted, every seed outcome replayed, zero new nodes, run +completed — proving the dirty form value never enters derivation and +the renamed row resolves cache-independently (F6). + +Revision 8 (sol re-review 6: NEW-9): shared replay gains a +**target-result authorization boundary** — returning a recorded +outcome is a read of the canonical records it references, authorized +separately from fresh-mutation authorization: a shared replay +requires the submitter to hold, at replay time, read authority on +every record the recorded outcome references, and a submitter who +passes the fresh-mutation check but lacks target read authority is +refused with the same constant-shape single bounded conflict as a +§4.3 collision, identifying no record — the response confirms no +tenant target's existence, preserving RBAC §7's no-existence-oracle +rule (§4.3). `shared` becomes server-verified seed-only policy: the +command layer re-derives the epoch's **canonical seed tuple set** +from canonical state alone and refuses any shared declaration whose +(operation, key, scope, digest) tuple is not a member, and a missing +seed fence is originated only by a submission passing the full +fresh-mutation authorization for that seed command — a wrong actor +cannot win an unrecorded seed key, and no shared row can exist +outside the seed sequence (§4.3). An authorized shared replay appends +a **replay access event** — a distinct non-mutation audit event class +recording the replaying actor, the current request's correlation ids, +and the fence row whose outcome was returned — so every access to a +recorded outcome is attributed without a duplicate semantic mutation +event, while the fence row and the mutation event immutably retain +the original actor (§4.3, §7.4). §6.7 adds the unauthorized-target +replay refusal, the non-seed shared declaration refusal, and the +unrecorded-seed-key race; §6.3's second-admin witness grants B +explicit read authority on the recorded seed targets and asserts B's +replay access events; replay-affected count equalities are scoped to +the mutation event class (NEW-9). + +Revision 9 (sol re-review 7: NEW-9 residual, NEW-10): the seed +boundary becomes server-complete and oracle-free. The **canonical +seed key set** is fence-independent (epoch id plus the fixed +seed-role list), while the full tuple set is **prefix-derived**: each +position's scope and payload digest derive from the committed +predecessors' recorded fence outcomes, the derivable members at any +state are the committed prefix plus the next unrecorded position, +the pre-first-company state derives exactly the seed-company tuple, +and an out-of-order shared declaration is refused recording nothing +(§4.3, §3.4). The epoch gains one immutable **seed-origin account** +— the first admin the finalize transaction created — and a +**seed-boundary gate** evaluated after fresh-mutation authorization +and before fence presence can affect the response: a submitter on a +canonical seed key who is neither the seed-origin account nor holds +target-result read authority on the position's recorded targets +receives the constant-shape bounded conflict, identical across the +recorded and unrecorded worlds, creating nothing in either — so +§5.2 eligibility alone can never originate a seed fence and the +eligible-wrong-actor race on the top-level seed-company key is +closed (NEW-9; witnesses §6.7: the two-world control and the +top-level origination race). Target-result authorization extends to +**every replay mode**: an `actor-bound` replay requires the recorded +actor to hold live read authority on every record the recorded +outcome references, actor equality remaining an additional +condition, never a substitute — a creator whose grants were revoked +is refused, not replayed (NEW-10; §6.7 lost-target-grant witness). + +Revision 10 (sol re-review 8: NEW-11): the seed-origin boundary becomes +recoverable without breaking the no-oracle result. The epoch's +seed-origin is a **designation** the finalize fixes to the first admin, +changed through exactly one disclosed command — **seed-origin +succession** (§4.3, §7 item 12): an eligible platform admin holding +target-result read authority on the committed seed prefix succeeds only +while the current origin fails identity §7.1 eligibility; refusals keep +the constant conflict shape whatever condition failed and whatever is +recorded, concurrent successions serialize on the epoch record, the +change is one audited epoch-record mutation, and recorded fence rows +immutably retain their original actor. The seed-boundary gate and the +origination rule read the epoch record's current designation, so a +banned origin — identity §7.1's sole unavailability state; deletion +does not exist under identity §7.3 — no longer strands the +unoriginated suffix — +the successor resumes and completes it with no factory reset and no new +epoch, restoring D4 re-runnability and §4.4's strand-nothing rule +(NEW-11; witnesses §6.7: succession recovery, origin-available refusal, +succession race). + +Revision 11 (sol re-review 9: NEW-12, NEW-13, NEW-14, NEW-15): succession +itself becomes oracle-free and strand-proof. Succession's conditions are +now **fence-independent**: the submitter's side is exactly platform-level +eligibility plus §5.2 top-level-create eligibility — never any authority +over, or reference to, committed seed records — and the origin's side is +the disjunction _unavailable or unable_: the current origin fails +identity §7.1's single account-unavailability predicate (today exactly +the better-auth ban), or lacks the seed-completion authority defined in +§4.3. Because every input is evaluated without consulting fence rows, +recorded outcomes, or the committed prefix, the command's outcome is +identical across the recorded and unrecorded worlds — the vacuous-prefix +oracle is gone (NEW-12). Successful succession **confers, in the same +transaction and inside its single audit event, the position-1 +initial-owner authority on the seed company where that position is +already originated** — exactly the authority origination of position 1 +would have self-conferred — so every successful successor holds +seed-completion authority by construction and no read-only capture can +strand the suffix; the _unable_ disjunct makes re-succession available +when a later designation loses that authority while staying +identity-eligible, and succession is repeatable across successive losses +(NEW-13). Condition (a)'s eligibility failure collapses to the one +predicate identity §7.1 actually defines, with a forward constraint +binding any future account-removal or account-disable contract to extend +that predicate and to preserve the epoch designation as a stable +reference (NEW-14). §1.2 now discloses both identity-surface additions — +the §7.3 finalize extension and the §7 item 12 succession command — and +succession appears in the §1.1 composed-surface inventory and the §7.8 +mapping amendment (NEW-15). Witnesses §6.7: the succession two-world +control, tenant-unprivileged successor completion, post-succession +grant-revocation re-succession, repeat succession, and empty-prefix +succession. (Revision 12 removes the conferral and the _unable_ +disjunct introduced here; it closes the same findings without them.) + +Revision 12 (sol re-review 10: NEW-12/NEW-13/NEW-14 residuals, NEW-16, +NEW-17): succession is reduced to a pure designation transfer and the +canonical seed tuples become fully epoch-derived, superseding revision +9's prefix-derived tuple set. Canonical seed payloads and scopes now +contain **no generated id and no account identifier**: a child +position references its parent by epoch-scoped canonical seed role, +resolved to the actual row server-side at execution +(canonical-reference resolution, §4.3), and position 1 carries no +initial-owner field — the ordinary top-level command's default (the +creator names itself, contract 2 §4.3) binds the initial `owner` to +the acting designation as a recorded outcome, never as payload +content. The full canonical seed tuple set is therefore +fence-independent and byte-stable absolutely: every client — fresh, +resuming, or a successor — derives identical bytes from the epoch id, +the immutable provenance, and the fixed example set alone, so a +replay after succession compares equal against every committed digest +and the historical-payload gap is closed (NEW-13). Succession itself +now writes exactly the designation update and its single audit event +— **no grant is conferred** — and condition (a) collapses to identity +§7.1 unavailability alone: the _unable_ disjunct and the +conferred-grant clause are removed, so the command reads identity, +platform-eligibility, and epoch-record state only, writes nothing +conditional, and is world-independent unconditionally — no allowed +grant transition, including an origin revoking its own position-1 +`owner` grant, can make its outcome or observables differ (NEW-12) — +and a platform admin can never parlay succession into authority over +an existing seed company: after full completion, succeeding confers +nothing at all (NEW-16). The origination authority succession +transfers is **designation-derived**: for exactly the fresh +origination of an unoriginated canonical seed position, the +hierarchy-authority component of fresh-mutation authorization is +satisfied by the current designation itself — a disclosed, scoped +amendment to contract 2 §4's evaluation (§7 item 12) conferring no +read authority, no replay authority, no standing grant, and nothing +outside the canonical seed key set — so a successor completes the +suffix by direct in-order origination, never replaying the committed +prefix, and the revocation lock that motivated the _unable_ disjunct +cannot arise (completion authority never depends on a revocable +grant). §6.1 gains the closed succession-write inventory and its +no-seed-input static assertion (NEW-17), and the Revision-10 +paragraph's origin-loss vocabulary is corrected to the banned state +identity actually defines (NEW-14). §6.7 reworked: the two-world +control now asserts equal event content, an empty grant-table delta, +and a full-command timing bound; new self-revocation two-world +refusal, designation-derived completion, post-completion +harmlessness, and post-succession replay witnesses. (Revision 13 +generalizes the designation-derived authority — which this revision +scoped to contract 2 §4 only — across every canonical position's +owning family, and adds the seed-progress query that locates the +suffix.) + +Revision 13 (sol re-review 11: NEW-18, NEW-19): the designated +client can locate the suffix, and can originate all of it. +**Seed-progress query** (NEW-18): revision 12 made every canonical +tuple derivable but left the committed-prefix length underivable — +a fresh successor's permitted inputs were identical across an +empty-prefix world and a k-committed world, so §6.7's required +never-submit-a-committed-position walk was impossible without +hidden fixture state, and blind submission could not distinguish a +committed prefix from a real collision or authorization loss. §4.3 +now defines one mapped, designation-only read surface returning +exactly the epoch's next unrecorded canonical position index (or a +completion marker): the designation screening is evaluated before +any fence state, every non-designated submitter — former +designations and platform admins included — is refused +byte-shape-identically across recorded and unrecorded worlds, the +read set is closed to position-committed existence flags plus the +designation (§6.1), and the state-dependent answer for the +designated account is the entitled disclosure that is the query's +purpose. The original origin's fresh-client resume and the +successor's completion both query first and originate in order +from the returned index; no client infers progress from refusal +shapes. **Generalized designation-derived authority** (NEW-19): +revision 12's amendment reached only contract 2 §4's +hierarchy-authority component, so a grant-less designation — an +origin that revoked its own position-1 `owner` grant, or a +tenant-unprivileged successor — could originate hierarchy +positions but not the ordinary workspace-content example +positions, whose authorization lives in RBAC §§2–3 and the +native-kanban SOT. §7 item 12 now amends the actor-authorization +component of every canonical position's owning family expressly — +contract 2 §4; RBAC §§2–3; native-kanban SOT REQ-TEN-001 / +Amendment A1 §8.1.3 — coupled and severable together, under one +mechanically decidable scope (current designation, next unrecorded +canonical position, exact server-derived tuple, in-order fresh +origination) and a defined **result-disclosure boundary**: a +successful origination's response and recorded outcome carry +exactly the command's canonical outcome fields, and a +designation-only actor's non-canonical content command is refused +by the owning contract. Witnesses §6.7: seed-progress two-world +refusal, seed-progress entitlement with the actual fresh client +run against both worlds, content-position completion in both +recovery variants, non-canonical content refusal, and the +result-disclosure witness. (Revision 14 completes this revision's +query with a full client protocol and typed completion, ratifies +the RBAC §1 exception this revision left implicit, and reconciles +the closed result schemas with contract 5's envelope.) + +Revision 14 (sol re-review 13: NEW-18/NEW-19 residuals, NEW-20, +NEW-21): the query's client protocol, the authority's ratified +boundary, the result envelope, and the refusal order are made +exact. **Query/originate loop** (NEW-18): the walk's complete +protocol is now normative in §4.3 — the query's state-derived +content is a closed discriminated union (`next` index or a typed +`complete` variant that is a result value, never an error); the +client stops on `complete`; on a refused canonical origination it +draws nothing from the refusal and re-queries, continuing only on +a strictly-later result (the benign stale-query race, where a +same-designation peer committed the position first) and stopping +to surface a genuine fault when the index is unchanged — so +progress derives from the entitled query alone under any number +of same-designation clients. Witnesses: same-designation race +(with its unchanged-index fault variant) and the completed-world +stop run of the actual fresh client. **RBAC §1 exception +ratified** (NEW-19): RBAC §1 declares its three authority layers +exhaustive, so §4.3 and §7 item 12 now name §1 itself among the +expressly amended surfaces — a narrow ratified exception making +the designation a fourth, disclosed authority source inside +exactly the mechanical origination scope and substitutable +nowhere else. The active-window boundary witness discriminates +canonical-key scope from completion-state scope: while a content +position is still next, the exact canonical tuple succeeds while +a second non-canonical item and a non-seed-workspace command +refuse in the SAME state, and post-origination reads of +predecessor- and successor-created seed content stay refused. +**Envelope reconciliation** (NEW-20): every closed response — +origination outcome and query alike — bounds its STATE-DERIVED +content while remaining an ordinary contract 5 §4 result DTO +carrying the mandated non-state correlation envelope, which +echoes the request and discloses no state; contract 5 is not +amended by the disclosure boundary. **One refusal order** +(NEW-21): the result-disclosure paragraph now restates the +operative §4.3 order instead of contradicting it — fresh-mutation +authorization first (its refusal is the owning family's), then +the seed-boundary gate before fence presence and +canonical-reference resolution, the constant shape scoped to +callers that reached the gate — and the child-race control +asserts the refusal class, pinning the order mechanically, with +the cross-surface shape control asserting one constant conflict +shape across the gate, succession, and query surfaces. (Revision 15 +extends this revision's envelope reconciliation to the +bootstrap-status response and corrects the active-window witness's +mutant attribution.) + +Revision 15 (sol re-review 14: NEW-20 residual, NEW-22): the +envelope reconciliation reaches the last closed response, and the +active-window witness names its mutants correctly. +**Bootstrap-status envelope** (NEW-20 residual): §2.3's closed +two-field response now bounds its STATE-DERIVED content only — +pre-epoch `epoch` plus `mode`, post-epoch `epoch` alone, no other +state-derived field — while the response remains an ordinary +contract 5 §4 result DTO whose fixed envelope frame carries the +request's own correlation ids, echoing the caller's request and +deriving from no stored record; §6 item 2's closed-field assertion +and §7 item 2's disclosure description follow. Contract 5 is not +amended. **Mutant attribution** (NEW-22): the active-window witness +now states that branches (a), (b), and (c) each start from an +isolated copy of the same incomplete pre-state (branch (a) commits +a state change), attributes branch (b)'s detection to the +seed-workspace-scoped incorrect evaluator, and names the separate +all-workspace incorrect evaluator that branch (c) catches — the +seed-workspace-scoped mutant, correctly refusing outside the seed +set, passes branch (c), so the two branches detect distinct +mutants. No other change. + +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 exactly one disclosed + exception**: every wizard operation except step 3's finalize is an + ordinary outbound Gateway call issued from the wizard's web modules + (or the equivalent scripted sequence), and the exception is the + §3.3 **bootstrap finalize command** — one server-side composed + transaction on identity §3's bootstrap surface, reachable only + while the bootstrap epoch is open, disclosed and ratified as the + §7.3 architecture amendment. No other server-side module composes + wizard operations. Contract 5 §6.1's outbound-call inventory, + scoped to the wizard modules, therefore sees the wizard's complete + outbound call set; the finalize command's internally composed + writes are proved complete by the dedicated §6.1 finalize-write + inventory, not by the outbound inventory. + 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 1–2), the + identity bootstrap and registration surface (step 3, including the + §3.3 finalize command, the §4.3 seed-origin succession + command, and the §4.3 seed-progress query), 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 undisclosed 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 + exceptions are exactly the **two disclosed amendments to identity + §3's epoch surface**, each severable and ratified with this + contract: the **§7.3 finalize extension** — the wizard drives the + bootstrap writer defined by identity §3, whose constraints + (§3.1–§3.6) bind, with this contract's single change extending the + epoch-closing command to carry the §3.3 value set inside the same + transaction — and the **§7 item 12 seed-origin succession command** + (§4.3), one mutating epoch-record command whose closed write set + is the designation update and its single audit event. Beyond those + two amendments, nothing is added to identity §3; the further + disclosed amendments are §7 item 12's + **designation-derived origination authority** — a scoped change, + for canonical seed origination only, to the actor-authorization + component of each canonical position's owning family (contract 2 + §4's hierarchy authority; RBAC §§2–3's workspace-content + authorization; the native-kanban SOT's workspace-scoped command + authorization, REQ-TEN-001 / Amendment A1 §8.1.3; and, because + RBAC §1 declares its three authority layers exhaustive, a + narrow ratified exception to RBAC §1 itself, scoped to exactly + that origination and substitutable nowhere else), conferring no + grant and no read authority — and §7 item 12's **seed-progress + query** (§4.3), one designation-only mapped read surface whose + entire state-derived content is the closed §4.3 discriminated + union — the epoch's next unrecorded canonical seed position + index, or a typed completion variant — inside the ordinary + contract 5 §4 result envelope, and nothing else; no + undisclosed authority exists; all of these surfaces appear in + the §1.1 composed-family inventory, the §7.8 mapping amendment, + and §6.1's inventories, so the D8 mapping and authorization-parity + witnesses cannot omit 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's **state-derived + content 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 the exact wire-token pair **`open`** + and **`completed`** — identity §3 names the two epoch states in + prose but defines no wire enumeration, so this contract pins the + tokens, as the second clause of the disclosed §7.9 amendment — and + `mode` — the recorded mode value, present **only while the epoch + is open** and absent from the state-derived content once the epoch + has completed. No other state-derived field exists in the + response, and the response remains an ordinary contract 5 §4 + result DTO: its fixed envelope frame carries the request's own + correlation ids — echoing the caller's request, deriving from no + stored record, and disclosing no state — so the closed schema + bounds disclosure of state and amends nothing in + contract 5. 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 and the seed company name + are both settings values: the company name is recorded under the + declared settings key **`bootstrap.seed-company-name`** — the §3.4 + seed parameter, a disclosed drafting addition (§7.11) — committed + by step 3's finalize command among the ordinary settings writes and + readable through the ordinary settings read surface. The company + name feeds step 4's company creation. **The seed parameter is + immutable seed provenance:** it is written exactly once, by the + finalize transaction, and every later write to the key — through + any surface, any actor — is refused by the settings family (a + disclosed immutable-key rule, §7.11). It records what the seed + sequence was derived from, not what the company is currently + named: the current name's canonical home is the company row, and + renaming the seed company is the ordinary hierarchy rename + command against that row, never a settings edit. 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) the system name and other settings + apply directly through the settings commands; the company-name + field renders the company row's current canonical name and + applies a change as the hierarchy rename. +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. The + PRD step list's SSO option **for the initial user is not + implemented in v1 — a disclosed PRD deviation (deferment, §7.10)**: + no v1 step configures a provider before finalize and no v1 step + links the first admin to a provider afterwards, so the initial user + cannot be SSO-created or SSO-linked in v1. SSO first becomes + available to accounts created post-epoch (providers configured and + JIT-enabled after finalize; identity §5 governs every SSO-created + account) — those are different users, not a satisfaction of the + initial-user option. 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 commits + every carried value through the ordinary settings and identity + configuration write implementations — the same code paths the + post-epoch commands use; no parallel write path. The executing + authority is the **bootstrap writer's own authority as amended by + §7.3**, never an authentication of the caller: the finalize + request begins and ends unauthenticated, and creating the admin + row does not authenticate the caller as that admin. Each carried + write is attributed in audit to the newly created admin as the + accountable principal the transaction establishes; the admin + authenticates afterwards by ordinary login. + 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, read + from the `bootstrap.seed-company-name` settings value, §3.1) and + the fixed example set (§4.3). **Canonical seed tuples are fully + epoch-derived and account-free.** No canonical seed payload or + scope contains a generated id or an account identifier: a child + position references its parent by the epoch-scoped canonical seed + role ("the seed company of this epoch", "the seed estate of this + epoch"), which the command layer resolves to the actual canonical + row server-side at execution (§4.3 canonical-reference + resolution), and position 1 carries no initial-owner field — it + takes the ordinary top-level command's default, the creator + naming itself (contract 2 §4.3), so the initial `owner` binding + is a property of the recorded outcome (the acting designation at + origination time), never of payload bytes. A resumed run — + including a fresh client holding none of the original run's + transient state, and a §4.3 successor holding no authority over + any committed record — reconstructs the same ordered sequence, + the same deterministic §4.3 keys, and byte-identical payloads + from the epoch id, the immutable seed parameter, and the fixed + example set alone, reading no recorded outcome. Because the seed + parameter is immutable (§3.1), the re-derived sequence is + **byte-stable absolutely** — across every re-run, resume, and + §4.3 succession: the same keys carry the same payload digests + whoever derives them, so already-committed mutations replay + (recorded outcomes) rather than collide, regardless of any + hierarchy rename performed since, and a replay after succession + compares equal against every committed digest by construction — + no payload ever named the origin. Because every seed + submission declares §4.3's `shared` replay mode, committed + positions replay for + whichever currently eligible admin holding §4.3 target-result + read authority on the recorded seed targets performs the re-run, + not only the actor the fence rows record. The §4.3 fence, not the + parameter's presence or absence, is what prevents re-seeding; the + parameter is provenance the derivation reads, never a value any + later step may change. + The first company is created by the ordinary top-level company + command under §5.2's eligibility policy, with the epoch's §4.3 + seed-origin account — the account the designation names at + origination time, initially the new admin — as actor; the + command's default names the actor as initial `owner` in the same + audited operation (contract 2 §4.3), so the owner binding follows + the acting designation through the outcome, not through any + payload field; the §4.3 seed-boundary gate reserves + origination of the canonical seed tuples to the epoch's current + seed-origin account — initially this admin, thereafter changed + only by §4.3 seed-origin succession — while + the same command outside the canonical seed key set follows §5.2 + unchanged. The initial estate, initial project, and initial + workspace with seeded example data (D4, D11) follow through hierarchy + commands (contract 1 §5.1) under the parent-`owner` authority + contract 2 §4.3 requires — for canonical seed origination, + satisfied by the §4.3 designation-derived authority, which the + original admin holds as designation exactly as a successor + would. 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; their actor-authorization + component — RBAC §§2–3's workspace-content authorization, and + the native-kanban SOT's workspace-scoped command authorization + (REQ-TEN-001, Amendment A1 §8.1.3) for the kanban example + positions — is, for canonical seed origination only, likewise + satisfied by the §4.3 designation-derived authority, under the + same mechanical scope and the §4.3 result-disclosure boundary + (§7 item 12); every other component of each content command's + evaluation (validation, eligibility, collision and replay + rules) is unchanged, and outside the canonical seed key set + every content command's authorization is untouched. +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, the + submission's declared **replay mode** — `actor-bound` (the + default) or `shared` (§7.4) — 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, the + submission's declared replay mode equals the recorded row's, and + the recorded scope and payload digest equal the submission's, + the submitter must pass **target-result authorization** — in + every replay mode. Returning a + recorded outcome is a read of the canonical records that + outcome references, and neither fresh-mutation authorization + nor recorded-actor identity is + read authorization on those records: every replay, `shared` or + `actor-bound`, requires the submitter to + hold, at replay time, read authority on every canonical record + the recorded outcome references, under each record's owning + contract's read-authorization rules (for the seed targets, the + contract 2 grant model — RBAC §1.1 platform-admin standing + confers none of it). Actor equality is the additional + `actor-bound` condition, never a substitute for target-result + authorization: an `actor-bound` row replays only for the + recorded actor, and only while that actor holds live + target-result read authority — an original actor whose grants + on the referenced records were since revoked is refused, not + replayed (witness §6.7). A submitter who passes the fresh-mutation + check but fails target-result authorization is refused with the + same single bounded conflict error as a collision below — + constant in shape, identifying no record, disclosing nothing of + the recorded outcome or its targets — so the refusal confirms + no tenant target's existence or identity and RBAC §7's + no-existence-oracle rule is preserved. On replay the command + executes nothing and returns the recorded outcome. A shared + replay adds no **mutation** audit event and leaves the fence + row untouched — audit attributes each mutation to the actor who + performed it, and the recorded acting principal is immutable — + but it appends a **replay access event**: a distinct + non-mutation audit event class recording the replaying actor as + accessing principal, the current request's correlation ids + (contract 5 §4.3), and a reference to the fence row whose + outcome was returned. The current submission's correlation + travels only in that access event and the trace layer; the + recorded outcome and its original mutation event are returned + and retained unchanged. Every access to a recorded outcome is + thereby attributed to its accessing actor without a duplicate + semantic mutation event ever existing. + - **Collision.** A submission whose (operation, key) pair is + recorded but whose scope, payload digest, or declared replay + mode differs — or, against an `actor-bound` row, whose actor + differs — is + refused with a single bounded conflict error (contract 5 §4.2); + it executes nothing and discloses nothing of the recorded + outcome. + - **Shared-declaration boundary and canonical-reference + resolution.** `shared` is a server-verified, seed-only policy, + never a caller privilege. The whole boundary is + fence-independent. The **canonical seed key set** — the + (operation identifier, key) pairs of §3.4's ordered seed + sequence — is derived from the epoch id and the fixed + seed-role list alone: the keys are deterministic and depend on + no generated id, so membership is decidable before any seed + mutation has run and without consulting the fence table. The + full **canonical seed tuple set** — every position's + authorization scope and payload digest — is likewise derived + from the epoch id, the immutable `bootstrap.seed-company-name` + provenance, and the fixed example set alone: no canonical seed + payload or scope contains a generated id or an account + identifier (§3.4). Where a child position must name its + parent, the payload carries the parent's **epoch-scoped + canonical seed role** ("the seed company of this epoch"), and + the command layer resolves that reference to the actual + canonical row server-side at execution — **canonical-reference + resolution**, available to exactly the canonical seed tuples + and nothing else, with the resolved rows recorded in the + position's outcome. Every tuple is therefore derivable at any + canonical state by any party from canonical settings state + alone, but **origination stays in order**: a canonical + position is originated only when every predecessor is + committed, and resolution of a reference to an uncommitted + predecessor fails closed. A submission declaring `shared` + whose (operation, key) is outside the canonical seed key set + or whose tuple does not equal its position's derived tuple — + and any origination submission for a position past the next + unrecorded one (out of order) — is refused with a single + bounded refusal (contract 5 §4.2 validation class) that + executes nothing and records no fence row. No other operation + can carry a shared declaration, so no shared fence row can + exist outside the seed sequence — the seed-only rule is + enforced by the command layer, not by wizard convention. + - **Seed-boundary gate and origination.** The epoch record holds + one **seed-origin designation**: at finalize it names the + account the §3.3 finalize transaction created as the epoch's + first admin (identity §3), and afterwards it changes through + exactly one path — the **seed-origin succession** command below + — never by any other write. The epoch's **seed-origin account** + is the account the designation currently names. Every mutating submission + whose (operation, key) is in the canonical seed key set — + whatever replay mode it declares — passes, after + fresh-mutation authorization and before the fence table is + consulted, the **seed-boundary gate**: the submitter is the + seed-origin account, or holds §4.3 target-result read + authority on the canonical records the position's recorded + outcome references. A submitter satisfying neither is refused + with the same single bounded conflict error as a collision — + and because the gate is evaluated without consulting fence + presence, the refusal is byte-shape-identical whether the seed + fence and its targets exist or not: the recorded and + unrecorded worlds are indistinguishable to that submitter, no + mutation or fence row is created in either, and RBAC §7's + no-existence-oracle rule holds at the seed boundary itself, + not merely at an existing fence (witness §6.7). For an + unrecorded position no recorded outcome exists to hold read + authority on, so only the seed-origin account can proceed to + origination: §5.2 eligibility alone never originates a seed + fence, which closes the eligible-wrong-actor race on the + top-level seed-company key. **Origination.** A seed fence row + not yet recorded is originated only by the seed-origin account + executing its seed mutation in order, passing the full + fresh-mutation authorization for that seed command — §5.2 + eligibility and identity §7.1 eligibility evaluated fresh + against the submitter, with the actor-authorization component + satisfied by the **designation-derived authority**: for + exactly the fresh origination of a currently-unoriginated + canonical seed position, the current designation itself + satisfies the actor-authorization component of the position's + **owning command family** — for the top-level and child + hierarchy positions, the parent-`owner` (or top-level) + authority contract 2 §4 requires; for the ordinary + workspace-content example positions, the workspace-content + authorization RBAC §§2–3 require and the workspace-scoped + command authorization the native-kanban SOT requires + (REQ-TEN-001, Amendment A1 §8.1.3) — coupled disclosed + amendments to each named surface (§7 item 12), severable + together, that confer no read authority, no replay authority, + no standing grant, no authority over any committed record, + and nothing outside the canonical seed key set. Because RBAC + §1 states its three authority layers exhaustively ("none + substitutable"), this authority is also, expressly, a narrow + ratified exception to RBAC §1's exhaustive-layer rule (§7 + item 12): within exactly the mechanical scope below — the + current designation, the next unrecorded canonical position, + the exact server-derived tuple, a fresh in-order + origination — the designation is a fourth, disclosed + authority source; outside that scope it substitutes for no + layer, anywhere, ever. The + authority's scope is mechanically decidable per submission: + the submitter is the epoch's current designation, the + (operation, key) is the next unrecorded canonical position, + the payload and scope equal that position's server-derived + tuple exactly, and the submission is a fresh in-order + origination; every other component of the owning family's + evaluation (validation, §5.2 eligibility, identity §7.1 + eligibility, collision and replay rules) is evaluated fresh + and unchanged; the authority is evaluated per submission and + writes nothing beyond the command's own canonical writes; a + refused submission records no row (no-error replay below). + **Result-disclosure boundary.** A successful origination's + response and recorded outcome carry, as their entire + STATE-DERIVED content, exactly the command's canonical + outcome fields — the created row id, any + canonical-reference-resolved parent id, the canonical key, + and the payload digest — and nothing else state-derived: no + listing, no attribute of any pre-existing record beyond the + resolved parent id the outcome must record, and no grant- or + fence-table content. The response remains an ordinary + contract 5 §4 result DTO: it additionally carries exactly + the non-state envelope metadata contract 5 §4.1/§4.3 mandate + for every mapped result — the request's own correlation ids + in the fixed envelope frame — which echoes the caller's + request, derives from no stored record, and discloses + nothing about any world's state; the boundary bounds + disclosure and amends nothing in contract 5. Refusals on + canonical seed keys follow the evaluation order this section + fixes and no other: fresh-mutation authorization is + evaluated first — a submitter it refuses receives the owning + command family's ordinary authorization refusal — and the + seed-boundary gate is evaluated next, before fence presence + and before canonical-reference resolution; the gate's + constant-shape conflict is the refusal of exactly the + callers that passed fresh-mutation authorization and failed + the gate (witness §6.7). The recorded actor of every shared row is + therefore the account that was the epoch's seed-origin at that + position's origination, authorized for the mutation the row + fences. Recorded positions are replayable by any admin holding + target-result read authority (§6.3). + - **Seed-origin succession.** Loss of the seed-origin account + does not strand the epoch (D4, §4.4). The designation changes + through exactly one mutating command, an amendment to identity + §3's epoch surface disclosed in §7 item 12: a platform admin + submits succession naming itself the epoch's seed-origin. + Succession is a **pure designation transfer**. It reads + identity state, platform eligibility, and the epoch record + only — never fence rows, recorded outcomes, grant rows, or + hierarchy records — and its complete write set is the epoch + record's designation update plus one audit event (closed + inventory, §6.1). It confers no grant of any kind. The command + succeeds only when BOTH: (a) the current seed-origin account + is **unavailable** — it fails identity §7.1's + account-unavailability predicate (today exactly the + better-auth ban; §5.2 records that no separate deactivated + state exists and identity §7.3 defers hard deletion) — and no + other origin-side condition exists: the origin's grant state + is never read, so no allowed grant change (including an origin + revoking its own position-1 `owner` grant) can make + succession's outcome differ between two worlds whose identity, + platform, and epoch state agree; and (b) the submitter is an + identity-§7.1-eligible platform admin holding §5.2 top-level + create eligibility. Condition (b) references no seed record + and no prefix: a tenant-unprivileged platform admin passes or + fails it identically whether or not any seed position is + committed. Because no input and no write depends on seed + state, the command's observables — response bytes, event count + and content, grant-table state — and its timing are identical + across any two worlds whose identity, platform, and epoch + state agree, whatever seed state either holds: succession + carries no existence oracle, unconditionally (witness §6.7 + two-world controls, self-revocation pair included). Any future + contract adding an account-removal or account-disable + mechanism MUST extend identity §7.1's single unavailability + predicate to cover it and MUST preserve the epoch record's + designation as a stable reference across it (a retained + identifier or tombstone — never a cascade that rewrites or + nulls the designation outside this command). A submission + failing either condition is refused with the same single + constant-shape bounded conflict as the seed-boundary gate, + byte-shape-identical whichever condition failed and whether + any seed fence exists, executes nothing, and appends no event. + Successful succession, in one transaction, updates the + designation in the epoch record and appends exactly one + ordinary mutation audit event recording the prior designation, + the new designation, and the acting principal — nothing else; + it writes no grant, rewrites no fence row and no recorded + outcome — rows already recorded immutably retain their + original actor. What succession transfers is the origination + role alone: the §4.3 designation-derived authority to + originate the unoriginated suffix, and nothing else. Because + that authority derives from the designation itself, never from + a revocable grant, no inability state exists — a designation + that lost every grant still completes the suffix — and + succession over a fully completed sequence is harmless by + construction: there is nothing left to originate, so the + successor gains no authority over any existing record. A + successor who originates position 1 becomes the seed company's + initial owner exactly as any §5.2-eligible creator of a + top-level company would (contract 2 §4.3 default) — an + authority §5.2 already grants, not an escalation. Succession + recovers **seed-sequence completion**, never tenant ownership: + recovering ownership of an existing company whose owners are + all unavailable is an account-administration surface of the + identity and RBAC contracts, expressly out of this contract's + scope. Concurrent successions serialize on the epoch record: + exactly one submitter commits and becomes the seed-origin, and + the loser, re-evaluated against the committed winner, fails + condition (a) — the now-current origin is identity-eligible — + and receives the constant-shape refusal. The seed-boundary + gate and the origination rule always read the epoch record's + current designation: after succession the successor originates + the remaining suffix in order under its own full + fresh-mutation authorization (§4.3 designation-derived + authority plus its own eligibility), locating that suffix + through the seed-progress query below and deriving every + tuple from canonical settings state alone — no replay of any + committed position and no read of any recorded outcome is + needed or implied — and the fence rows it + originates record the successor. Succession is repeatable + across successive origin losses. Factory reset (§4.2) remains + the only path to a new epoch; it is never required to complete + an interrupted seed sequence. + - **Seed-progress query.** Locating the unoriginated suffix is a + disclosed, mapped read surface, never an inference from + refusal shapes: the **seed-progress query** returns, as its + entire state-derived content, exactly one value from a + closed discriminated union of two result variants — `next`, + carrying the index of the epoch's next unrecorded canonical + seed position, or `complete`, carrying no index, when every + position is recorded — and nothing else state-derived. The + `complete` variant is a typed result value on the success + path, never an error shape and never a sentinel index; the + response is an ordinary contract 5 §4 result DTO whose only + other content is the mandated non-state envelope metadata + (the request's own correlation ids), which echoes the + request and discloses no state. It is authorized for + exactly the account the epoch's designation currently names, + and that screening is evaluated first, before any fence state + is consulted: every other submitter — a former designation, a + platform admin, and an admin holding target-result read + authority included — is refused with the same single + constant-shape bounded conflict as the seed-boundary gate, + byte-shape-identical whether any seed fence exists or not, so + the recorded and unrecorded worlds stay indistinguishable to + every non-designated actor and RBAC §7's no-existence-oracle + rule holds on this surface too. For the designated account + the returned index is intentionally state-dependent — that + disclosure is the query's purpose, and it is bounded: the + query reads only which canonical positions have committed + fence rows (position-committed existence) plus the epoch + record's designation, never a recorded outcome, a payload or + digest, a resolved id, an acting principal, or any grant + state, and its closed read set is statically asserted (§6.1). + The query writes nothing and appends no event. A resuming + designated client — the original origin on a fresh client and + a §4.3 successor alike — runs the **query/originate loop**, + the walk's complete protocol: submit the query; on + `complete`, STOP — the walk is finished and the client + submits no origination and no other seed-key command; on + `next` index i, originate position i, deriving its tuple + from canonical settings state alone, and on success continue + the loop from a fresh query or the next index. If an + origination on a canonical seed key is refused, the client + draws NO conclusion from the refusal itself — refusal shapes + are not progress signals — and re-submits the entitled + query: a result strictly beyond i (a greater index or + `complete`) means another client of the same designation + committed position i between query and origination — the + **stale-query race**, benign by construction — and the loop + continues from the fresh result; a result that still names i + means the refusal was a genuine fault, and the client stops + and surfaces the refusal without submitting further. The + loop's only progress source is the query, so the walk is + race-safe under any number of same-designation clients: each + position commits exactly once (Concurrency below), and every + client either advances on its own successes or + re-synchronizes through the query it is entitled to. An + admin holding target-result read authority may instead walk + the sequence and receive recorded outcomes as replays + (§6.3). No client is required to infer progress from + refusals, and no non-designated actor can. + - **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 + (fresh-mutation authorization, the seed-boundary gate where + the key is a seed key, and target-result 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, and every seed submission declares the `shared` + replay mode: the seed set is a per-epoch singleton (§4.4), derived + from immutable provenance (§3.4), so whichever currently eligible + admin holding target-result read authority on the recorded seed + targets performs a re-run or resume must replay the recorded + outcomes rather than collide on actor identity — re-runnability is + not restricted to the original acting admin (witness §6.3). All + other submissions default to `actor-bound`; nothing in this + contract declares `shared` outside the seed sequence, and the + shared-declaration boundary makes that exclusivity + server-enforced: a shared declaration outside the canonical seed + tuple set is refused, not merely unconventional. Correlation + ids (contract 5 §4.3) remain pure trace + linkage and carry no idempotency semantics; a shared replay's + current correlation is carried by its §4.3 replay access event, + never by rewriting the recorded outcome or its mutation event. 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 4–5 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 resumed designated client runs the §4.3 query/originate + loop — querying, originating the returned index, stopping on + the typed completion variant, and re-querying (never + interpreting the refusal) if a canonical origination is + refused — re-deriving every tuple from canonical state; a + target-authorized admin's re-run may instead re-submit the full + ordered seed sequence with the same deterministic keys, + already-committed mutations returning their recorded outcomes — + either way only the remainder executes, without duplication and + without compensating rollback of completed commands. There is no + wizard-level transaction spanning steps. Loss of the seed-origin + account mid-sequence — identity §7.1 unavailability — is likewise + recoverable without a new epoch: §4.3 seed-origin succession + designates an eligible successor, and the resumed run locates + the remaining suffix through the same §4.3 query/originate + loop and completes it under the successor's designation-derived + authority — the ordinary workspace-content example positions + included (§4.3, §7 item 12) — deriving every tuple from + canonical settings state alone: no grant is conferred and no + committed position is replayed. Succession is repeatable, so + interrupted runs strand nothing even across successive origin + losses. Origination authority — and suffix location, the §4.3 + seed-progress query — is designation-derived (§4.3), never + grant-dependent, so no revocation — including an origin + revoking its own position-1 `owner` grant — can strand the + suffix while the origin remains available. + +## 5. Seeding authority (resolves contract 2 review NEW-1) + +1. During the bootstrap epoch, the bootstrap writer's authority + (identity §3, as amended by the §7.3 finalize extension) covers + creating the first account, closing the epoch, and committing the + §3.3 carried values inside the finalize transaction — nothing + else. 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: parent + `owner` authority, no automatic grant needed — for canonical seed + origination, the parent-authority component is satisfied by the + §4.3 designation-derived authority (§7 item 12); outside the + canonical seed key set the rule is unchanged. +4. Example-content creation inside the wizard (the fixed §3.4 + example set) follows each item's owning content contract — RBAC + §§2–3's workspace-content authorization and, for the kanban + examples, the native-kanban SOT's workspace-scoped command + authorization (REQ-TEN-001, Amendment A1 §8.1.3) — with the + same canonical-seed-origination exception: for exactly those + positions, the actor-authorization component is satisfied by + the §4.3 designation-derived authority under §7 item 12's + mechanical scope and the §4.3 result-disclosure boundary. + Outside the canonical seed key set every content rule is + unchanged, and a designation-only actor's non-canonical content + command is refused by the owning contract (witness §6.7). + +## 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's outbound calls because §1.1 + forbids server-side wizard composition outside the single declared + §3.3 finalize handler, and the witness statically asserts that + scoped prohibition (no server-side module other than the declared + finalize handler composes wizard operations). The inventoried + operation set is asserted equal, in both directions, to the §1.1 + declared family list. **Finalize-write inventory:** the finalize + handler's internal write set is statically enumerated and asserted + equal, in both directions, to the §3.3 carried-value list — the + admin creation and epoch transition plus the settings writes + (including `bootstrap.seed-company-name`), the registration-mode + write, and the applicable JIT writes, nothing else; each internal + write is asserted to invoke the owning command family's ordinary + write implementation (no parallel write path); and the handler is + asserted refused once the epoch has completed (identity §3.4). + **Succession-write inventory:** the §4.3 succession handler's + internal write set is statically enumerated and asserted equal, in + both directions, to: the epoch record's designation update plus + its single audit event (and the audit family's required outbox + record where one exists) — no `hierarchy_grants` write, no + fence-table write, no settings write, no hierarchy or content + write, nothing else; and the handler is statically asserted to + read no fence table, no recorded outcome, no grant table, and no + hierarchy record — its inputs are identity state, platform + eligibility, and the epoch record only (§4.3). + **Seed-progress-query inventory:** the §4.3 seed-progress query + handler's read set is statically enumerated and asserted equal, + in both directions, to: the epoch record's current designation + (its authorization input, screened first) and the + position-committed existence flags of the epoch's canonical + seed keys — no recorded outcome, no payload or digest, no + resolved id, no acting principal, no grant table, no hierarchy + or content record; its write set is asserted empty (no event, + no row), and its response DTO is asserted closed in both + halves: its state-derived content is exactly the §4.3 + discriminated next-index-or-complete union, its only other + content is contract 5 §4's non-state envelope metadata (the + request's correlation ids), and no further field exists — the + closed-schema assertion covers the full wire shape, both + variants included. 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's state-derived content matches §2.3's + closed two-field schema + exactly while the epoch is open — the epoch field carrying one of + §2.3's two exact wire tokens — and after the epoch completes + contains the epoch field only — the mode field absent + (closed-field assertion on the state-derived content in both + phases, with the response's contract 5 §4 envelope asserted to + carry the request's own correlation ids — present, equal to the + request's, derived from no stored record — and no further + state-derived field in either + phase); 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. + **Seed-provenance witnesses (§3.1, §3.4):** rename the seed + company through the hierarchy command, delete the wizard's + seed-node bookkeeping cache, then re-run to completion — + the re-derived seed sequence carries the same keys and payload + digests as the first run (asserted digest equality), every seed + submission replays with the recorded outcome, zero new nodes are + created, the run completes, and the company keeps its renamed + name — the deleted cache proving the renamed row was resolved + from canonical state alone (§1.3), not from a stored id. A re-run + submitting a different company name renames the company row and + commits no settings write to the seed key, **and that same run**, + with the bookkeeping cache likewise deleted beforehand, continues + through step 4 deriving the seed sequence from the immutable seed + parameter — asserted to carry the first run's keys and payload + digests, not digests of the newly submitted name — replays every + seed outcome, creates zero new nodes, zero new users, and zero + new grants, and completes; a direct post-epoch + settings write to `bootstrap.seed-company-name`, by any actor, is + refused; and a control run that force-mutates a seed payload + digest receives the §4.3 collision refusal, proving the fence + still discriminates. + **Second-admin re-run witness (§4.3 shared replay):** after admin + A's completed first run, create a second account B and grant it + platform-admin, the hierarchy authority the seed commands + require, and **explicit target-result read authority on every + recorded seed target** — a contract 2 grant conferring read on + the seed company and its seeded children (B is freshly + authorized with explicit target authority, and no text restricts + re-runs to A); delete the bookkeeping cache; B re-runs the + wizard to completion making no changes — every seed submission + replays with A's recorded outcome (asserted by mutation-count + and mutation-audit-event-count equality across the run, the + fence rows still recording A as acting principal), exactly one + §4.3 replay access event exists per replayed submission, each + naming B as accessing principal and carrying B's run's + correlation ids while referencing A's fence row, zero new + hierarchy nodes, users, grants, or example content exist, and + the run completes. + **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 mutation-audit-event-count equality); the same + key with a + changed payload digest is refused with the single bounded conflict + and executes nothing; the same key and payload submitted by a + different authorized actor against an **actor-bound** fence row (a + control row recorded outside the seed sequence) is refused with + the same single bounded conflict (actor mismatch) and executes + nothing, while against a **shared** row (every §3.4 seed fence) a + different authorized actor holding target-result read authority + replays with the recorded outcome, executing nothing, adding no + mutation audit event, and appending exactly one replay access + event naming the replaying actor and its correlation ids, the + fence row still recording the original actor; a + submission whose declared replay mode differs from the recorded + row's is refused with the single bounded conflict and executes + nothing; the same key, + actor, and payload submitted against a different authorization + scope is likewise refused (scope mismatch) 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 — asserted against a shared seed fence, + proving shared replay never bypasses fresh authorization. + **Target-authorization and boundary witnesses (§4.3, NEW-9):** + an **unauthorized-target shared replay** — a platform admin + holding §5.2 fresh-create eligibility but no contract 2 grant on + the seed company derives the canonical seed tuple per §3.4 and + submits it with the recorded `shared` mode — is refused with the + single bounded conflict, and the refusal response is asserted + byte-shape-identical to the changed-digest collision refusal + above (same error class, same fields, no record identifier, no + scope detail beyond the caller's own submission), executes + nothing, changes no fence row, and appends no mutation audit + event — proving the recorded target is neither returned nor + confirmed to exist and RBAC §7's no-existence-oracle rule holds + at the fence; the **two-world seed-boundary control (§4.3 + seed-boundary gate)** — the SAME eligible non-originator actor + submits the exact canonical seed-company tuple in two prepared + worlds: one where the seed fence and its targets exist (the + recorded world) and one freshly finalized epoch where they do + not (the unrecorded world, before any seed command has run) — + and in both worlds receives the identical bounded conflict + refusal (asserted byte-shape-identical across the two worlds and + to the collision refusal), executes nothing, and creates no + mutation, fence row, or hierarchy node in either — proving the + response is computed without consulting fence presence, the + recorded and unrecorded worlds are indistinguishable to that + actor, and no eligible wrong actor can originate the top-level + seed fence; a **non-seed shared declaration** — an ordinary + hierarchy or content command whose tuple is outside the + canonical seed tuple set, submitted with `shared` declared by an + actor fully authorized for the mutation — is refused with the + §4.3 validation refusal, executes nothing, and records no fence + row (asserted absent); an **out-of-order origination** — + with the seed prefix committed through position k, the + seed-origin account submits the position k+2 canonical tuple + (past the next unrecorded position) — and is refused with the + §4.3 validation refusal, executes nothing, and records no fence + row, proving in-order origination is enforced even though every + tuple is derivable at any state; an **unrecorded-seed-key + race** in two variants — (child variant) with one child seed + tuple deliberately left unrecorded, an actor lacking that seed + command's hierarchy authority races the seed-origin account's + resume for the same (operation, key): the unauthorized + submission receives the owning command family's ordinary + authorization refusal — asserted NOT the seed-boundary gate's + constant-shape conflict, pinning the §4.3 evaluation order in + which fresh-mutation authorization refuses before the gate is + reached — and records no + fence row, the origin account's submission executes afresh, and + the resulting fence row records the seed-origin account; + (top-level variant, NEW-9) with the seed-company tuple + unrecorded, an eligible platform admin who is not the + seed-origin account — passing §5.2 fresh-mutation authorization + in full, since the top-level command requires no hierarchy + authority — races the seed-origin account for the seed-company + (operation, key): the non-originator receives the constant + bounded conflict refusal from the seed-boundary gate and + records no fence row and no company, the seed-origin account + executes afresh, and the resulting fence row records the + seed-origin account — proving origination of a missing seed + fence is bound to the seed-origin account, not to eligibility + alone; an **actor-bound lost-target-grant replay (NEW-10)** — an + actor creates a non-seed top-level company under an + `actor-bound` key, grants a second account `owner`, and the + second account then revokes every grant the creator held on the + company; the creator, still authenticated and eligible, + resubmits the exact recorded (operation, key, scope, payload, + mode) tuple — actor equality holds but live target-result + authorization fails, so the submission is refused with the + single bounded conflict, executes nothing, returns nothing of + the recorded outcome, and appends no access or mutation event; + re-granting the creator read authority and resubmitting returns + the recorded outcome — proving actor equality is never a + substitute for live target-result read authority on any replay + mode; **seed-origin succession witnesses (§4.3, NEW-11 through + NEW-17):** a **succession recovery** — the seed-origin account + commits a proper seed prefix and is then banned (identity §7.1); + an eligible platform admin holding §5.2 top-level create + eligibility submits succession, the epoch record's designation + changes to the successor with exactly one mutation audit event + recording the prior designation, the new designation, and the + acting principal — asserted to write no grant row and touch no + fence row — and the successor's resumed run submits the §4.3 + seed-progress query — asserted to return exactly the first + unrecorded index — derives the + remaining tuples from canonical settings state alone and + originates the suffix in order from that index, never + submitting a committed + position: zero replay access events name the successor, zero + grant rows name the successor, the mutation count equals exactly + the suffix length, the new fence rows record the successor, the + pre-succession rows immutably retain the original origin, and + the full seed set completes with no factory reset and no new + epoch; an **origin-available succession refusal** — the same + eligible admin submits succession while the current origin + remains §7.1-eligible — is refused with the single + constant-shape bounded conflict (asserted byte-shape-identical + to the collision refusal), changes no epoch record, and appends + no audit event; a **succession two-world control (NEW-12)** — + the SAME identity-eligible, §5.2-create-eligible platform admin + holding no grant on any seed record submits succession in two + prepared worlds with the current origin banned in both: one + where a proper seed prefix stands committed and one freshly + finalized epoch with no position committed — and in BOTH worlds + the command succeeds, the designation changes to the submitter, + and exactly one succession audit event appends, with the worlds + asserted equal in response bytes (modulo run-scoped + identifiers), in audit event content (the same field set and + classes, no seed reference and no grant reference in either), + and in grant-table delta (empty in both), and the full command + execution asserted within a fence-independent timing bound (it + consults no fence row and no grant row); the control is repeated + with a submitter failing condition (b) — refused + byte-shape-identically in both worlds, no record change, no + event in either — proving succession's outcome and observables + are a function of identity, platform, and epoch state only; a + **self-revocation two-world refusal (NEW-12)** — world U holds a + freshly finalized epoch with no seed position committed; in + world R the origin A originates position 1 (the outcome names A + initial owner by the contract 2 §4.3 default) and then, still + eligible, revokes its own `owner` grant on the seed company + (RBAC §4.1 authorizes it); identity, platform, and epoch state + now agree across U and R; an eligible platform admin B submits + succession in both worlds and is refused byte-shape-identically + in BOTH (the origin is available; grant state is not an input), + with no event and no record change in either — proving no + allowed grant change opens succession or leaks seed state; a + **seed-progress two-world refusal (NEW-18)** — worlds U (no + seed position committed) and P (positions 1..k committed) agree + on identity, platform, and epoch state; a non-designated actor + — an eligible platform admin, a former designation after + succession, and an admin holding target-result read authority + each probed — submits the §4.3 seed-progress query in both + worlds and is refused byte-shape-identically in both, with no + event appended in either, and the refusal bytes are + additionally asserted byte-shape-identical to the seed-boundary + gate's conflict as returned to a gate-refused mutating + submitter — the cross-surface control proving one constant + shape spans the gate, succession, and query surfaces — and the + query surface therefore discloses + nothing to anyone but the current designation; a + **seed-progress entitlement witness (NEW-18)** — the SAME + designated account submits the query in worlds U and P: it + returns 1 in U and k+1 in P (the intentional, entitled + disclosure), reading no outcome payload and no grant state + (asserted by the §6.1 closed read set); the actual fresh + client — holding no transient state, no bookkeeping cache, and + no seed read authority — is then run to completion against + BOTH worlds, and in each it originates first exactly the + returned index and completes the sequence without submitting + any committed position and without receiving a single refusal + in the walk — proving progress location is a disclosed entitled + read, never an inference from refusal shapes; a + **same-designation race witness (NEW-18)** — two fresh clients + C1 and C2 of the same grant-less designation both submit the + query and both receive the same `next` index i; C1 originates + position i and commits; C2 then submits the identical tuple + and is refused; C2 is asserted to follow the §4.3 + query/originate loop exactly — it does not retry, does not + advance to i+1 on its own, and interprets nothing from the + refusal — and re-submits the query, receiving a result + strictly beyond i (a greater `next` or `complete`), from which + it continues the loop to completion; per canonical key exactly + one mutation and one fence row exist; a fault variant of the + same witness refuses C2's origination while position i is + STILL unrecorded and asserts the re-query returns the SAME + index i, whereupon the client stops and surfaces the refusal + rather than looping — proving the loop distinguishes the + benign stale-query race from a genuine fault through the + entitled query alone; a **completed-world stop witness + (NEW-18)** — the actual fresh designated client is run against + a world whose canonical sequence is fully recorded: the query + returns the typed `complete` variant (asserted against the + closed DTO — a result value, not an error and not an index), + and the client stops, submitting zero originations and zero + other seed-key commands — proving the terminal branch is + defined, typed, and honored; a + **designation-derived completion (NEW-12/NEW-13/NEW-19)** — + origin A originates a prefix extending past workspace creation + — so the remaining suffix consists of ordinary + workspace-content example positions — revokes its own + position-1 `owner` grant, and resumes: the seed-progress query + returns the first unrecorded index and every remaining + origination, the content positions included, succeeds under the + designation-derived authority, zero new grant rows are written + beyond each command's own §5.2/§4.3 defaults, and the seed set + completes — proving completion, content positions included, + never depends on a revocable grant; a **tenant-unprivileged + successor completion (NEW-13/NEW-19)** — + the successor of the two-world control's recorded world, whose + recorded prefix likewise extends past workspace creation, who + held no seed-record authority before succeeding and receives + none by succeeding, completes the entire remaining suffix — + its workspace-content positions included — by + direct in-order origination from the seed-progress query's + returned index, using only the designation-derived + authority plus its own eligibility; a subsequent read attempt by + that successor against a committed pre-succession seed record is + refused — proving succession recovers completion without + conferring read or tenant authority; an **active-window + boundary witness (NEW-19)** — in a world whose next unrecorded + canonical position IS an ordinary workspace-content example + position, a designation holding no grant submits, in that SAME + state: (a) that position's exact canonical tuple, which + succeeds under the designation-derived authority; (b) a + non-canonical content command against the seed workspace — a + second kanban item — which is refused by the owning content + contract's authorization with nothing written; and (c) a + content command against a workspace outside the seed set, + refused likewise; branches (a), (b), and (c) each start from + an isolated copy of the same incomplete pre-state — branch (a) + commits a state change, so no branch runs in another's + post-state; this witness is discriminating where the + post-completion refusal below is not — an incorrect evaluator + scoped by completion state rather than by canonical key (one + granting the designation all seed-workspace writes while + seeding is incomplete) passes the post-completion test but + fails branch (b), which refuses while seeding is still + incomplete, and a second, broader incorrect evaluator (one + granting the designation writes in EVERY workspace while + seeding is incomplete) passes the post-completion test but + fails branch (c) — the control against that all-workspace + bypass, which the seed-workspace-scoped evaluator, correctly + refusing outside the seed set, would pass; after branch (a) + commits, read + attempts by the acting designation and by a later successor + against BOTH predecessor-created and successor-created seed + content are refused — the bounded origination response is the + only disclosure either ever receives; a **non-canonical content + refusal (NEW-19)** — the post-completion variant of the same + boundary: a designation holding no grant (the + self-revocation world, post-completion) submits, against the + seed workspace, an ordinary content command whose (operation, + key) is outside the canonical seed key set — a second, + non-canonical kanban item — and is refused by the owning + content contract's authorization with nothing written — proving + the designation-derived authority stops at the canonical set + and confers no general workspace authority; a + **result-disclosure witness (NEW-19/NEW-20)** — a successor's + content-position origination response and recorded outcome are + asserted to carry, as their entire state-derived content, + exactly the canonical outcome fields + (created row id, resolved parent id, canonical key, payload + digest) and no attribute of any pre-existing record beyond the + resolved parent id, while the response's envelope carries the + request's own correlation ids per contract 5 §4.3 — asserted + present, asserted equal to the request's, and derived from no + stored record — proving origination under the + designation-derived authority discloses nothing further and + still conforms to contract 5's result envelope; a + **post-completion + harmlessness control (NEW-16)** — with the seed sequence fully + complete, the origin is banned and an eligible platform admin B + submits succession: it succeeds with exactly one audit event, + zero grant rows written, and zero hierarchy or content + mutations; B's subsequent attempts to read the seed company, its + children, or their content are refused — proving succession over + a completed sequence confers nothing; a **post-succession replay + (NEW-13)** — after an A→B succession, an admin holding explicit + target-result read authority on the recorded seed targets + derives position 1's tuple afresh from canonical settings state: + the derived payload is asserted byte-identical to the committed + one (digest equality — no payload field ever named the origin) + and the submission replays, returning the recorded outcome; a + **repeat succession (NEW-14)** — A is banned, B succeeds and + commits further prefix, B is then banned, C succeeds and + completes the suffix: each succession appends exactly one event, + every fence row records its true originator (A's rows, B's rows, + C's rows), and the seed set completes; an **empty-prefix + succession (NEW-13)** — the origin is banned after finalize but + before any seed position commits; the successor succeeds + (condition (b) evaluated with no seed record in existence) and + originates the ENTIRE sequence: position 1's committed payload + is asserted byte-identical to a control derivation performed + before the succession (digest equality — the payload names no + account), and the recorded outcome and its same-operation + initial `owner` grant name the successor — asserting the owner + binding follows the acting designation through the outcome, not + the payload; a **succession race** — with the origin banned, two + eligible, §5.2-create-eligible admins submit succession + concurrently: the epoch record serializes them, exactly one + commits and becomes the designated origin with one audit event, + the loser receives the constant-shape refusal (re-evaluated: the + now-current origin is identity-eligible), and the seed sequence + completes exactly once under the winner; 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 mutation audit event exist, and + the losing + submission received the winner's recorded outcome (its access + attributed by the §4.3 replay access event); and with the + winner's transaction forced to abort, the waiting loser finds no + fence row, executes, and commits exactly one mutation and one + mutation audit event. Two envelope-shape witnesses complete the §4.3 + coverage: the same raw key submitted to two DIFFERENT operations + executes both independently, each committing its own mutation, + audit event, and fence row — proving uniqueness is the + (operation, key) pair, so a globally key-unique fence fails this + witness; and a fresh submission refused by authorization records + no fence row — the same actor, made eligible, retries the same + (operation, key, payload) and the command executes afresh, + distinguishing an authorization refusal from a pre-commit failure + and proving refusals record nothing. +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 state-derived response content (epoch state plus the + recorded mode value, the latter present during the bootstrap + epoch only), carried in an ordinary contract 5 §4 result DTO + whose envelope echoes the request's correlation ids (§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 bootstrap writer's amended authority (never by + authenticating the caller as the created admin; §3.3) with + identity §3.5's atomicity extended over them. This item is also a + disclosed, bounded amendment to the §1.1 client-side-composition + rule: the finalize handler is the wizard's single server-side + composed transaction, reachable only while the epoch is open, + witnessed by §6.1's finalize-write inventory. 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. Including the **replay mode**: each keyed + submission declares `actor-bound` (default) or `shared`, the + declaration is recorded in the fence row, and every replay — in + either mode — requires the submitter, freshly authorized with + matching scope and payload digest, to pass the §4.3 + target-result authorization: read authority, live at replay + time, on every canonical record the recorded outcome + references, refused otherwise with the constant-shape conflict + that preserves RBAC §7's no-existence-oracle rule. An + actor-bound row additionally requires recorded-actor equality — + never as a substitute for target-result authority — and a + declared-mode mismatch is a collision. Including + the **shared-declaration boundary and canonical-reference + resolution**: `shared` is server-verified against the epoch's + canonical seed key set and its canonical seed tuple set, both + fully derived from the epoch id, the immutable seed-parameter + provenance, and the fixed example set alone — no canonical seed + payload or scope contains a generated id or an account + identifier; child positions reference parents by epoch-scoped + canonical seed role, resolved to canonical rows server-side at + execution, available to exactly the canonical seed tuples — with + a shared declaration outside the key set or off its position's + derived tuple, and any origination past the next unrecorded + position (out of order), refused recording nothing (§4.3). Including the + **seed-boundary gate**: the epoch's seed-origin designation + initially names the first admin the finalize transaction + created and changes only through item 12's succession command; + every submission on a canonical seed key must be the currently + designated account + or hold target-result read authority on the position's recorded + targets, refused otherwise with the constant-shape conflict + evaluated before fence presence — so recorded and unrecorded + worlds are indistinguishable to the refused submitter — and + origination of a missing seed fence is reserved to the + seed-origin account passing the full fresh-mutation + authorization for that seed command, its hierarchy-authority + component satisfied by item 12's designation-derived authority + (§4.3). Including the **replay access event**: a + distinct non-mutation audit event class, appended on every + shared replay, recording the accessing actor, the current + request's correlation ids, and the fence row returned — the + disclosed mechanism by which a replay's access is attributed + without a duplicate semantic mutation event, the fence row and + mutation event immutably retaining the original actor. This + contract declares `shared` for exactly the §3.4 seed sequence — + deterministic, epoch-scoped singletons any eligible, + target-authorized admin must be + able to re-run (§4.1) — and for nothing else. +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), + scoped by the single disclosed §3.3 finalize exception (item 3). +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 §4.3 seed-origin succession command, and the §4.3 + seed-progress query, so the official-tool mapping and §6.1's + witnesses can omit none of them), 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. Second + clause: the pin of the `epoch` field's wire enumeration to exactly + the tokens `open` and `completed` (§2.3) — identity §3 names the + two epoch states in prose but defines no wire values, so this + contract fixes them. +10. The password-only v1 first admin (§3.3) — a disclosed **PRD + deviation (deferment)**: PRD Part I §6's initial-user SSO option + is not implemented in v1. Identity §3.6's SSO variant is not + composed by the v1 wizard, the initial user cannot be SSO-created + or SSO-linked in v1, and SSO first becomes available to accounts + created post-epoch (different users, not a satisfaction of the + initial-user field). The deviation narrows the PRD field for v1 + and is severable. +11. The **`bootstrap.seed-company-name`** settings key (§3.1) — the + owning record of the §3.4 seed parameter: written exactly once by + the finalize transaction among the ordinary settings writes, read + through the ordinary settings read surface, and **immutable + thereafter** — the settings family refuses every later write to + the key, from any surface and any actor. The key is seed + provenance for §3.4's derivation; the current company name lives + on the company row and changes only through the ordinary + hierarchy rename (§3.1, witnesses §6.3). +12. The **seed-origin succession command, the designation-derived + origination authority, and the seed-progress query** (§4.3) — + three coupled amendments, proposed and ratified here, severable + together. First, an amendment to identity §3's epoch surface: + one mutating command that redesignates the epoch's seed-origin + to the submitter, valid only while the current origin is + **unavailable** — it fails identity §7.1's + account-unavailability predicate (today exactly the better-auth + ban; future removal or disable contracts must extend that one + predicate and preserve the designation, §4.3) — and the + submitter is an identity-§7.1-eligible platform admin holding + §5.2 top-level create eligibility; both conditions are + evaluated against identity, platform-eligibility, and + epoch-record state only, never against fence rows, recorded + outcomes, grant rows, or hierarchy records, so the command's + outcome, observables, and timing are world-independent + unconditionally (no existence oracle). Refusals are the + constant-shape §4.3 conflict regardless of which condition + failed; success is one audited epoch-record write serialized on + the epoch record, whose closed write set (§6.1) is the + designation update plus its single audit event — it confers no + grant of any kind and grants no tenant authority; ownership + recovery for existing records is expressly out of scope + (§4.3). The command is repeatable (a later unavailable + successor is succeeded the same way), and recorded fence rows + are never rewritten. Second, the **designation-derived + origination authority** — a scoped amendment to the + actor-authorization component of every canonical seed + position's owning command family, each amended surface named + expressly: contract 2 §4's parent-`owner` and top-level + hierarchy-authority evaluation (the company, estate, project, + and workspace positions); RBAC §§2–3's workspace-content + authorization evaluation (the ordinary example-content + positions); the native-kanban SOT's workspace-scoped + command authorization (REQ-TEN-001, Amendment A1 §8.1.3) for + the kanban example positions; and — because RBAC §1 declares + its three authority layers (platform role, hierarchy grants, + workspace membership) exhaustive and "none substitutable" — + RBAC §1 itself, amended with a narrow ratified exception: for + exactly the mechanical scope below, the epoch's current + designation is a fourth, disclosed authority source, and + outside that scope §1's exhaustive rule stands unchanged, the + designation substituting for no layer on any other surface, + key, or command. For exactly the fresh + origination of a currently-unoriginated canonical seed + position, the epoch record's current designation itself + satisfies that one component; the scope is mechanically + decidable per submission — current designation, next + unrecorded canonical position, exact server-derived tuple, + in-order fresh origination — and every other component of each + family's evaluation (validation, §5.2 eligibility, identity + §7.1 eligibility, collision and replay rules) is evaluated + fresh and unchanged. It confers no read authority, no replay + authority, no standing grant, no authority over any committed + record, and nothing outside the canonical seed key set; it is + evaluated per submission and writes nothing beyond the + command's own canonical writes; and a successful origination's + response and recorded outcome are bounded, in their + state-derived content, to exactly the + command's canonical outcome fields (created row id, resolved + parent id, canonical key, payload digest) — the §4.3 + result-disclosure boundary, whose responses remain ordinary + contract 5 §4 result DTOs carrying the mandated non-state + correlation envelope, amending nothing in contract 5. Third, + the **seed-progress query** + (§4.3) — an addition to contract 5 §4's command-envelope + surface, the owning contract of the item 4 fence table whose + recording existence it reads: + one mapped read surface whose result DTO conforms to contract + 5 §4.1/§4.3 (explicit DTO, correlation echoed) and whose + state-derived content is only the closed §4.3 discriminated + union — the epoch's next unrecorded canonical position index + (`next`) or the typed completion variant (`complete`) — + authorized for exactly the current designation, the + screening evaluated before any fence state with every + non-designated submitter refused with the constant-shape + conflict byte-shape-identically across recorded and unrecorded + worlds; its closed read set (the designation plus + position-committed existence flags, §6.1) covers no recorded + outcome, no grant state, and no content, and it writes + nothing. Together these make origin loss recoverable with no + escalation surface and no oracle: without the succession + command a banned seed-origin account strands the unoriginated + seed suffix; without the generalized authority the suffix's + content positions refuse for a grant-less designation; and + without the query no fresh designated client can locate the + suffix at all — each contradicting PRD D4's no-lock-in + requirement (§4.4). + +## Ruling request + +Ratify sections 1–7 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).