72 KiB
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 or deleted origin 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).
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
- 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 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.
- The wizard introduces no new mutation surface. Every state change it performs is an existing command with its own contract: user and epoch writes under the identity contract §3, hierarchy writes under contract 1 §5, grant writes under contract 2 §4, settings writes under their owning command family. The one exception is the bootstrap surface, where the wizard drives the bootstrap writer defined by identity §3 as amended by the disclosed §7.3 finalize extension: the writer's constraints (§3.1–§3.6) bind, and this contract's single change to them — extending the epoch-closing command to carry the §3.3 value set inside the same transaction — is exactly the §7.3 amendment, severable and ratified with this contract. Beyond that amendment, nothing is added to identity §3, and no undisclosed authority exists.
- 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.
- 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
- 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.
- 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.
- Mode is an install-time input, not a wizard output. The
deployment mode is recorded canonically at bootstrap and owned by
contract 6 (§2 there): the wizard reads the recorded mode and
branches on it; it never writes mode and never derives it from
feature state. During the bootstrap epoch no authenticated account
exists, so contract 6 §2.2's authenticated read surface is
unreachable there; the pre-epoch flow instead branches on the mode
value reported by the unauthenticated bootstrap-status response
of the bootstrap surface (identity §3), which evaluates the mode
record server-side. The bootstrap-status response is a closed
two-field schema:
epoch— one field whose value set is exactly the bootstrap epoch states identity §3 defines forbootstrap_state, closed to the exact wire-token pairopenandcompleted— 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 — andmode— the recorded mode value, present only while the epoch is open and absent from the response schema once the epoch has completed. No other field exists in the response. The unauthenticated pre-epoch mode disclosure is a disclosed amendment to contract 6 §2.2's authenticated-read rule (§7.9); post-epoch, §2.2's authenticated-only rule holds unchanged and the bootstrap-status response carries no mode field. Post-epoch wizard runs read mode through contract 6 §2.2 unchanged. Changing mode later is conversion (contract 6), not a wizard re-run. In v1 a recorded mode ofenterpriseis 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. - 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:
- 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. - 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.
- 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.nameMUST 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 (registrationclosed, 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). - 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-namesettings value, §3.1) and the fixed example set (§4.3). A resumed run — including a fresh client holding none of the original run's transient state — reconstructs the same ordered sequence and the same deterministic §4.3 keys from that canonical state alone, prefix-wise: each position's scope and payload derive from the committed predecessors' recorded outcomes, so the run walks the order and never precomputes a tuple past the next unrecorded position (§4.3 shared-declaration boundary). Because the seed parameter is immutable (§3.1), the re-derived sequence is byte-stable across every re-run and resume: the same keys carry the same payload digests, so already-committed mutations replay (recorded outcomes) rather than collide, regardless of any hierarchy rename performed since — and, because every seed submission declares §4.3'ssharedreplay mode, they 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 new admin — the epoch's §4.3 seed-origin account — as actor, naming the admin as initialownerin the same audited operation (contract 2 §4.3); 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 admin'sownerauthority (contract 2 §4.3). Seeded examples are ordinary workspace content created by ordinary commands, attributable in audit to the acting admin, carrying the run's trace correlation ids (contract 5 §4.3) and the §4.3 idempotency keys. - 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")
-
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.
-
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.
-
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) orshared(§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,
sharedoractor-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 additionalactor-boundcondition, never a substitute for target-result authorization: anactor-boundrow 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-boundrow, 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.
sharedis a server-verified, seed-only policy, never a caller privilege. The boundary has a fence-independent part and a prefix-derived part. 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 is prefix-derived, because later seed tuples embed generated ids: the tuple at seed position k — its authorization scope and payload digest — is derived from the epoch id, the immutablebootstrap.seed-company-nameprovenance, the fixed example set, and the canonical recorded outcomes of positions 1 through k−1 (the ids the committed predecessor fence rows reference). At any canonical state exactly these members are derivable: every committed-prefix tuple (read back from its fence row) and the next unrecorded tuple in order. Before the first company exists, the derivable set is exactly the seed-company tuple. A fresh client derives the same way — §3.4's derivation is this walk: submit the sequence in order, learning each generated id from the returned recorded outcome or the submission's own execution, never precomputing a tuple past the next position. A submission declaringsharedwhose (operation, key) is outside the canonical seed key set, whose tuple does not equal its position's derived tuple, or whose position lies past the next unrecorded position (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 plus the hierarchy authority the command itself requires); a refused submission records no row (no-error replay below). 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: an eligible platform admin — passing §5.2 fresh-mutation authorization in full — submits succession naming itself the epoch's seed-origin. The command succeeds only when, evaluated against canonical state inside the succession transaction itself: (a) the current seed-origin account fails identity §7.1 eligibility (banned, deleted, or disabled) — succession while the current origin remains eligible is refused — and (b) the submitter holds §4.3 target-result read authority on every canonical record referenced by the recorded outcomes of the committed seed prefix (vacuously satisfied while no position is committed). 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 — so succession adds no existence oracle (witness §6.7) — executes nothing, and appends no event. Successful succession updates the designation in the epoch record and appends one ordinary mutation audit event recording the prior designation, the new designation, and the acting principal; it rewrites no fence row and no recorded outcome — rows already recorded immutably retain their original actor. 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 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, and the fence rows it originates record the successor. Factory reset (§4.2) remains the only path to a new epoch; it is never required to complete an interrupted seed sequence.
- 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
sharedreplay 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 toactor-bound; nothing in this contract declaressharedoutside 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). - 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 —
-
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 run re-derives the full ordered seed sequence from canonical state and re-submits it with the same deterministic keys, already-committed mutations return their recorded outcomes, and only the remainder executes, without duplication and without compensating rollback of completed commands. There is no wizard-level transaction spanning steps. Loss of the seed-origin account mid-sequence is likewise recoverable without a new epoch: §4.3 seed-origin succession designates an eligible successor, and the resumed run completes the remaining suffix under the successor — interrupted runs strand nothing even across origin-account loss.
5. Seeding authority (resolves contract 2 review NEW-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. - 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
ownergrant 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. - Child-node creation inside the wizard (estate, project, workspace
under the seeded company) follows contract 2 §4.3 unchanged: parent
ownerauthority, no automatic grant needed.
6. Verification requirements
Binding on the implementing PRs:
- 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). 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. - Mode witnesses: the branch point exists — a pre-epoch flow
resolves its step set from the bootstrap-status mode field (§2.3),
a post-epoch run from contract 6 §2.2's authenticated read; the
bootstrap-status response matches §2.3's closed two-field schema
exactly while the epoch is open — 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 from the
response (closed-field assertion on the response schema in both
phases); post-epoch, an unauthenticated mode read through any
surface is refused (contract 6 §2.2, as amended by §7.9, holds); v1 with mode
standaloneyields 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. - 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 asownerin 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). - 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
ownergrant, 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. - 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.nameequals 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 (registrationclosed, JIT off — identity §2.2, §4.1). - Gating-independence witness: with any wizard-completion marker deleted (§1.4), authorization and registration gating behave identically — proving no gate reads wizard state.
- 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
sharedmode — 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 withshareddeclared 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 shared declaration — with the seed prefix committed through position k, the seed-origin account submits the position k+2 tuple (past the next unrecorded position), constructed by the test harness from ids it obtained out of band — and is refused with the §4.3 validation refusal, executes nothing, and records no fence row, proving the prefix-aware derivation rejects positions the canonical walk cannot yet derive; 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 authorization refusal 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 anactor-boundkey, grants a second accountowner, 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): a succession recovery — the seed-origin account commits a proper seed prefix and is then banned (identity §7.1); an eligible platform admin holding target-result read authority on the committed prefix 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, and the successor's resumed run replays the committed prefix (its access attributed by §4.3 replay access events) and originates the remaining suffix in order — 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 race — with the origin banned, two eligible, prefix-authorized 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, 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. - 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.
- 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.
- Enrollment witness: the enrollment step exists, invokes only the rank-4 family, and a run that skips it completes with zero enrollment-family mutations.
- 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:
- Enrollment-step skippability (§3.5) — the PRD step list does not mark the step optional.
- The unauthenticated bootstrap-status mode disclosure — the closed two-field response schema (epoch state plus the recorded mode value, the latter present during the bootstrap epoch only) (§2.3).
- 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.
- 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) orshared, 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:sharedis server-verified against the epoch's canonical seed key set (fence-independent, derived from the epoch id and the fixed seed-role list) and its prefix-derived canonical seed tuple set — each position's scope and digest derived from the committed predecessors' recorded outcomes — with a shared declaration outside the key set, off its position's derived tuple, or past the next unrecorded position 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 (§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 declaressharedfor 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. - The presentation-and-submission obligation for applicable mandatory choices on wizard runs (§3.3).
- The no-server-side-orchestrator architectural constraint (§1.1), scoped by the single disclosed §3.3 finalize exception (item 3).
- The wizard-completion-marker presentational-only rule (§1.4).
- The contract 5 §3.1 rank-6 mapping expansion (§1.1): the rank-6 composition row, which today names only the rank-1 hierarchy and rank-4 enrollment families, is amended to name all six composed families — adding the settings command family, the identity bootstrap and registration surface (including the §3.3 finalize command), the mode reads (contract 6 §2.2 and the §2.3 bootstrap-status field), and the ordinary content commands used for example seeding — with one mapping row per newly named family. Without this amendment those operations are unmapped and blocked under contract 5 §5.
- 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
epochfield's wire enumeration to exactly the tokensopenandcompleted(§2.3) — identity §3 names the two epoch states in prose but defines no wire values, so this contract fixes them. - 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.
- The
bootstrap.seed-company-namesettings 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). - The seed-origin succession command (§4.3) — an amendment to identity §3's epoch surface, proposed and ratified here, severable: one mutating command that redesignates the epoch's seed-origin to an eligible platform admin holding target-result read authority on the committed seed prefix, valid only while the current origin fails identity §7.1 eligibility; refusals are the constant-shape §4.3 conflict regardless of which condition failed, the change is one audited epoch-record write serialized on the epoch record, and recorded fence rows are never rewritten. Without this amendment a banned or deleted seed-origin account strands the unoriginated seed suffix, 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
ownergrant (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).