docs: onboarding-wizard contract revision 5 (sol re-review 3 residuals + N5/N6)
ci/woodpecker/pr/ci Pipeline was successful

This commit is contained in:
fred
2026-08-26 20:40:14 -05:00
parent e58d0a5447
commit 0162443a38
+145 -48
View File
@@ -68,6 +68,26 @@ outcomes are recorded; the concurrent loser receives the winner's
recorded outcome (F7). §7 now names the contract 5 §3.1 rank-6 recorded outcome (F7). §7 now names the contract 5 §3.1 rank-6
mapping rows the composition expansion amends (F5, N4). 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).
Scope: the Gateway-backed product onboarding wizard. Out of scope: the Scope: the Gateway-backed product onboarding wizard. Out of scope: the
host-local install wizard (`mosaic wizard`, which drives host install and host-local install wizard (`mosaic wizard`, which drives host install and
gateway bootstrap and is not this artifact — audit REPORT.md layer 3); gateway bootstrap and is not this artifact — audit REPORT.md layer 3);
@@ -84,11 +104,19 @@ through the extensibility rule §2.4).
every other webUI surface: no wizard operation reaches the database every other webUI surface: no wizard operation reaches the database
or filesystem directly, and no wizard-only privileged write path or filesystem directly, and no wizard-only privileged write path
exists. Concretely, the wizard is contract 5's rank-6 family, and it exists. Concretely, the wizard is contract 5's rank-6 family, and it
is a **client-side composition with no server-side wizard is a **client-side composition with exactly one disclosed
orchestrator**: every wizard operation is an ordinary outbound exception**: every wizard operation except step 3's finalize is an
Gateway call issued from the wizard's web modules (or the equivalent ordinary outbound Gateway call issued from the wizard's web modules
scripted sequence), so contract 5 §6.1's outbound-call inventory, (or the equivalent scripted sequence), and the exception is the
scoped to those modules, sees the wizard's complete operation set. §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 The composed operations span six existing families: the rank-1
hierarchy commands and the rank-4 enrollment command (contract 5 hierarchy commands and the rank-4 enrollment command (contract 5
§3.1 — built first), the settings command family (steps 12), the §3.1 — built first), the settings command family (steps 12), the
@@ -104,10 +132,15 @@ through the extensibility rule §2.4).
it performs is an existing command with its own contract: user and it performs is an existing command with its own contract: user and
epoch writes under the identity contract §3, hierarchy writes under epoch writes under the identity contract §3, hierarchy writes under
contract 1 §5, grant writes under contract 2 §4, settings writes under contract 1 §5, grant writes under contract 2 §4, settings writes under
their owning command family. The one exception is the bootstrap epoch their owning command family. The one exception is the bootstrap
transition, where the wizard drives the bootstrap writer defined by surface, where the wizard drives the bootstrap writer defined by
identity §3 — that writer's constraints (§3.1–§3.6) bind unchanged; identity §3 **as amended by the disclosed §7.3 finalize
this contract adds nothing to them. 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.
3. **Wizard state derives from canonical state.** Each step renders the 3. **Wizard state derives from canonical state.** Each step renders the
system's current configuration (read through the same commands) and system's current configuration (read through the same commands) and
applies deltas; the wizard does not keep an answer file whose contents applies deltas; the wizard does not keep an answer file whose contents
@@ -147,10 +180,13 @@ through the extensibility rule §2.4).
record server-side. The bootstrap-status response is a **closed record server-side. The bootstrap-status response is a **closed
two-field schema**: `epoch` — one field whose value set is exactly two-field schema**: `epoch` — one field whose value set is exactly
the bootstrap epoch states identity §3 defines for the bootstrap epoch states identity §3 defines for
`bootstrap_state`, closed to that enumeration — and `mode` — the `bootstrap_state`, closed to the exact wire-token pair **`open`**
recorded mode value, present **only while the epoch is open** and and **`completed`** — identity §3 names the two epoch states in
absent from the response schema once the epoch has completed. No prose but defines no wire enumeration, so this contract pins the
other field exists in the response. The unauthenticated pre-epoch 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 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 mode disclosure is a disclosed amendment to contract 6 §2.2's
authenticated-read rule (§7.9); post-epoch, §2.2's authenticated-read rule (§7.9); post-epoch, §2.2's
authenticated-only rule holds unchanged and the bootstrap-status authenticated-only rule holds unchanged and the bootstrap-status
@@ -173,7 +209,12 @@ through the extensibility rule §2.4).
The v1 wizard consists of exactly these steps, in order, each backed by The v1 wizard consists of exactly these steps, in order, each backed by
the named authority: the named authority:
1. **System and company name.** System name is a settings value; company 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. On a first run this step name feeds step 4's company creation. On a first run this step
collects and validates only — the collected values are committed by 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) step 3's finalize command (§3.3). On a re-run (an authenticated admin exists)
@@ -191,11 +232,16 @@ the named authority:
v1 first admin is password-only.** A step-2 SSO choice cannot yield v1 first admin is password-only.** A step-2 SSO choice cannot yield
a canonically configured provider before the epoch closes, so an a canonically configured provider before the epoch closes, so an
SSO-authenticated first admin is not constructible in this flow; SSO-authenticated first admin is not constructible in this flow;
the v1 wizard does not compose identity §3.6's SSO variant, and the the v1 wizard does not compose identity §3.6's SSO variant. The
PRD step list's SSO option is satisfied post-epoch (providers PRD step list's SSO option **for the initial user is not
configured and JIT-enabled after finalize; identity §5 governs implemented in v1 — a disclosed PRD deviation (deferment, §7.10)**:
every SSO-created account). This is a disclosed sequencing decision no v1 step configures a provider before finalize and no v1 step
(§7.10). The password path's canonical `users.name` MUST equal the 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 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 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 PRD's step list is dropped. The wizard also presents the applicable
@@ -218,11 +264,17 @@ the named authority:
seed parameter), the step-2 component choices, the seed parameter), the step-2 component choices, the
registration-mode submission, and the applicable JIT submissions. registration-mode submission, and the applicable JIT submissions.
The command executes **in one transaction**: it creates the admin The command executes **in one transaction**: it creates the admin
and closes the epoch exactly as identity §3 defines, then — with and closes the epoch exactly as identity §3 defines, then commits
the new admin existing inside the same transaction, holding the every carried value through the ordinary settings and identity
RBAC §1.1 platform authority those writes require — commits every configuration write implementations — the same code paths the
carried value through the ordinary settings and identity post-epoch commands use; no parallel write path. The executing
configuration writes, each attributed in audit to the new admin. 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 Either the whole transaction commits or none of it exists (identity
§3.5's atomicity extends over the carried writes). Before finalize §3.5's atomicity extends over the carried writes). Before finalize
the run holds collected values only: no canonical write of any kind the run holds collected values only: no canonical write of any kind
@@ -236,11 +288,15 @@ the named authority:
closes the epoch, and commits the §3.3 carried values; it has no closes the epoch, and commits the §3.3 carried values; it has no
hierarchy authority and creates no hierarchy node. The seed hierarchy authority and creates no hierarchy node. The seed
sequence is derived entirely from canonical state: the seed sequence is derived entirely from canonical state: the seed
parameter the finalize command recorded (the company name) and the parameter the finalize command recorded (the company name, read
fixed example set (§4.3). A resumed run — including a fresh client from the `bootstrap.seed-company-name` settings value, §3.1) and
holding none of the original run's transient state — reconstructs the fixed example set (§4.3). A resumed run — including a fresh
the same ordered sequence and the same deterministic §4.3 keys from client holding none of the original run's transient state —
that canonical state alone. reconstructs the same ordered sequence and the same deterministic
§4.3 keys from that canonical state alone. Once the first company
exists the seed parameter is inert bookkeeping: the §4.3 fence,
not the parameter's presence or absence, is what prevents
re-seeding.
The first company is created by the ordinary top-level company The first company is created by the ordinary top-level company
command under §5.2's eligibility policy, with the new admin as actor, command under §5.2's eligibility policy, with the new admin as actor,
naming the admin as initial `owner` in the same audited operation naming the admin as initial `owner` in the same audited operation
@@ -351,9 +407,11 @@ collects no sensitive category, so v1 ships no custody surface.
## 5. Seeding authority (resolves contract 2 review NEW-1) ## 5. Seeding authority (resolves contract 2 review NEW-1)
1. During the bootstrap epoch, the bootstrap writer's authority (identity 1. During the bootstrap epoch, the bootstrap writer's authority
§3) covers exactly what identity §3 defines: creating the first (identity §3, as amended by the §7.3 finalize extension) covers
account and closing the epoch. It creates no hierarchy node. The 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 first company is created post-epoch by the first admin through the
ordinary top-level company command (§5.2), naming that admin as ordinary top-level company command (§5.2), naming that admin as
initial `owner` (contract 2 §4.3). No operator-designated third initial `owner` (contract 2 §4.3). No operator-designated third
@@ -380,11 +438,21 @@ Binding on the implementing PRs:
1. **D8 mapping witness:** every Gateway call the wizard makes resolves 1. **D8 mapping witness:** every Gateway call the wizard makes resolves
to a contract 5 mapping row, asserted by contract 5 §6.1's to a contract 5 mapping row, asserted by contract 5 §6.1's
outbound-call inventory scoped to the wizard modules — an inventory outbound-call inventory scoped to the wizard modules — an inventory
that is complete for the wizard because §1.1 forbids a server-side that is complete for the wizard's outbound calls because §1.1
wizard orchestrator, and the witness statically asserts that forbids server-side wizard composition outside the single declared
prohibition (no server-side module composes wizard operations). The §3.3 finalize handler, and the witness statically asserts that
inventoried operation set is asserted equal, in both directions, to scoped prohibition (no server-side module other than the declared
the §1.1 declared family list. Wizard modules appear in no 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 class-table writer allowlist (contract 1 §6.3b) and hold no direct
database or filesystem access (static assertion, plus a runtime database or filesystem access (static assertion, plus a runtime
probe that a wizard-context filesystem/database access attempt is probe that a wizard-context filesystem/database access attempt is
@@ -396,7 +464,8 @@ Binding on the implementing PRs:
resolves its step set from the bootstrap-status mode field (§2.3), 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 a post-epoch run from contract 6 §2.2's authenticated read; the
bootstrap-status response matches §2.3's closed two-field schema bootstrap-status response matches §2.3's closed two-field schema
exactly while the epoch is open, and after the epoch completes 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 contains the epoch field only — the mode field absent from the
response (closed-field assertion on the response schema in both response (closed-field assertion on the response schema in both
phases); post-epoch, an unauthenticated mode read through any phases); post-epoch, an unauthenticated mode read through any
@@ -472,13 +541,21 @@ Binding on the implementing PRs:
executes nothing and returns the recorded outcome (asserted by executes nothing and returns the recorded outcome (asserted by
mutation-count and audit-event-count equality); the same key with a mutation-count and audit-event-count equality); the same key with a
changed payload digest is refused with the single bounded conflict changed payload digest is refused with the single bounded conflict
and executes nothing; a replay by an actor who has since lost and executes nothing; the same key and payload submitted by a
different authorized actor is refused with the same single bounded
conflict (actor mismatch) 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, eligibility (identity §7.1 ban) receives the authorization refusal,
not the recorded outcome; a submission that failed before commit not the recorded outcome; a submission that failed before commit
leaves no fence row and its retry executes; two concurrent resumed leaves no fence row and its retry executes; two concurrent resumed
runs executing the seed sequence yield exactly one seed set — per runs executing the seed sequence yield exactly one seed set — per
key, exactly one mutation and one audit event exist, and the losing key, exactly one mutation and one audit event exist, and the losing
submission received the winner's recorded outcome. submission received the winner's recorded outcome; and with the
winner's transaction forced to abort, the waiting loser finds no
fence row, executes, and commits exactly one mutation and one
audit event.
8. **Actor-matrix witness (§5.2):** post-bootstrap top-level company 8. **Actor-matrix witness (§5.2):** post-bootstrap top-level company
creation succeeds for an ordinary authenticated non-admin user creation succeeds for an ordinary authenticated non-admin user
(positive), and is refused for an unauthenticated caller and for a (positive), and is refused for an unauthenticated caller and for a
@@ -523,9 +600,14 @@ contracts and are not additions:
identity §3's bootstrap surface: one transaction carrying the identity §3's bootstrap surface: one transaction carrying the
first-admin fields, the collected settings, registration-mode, and first-admin fields, the collected settings, registration-mode, and
JIT values, and the §3.4 seed parameter, committing the carried JIT values, and the §3.4 seed parameter, committing the carried
writes under the new admin's authority with identity §3.5's writes under the bootstrap writer's amended authority (never by
atomicity extended over them. Severable from the rest of this authenticating the caller as the created admin; §3.3) with
contract. 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 4. The idempotency-key field and its same-transaction uniqueness
fence, with the §4.3 replay, collision, no-error-replay, and fence, with the §4.3 replay, collision, no-error-replay, and
concurrency rules — an addition to contract 5 §4's command concurrency rules — an addition to contract 5 §4's command
@@ -533,7 +615,8 @@ contracts and are not additions:
this contract. this contract.
5. The presentation-and-submission obligation for applicable mandatory 5. The presentation-and-submission obligation for applicable mandatory
choices on wizard runs (§3.3). choices on wizard runs (§3.3).
6. The no-server-side-orchestrator architectural constraint (§1.1). 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). 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 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 composition row, which today names only the rank-1 hierarchy and
@@ -547,10 +630,24 @@ contracts and are not additions:
under contract 5 §5. under contract 5 §5.
9. The contract 6 §2.2 amendment permitting the single unauthenticated 9. The contract 6 §2.2 amendment permitting the single unauthenticated
pre-epoch mode disclosure through the §2.3 bootstrap-status field; pre-epoch mode disclosure through the §2.3 bootstrap-status field;
post-epoch, §2.2's authenticated-only rule is unchanged. post-epoch, §2.2's authenticated-only rule is unchanged. Second
10. The password-only v1 first admin (§3.3): identity §3.6's SSO clause: the pin of the `epoch` field's wire enumeration to exactly
variant is not composed by the v1 wizard; the PRD step list's SSO the tokens `open` and `completed` (§2.3) — identity §3 names the
option is satisfied post-epoch. 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 by the finalize
transaction among the ordinary settings writes, read through the
ordinary settings read surface, inert once the first company
exists (§3.4).
## Ruling request ## Ruling request