diff --git a/docs/requirements/onboarding-wizard.md b/docs/requirements/onboarding-wizard.md index d50a3ab9..fcb67804 100644 --- a/docs/requirements/onboarding-wizard.md +++ b/docs/requirements/onboarding-wizard.md @@ -325,7 +325,53 @@ by the owning contract. Witnesses §6.7: seed-progress two-world refusal, seed-progress entitlement with the actual fresh client run against both worlds, content-position completion in both recovery variants, non-canonical content refusal, and the -result-disclosure witness. +result-disclosure witness. (Revision 14 completes this revision's +query with a full client protocol and typed completion, ratifies +the RBAC §1 exception this revision left implicit, and reconciles +the closed result schemas with contract 5's envelope.) + +Revision 14 (sol re-review 13: NEW-18/NEW-19 residuals, NEW-20, +NEW-21): the query's client protocol, the authority's ratified +boundary, the result envelope, and the refusal order are made +exact. **Query/originate loop** (NEW-18): the walk's complete +protocol is now normative in §4.3 — the query's state-derived +content is a closed discriminated union (`next` index or a typed +`complete` variant that is a result value, never an error); the +client stops on `complete`; on a refused canonical origination it +draws nothing from the refusal and re-queries, continuing only on +a strictly-later result (the benign stale-query race, where a +same-designation peer committed the position first) and stopping +to surface a genuine fault when the index is unchanged — so +progress derives from the entitled query alone under any number +of same-designation clients. Witnesses: same-designation race +(with its unchanged-index fault variant) and the completed-world +stop run of the actual fresh client. **RBAC §1 exception +ratified** (NEW-19): RBAC §1 declares its three authority layers +exhaustive, so §4.3 and §7 item 12 now name §1 itself among the +expressly amended surfaces — a narrow ratified exception making +the designation a fourth, disclosed authority source inside +exactly the mechanical origination scope and substitutable +nowhere else. The active-window boundary witness discriminates +canonical-key scope from completion-state scope: while a content +position is still next, the exact canonical tuple succeeds while +a second non-canonical item and a non-seed-workspace command +refuse in the SAME state, and post-origination reads of +predecessor- and successor-created seed content stay refused. +**Envelope reconciliation** (NEW-20): every closed response — +origination outcome and query alike — bounds its STATE-DERIVED +content while remaining an ordinary contract 5 §4 result DTO +carrying the mandated non-state correlation envelope, which +echoes the request and discloses no state; contract 5 is not +amended by the disclosure boundary. **One refusal order** +(NEW-21): the result-disclosure paragraph now restates the +operative §4.3 order instead of contradicting it — fresh-mutation +authorization first (its refusal is the owning family's), then +the seed-boundary gate before fence presence and +canonical-reference resolution, the constant shape scoped to +callers that reached the gate — and the child-race control +asserts the refusal class, pinning the order mechanically, with +the cross-surface shape control asserting one constant conflict +shape across the gate, succession, and query surfaces. Scope: the Gateway-backed product onboarding wizard. Out of scope: the host-local install wizard (`mosaic wizard`, which drives host install and @@ -390,11 +436,16 @@ through the extensibility rule §2.4). component of each canonical position's owning family (contract 2 §4's hierarchy authority; RBAC §§2–3's workspace-content authorization; the native-kanban SOT's workspace-scoped command - authorization, REQ-TEN-001 / Amendment A1 §8.1.3), conferring no + authorization, REQ-TEN-001 / Amendment A1 §8.1.3; and, because + RBAC §1 declares its three authority layers exhaustive, a + narrow ratified exception to RBAC §1 itself, scoped to exactly + that origination and substitutable nowhere else), conferring no grant and no read authority — and §7 item 12's **seed-progress - query** (§4.3), one designation-only mapped read surface - disclosing exactly the epoch's next unrecorded canonical seed - position index (or a completion marker) and nothing else; no + query** (§4.3), one designation-only mapped read surface whose + entire state-derived content is the closed §4.3 discriminated + union — the epoch's next unrecorded canonical seed position + index, or a typed completion variant — inside the ordinary + contract 5 §4 result envelope, and nothing else; no undisclosed authority exists; all of these surfaces appear in the §1.1 composed-family inventory, the §7.8 mapping amendment, and §6.1's inventories, so the D8 mapping and authorization-parity @@ -799,7 +850,16 @@ collects no sensitive category, so v1 ships no custody surface. amendments to each named surface (§7 item 12), severable together, that confer no read authority, no replay authority, no standing grant, no authority over any committed record, - and nothing outside the canonical seed key set. The + and nothing outside the canonical seed key set. Because RBAC + §1 states its three authority layers exhaustively ("none + substitutable"), this authority is also, expressly, a narrow + ratified exception to RBAC §1's exhaustive-layer rule (§7 + item 12): within exactly the mechanical scope below — the + current designation, the next unrecorded canonical position, + the exact server-derived tuple, a fresh in-order + origination — the designation is a fourth, disclosed + authority source; outside that scope it substitutes for no + layer, anywhere, ever. The authority's scope is mechanically decidable per submission: the submitter is the epoch's current designation, the (operation, key) is the next unrecorded canonical position, @@ -812,15 +872,30 @@ collects no sensitive category, so v1 ships no custody surface. writes nothing beyond the command's own canonical writes; a refused submission records no row (no-error replay below). **Result-disclosure boundary.** A successful origination's - response and recorded outcome contain exactly the command's - canonical outcome fields — the created row id, any + response and recorded outcome carry, as their entire + STATE-DERIVED content, exactly the command's canonical + outcome fields — the created row id, any canonical-reference-resolved parent id, the canonical key, - and the payload digest — and nothing else: no listing, no - attribute of any pre-existing record beyond the resolved - parent id the outcome must record, and no grant- or - fence-table content. Refusals on canonical seed keys are - screened by the seed-boundary gate first and keep its - constant shape. The recorded actor of every shared row is + and the payload digest — and nothing else state-derived: no + listing, no attribute of any pre-existing record beyond the + resolved parent id the outcome must record, and no grant- or + fence-table content. The response remains an ordinary + contract 5 §4 result DTO: it additionally carries exactly + the non-state envelope metadata contract 5 §4.1/§4.3 mandate + for every mapped result — the request's own correlation ids + in the fixed envelope frame — which echoes the caller's + request, derives from no stored record, and discloses + nothing about any world's state; the boundary bounds + disclosure and amends nothing in contract 5. Refusals on + canonical seed keys follow the evaluation order this section + fixes and no other: fresh-mutation authorization is + evaluated first — a submitter it refuses receives the owning + command family's ordinary authorization refusal — and the + seed-boundary gate is evaluated next, before fence presence + and before canonical-reference resolution; the gate's + constant-shape conflict is the refusal of exactly the + callers that passed fresh-mutation authorization and failed + the gate (witness §6.7). The recorded actor of every shared row is therefore the account that was the epoch's seed-origin at that position's origination, authorized for the mutation the row fences. Recorded positions are replayable by any admin holding @@ -910,10 +985,18 @@ collects no sensitive category, so v1 ships no custody surface. an interrupted seed sequence. - **Seed-progress query.** Locating the unoriginated suffix is a disclosed, mapped read surface, never an inference from - refusal shapes: the **seed-progress query** returns exactly - one value — the index of the epoch's next unrecorded - canonical seed position, or a completion marker when every - position is recorded — and nothing else. It is authorized for + refusal shapes: the **seed-progress query** returns, as its + entire state-derived content, exactly one value from a + closed discriminated union of two result variants — `next`, + carrying the index of the epoch's next unrecorded canonical + seed position, or `complete`, carrying no index, when every + position is recorded — and nothing else state-derived. The + `complete` variant is a typed result value on the success + path, never an error shape and never a sentinel index; the + response is an ordinary contract 5 §4 result DTO whose only + other content is the mandated non-state envelope metadata + (the request's own correlation ids), which echoes the + request and discloses no state. It is authorized for exactly the account the epoch's designation currently names, and that screening is evaluated first, before any fence state is consulted: every other submitter — a former designation, a @@ -933,13 +1016,32 @@ collects no sensitive category, so v1 ships no custody surface. state, and its closed read set is statically asserted (§6.1). The query writes nothing and appends no event. A resuming designated client — the original origin on a fresh client and - a §4.3 successor alike — first submits the query and then - originates in order from the returned index, deriving each - tuple from canonical settings state alone; an admin holding - target-result read authority may instead walk the sequence - and receive recorded outcomes as replays (§6.3). No client is - required to infer progress from refusals, and no - non-designated actor can. + a §4.3 successor alike — runs the **query/originate loop**, + the walk's complete protocol: submit the query; on + `complete`, STOP — the walk is finished and the client + submits no origination and no other seed-key command; on + `next` index i, originate position i, deriving its tuple + from canonical settings state alone, and on success continue + the loop from a fresh query or the next index. If an + origination on a canonical seed key is refused, the client + draws NO conclusion from the refusal itself — refusal shapes + are not progress signals — and re-submits the entitled + query: a result strictly beyond i (a greater index or + `complete`) means another client of the same designation + committed position i between query and origination — the + **stale-query race**, benign by construction — and the loop + continues from the fresh result; a result that still names i + means the refusal was a genuine fault, and the client stops + and surfaces the refusal without submitting further. The + loop's only progress source is the query, so the walk is + race-safe under any number of same-designation clients: each + position commits exactly once (Concurrency below), and every + client either advances on its own successes or + re-synchronizes through the query it is entitled to. An + admin holding target-result read authority may instead walk + the sequence and receive recorded outcomes as replays + (§6.3). No client is required to infer progress from + refusals, and no non-designated actor can. - **No error replay.** The fence row commits only with its mutation, so only committed outcomes are ever recorded. A failed or refused submission records no fence row; a retry executes @@ -996,9 +1098,11 @@ collects no sensitive category, so v1 ships no custody surface. individually atomic commands, not one transaction: an interruption between them leaves a prefix of committed seed nodes, and the §4.3 fence makes the resumed run complete exactly the remaining suffix — - the resumed designated client locates that suffix through the - §4.3 seed-progress query and originates in order from the - returned index, re-deriving every tuple from canonical state; a + the resumed designated client runs the §4.3 query/originate + loop — querying, originating the returned index, stopping on + the typed completion variant, and re-querying (never + interpreting the refusal) if a canonical origination is + refused — re-deriving every tuple from canonical state; a target-authorized admin's re-run may instead re-submit the full ordered seed sequence with the same deterministic keys, already-committed mutations returning their recorded outcomes — @@ -1008,8 +1112,8 @@ collects no sensitive category, so v1 ships no custody surface. account mid-sequence — identity §7.1 unavailability — is likewise recoverable without a new epoch: §4.3 seed-origin succession designates an eligible successor, and the resumed run locates - the remaining suffix through the §4.3 seed-progress query and - completes it under the successor's designation-derived + the remaining suffix through the same §4.3 query/originate + loop and completes it under the successor's designation-derived authority — the ordinary workspace-content example positions included (§4.3, §7 item 12) — deriving every tuple from canonical settings state alone: no grant is conferred and no @@ -1102,8 +1206,13 @@ Binding on the implementing PRs: seed keys — no recorded outcome, no payload or digest, no resolved id, no acting principal, no grant table, no hierarchy or content record; its write set is asserted empty (no event, - no row), and its response schema is closed to the single - index-or-completion value. Wizard modules appear in no + no row), and its response DTO is asserted closed in both + halves: its state-derived content is exactly the §4.3 + discriminated next-index-or-complete union, its only other + content is contract 5 §4's non-state envelope metadata (the + request's correlation ids), and no further field exists — the + closed-schema assertion covers the full wire shape, both + variants included. Wizard modules appear in no class-table writer allowlist (contract 1 §6.3b) and hold no direct database or filesystem access (static assertion, plus a runtime probe that a wizard-context filesystem/database access attempt is @@ -1291,7 +1400,11 @@ Binding on the implementing PRs: 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 + submission receives the owning command family's ordinary + authorization refusal — asserted NOT the seed-boundary gate's + constant-shape conflict, pinning the §4.3 evaluation order in + which fresh-mutation authorization refuses before the gate is + reached — and records no fence row, the origin account's submission executes afresh, and the resulting fence row records the seed-origin account; (top-level variant, NEW-9) with the seed-company tuple @@ -1378,7 +1491,12 @@ Binding on the implementing PRs: succession, and an admin holding target-result read authority each probed — submits the §4.3 seed-progress query in both worlds and is refused byte-shape-identically in both, with no - event appended in either — proving the query surface discloses + event appended in either, and the refusal bytes are + additionally asserted byte-shape-identical to the seed-boundary + gate's conflict as returned to a gate-refused mutating + submitter — the cross-surface control proving one constant + shape spans the gate, succession, and query surfaces — and the + query surface therefore discloses nothing to anyone but the current designation; a **seed-progress entitlement witness (NEW-18)** — the SAME designated account submits the query in worlds U and P: it @@ -1392,6 +1510,30 @@ Binding on the implementing PRs: any committed position and without receiving a single refusal in the walk — proving progress location is a disclosed entitled read, never an inference from refusal shapes; a + **same-designation race witness (NEW-18)** — two fresh clients + C1 and C2 of the same grant-less designation both submit the + query and both receive the same `next` index i; C1 originates + position i and commits; C2 then submits the identical tuple + and is refused; C2 is asserted to follow the §4.3 + query/originate loop exactly — it does not retry, does not + advance to i+1 on its own, and interprets nothing from the + refusal — and re-submits the query, receiving a result + strictly beyond i (a greater `next` or `complete`), from which + it continues the loop to completion; per canonical key exactly + one mutation and one fence row exist; a fault variant of the + same witness refuses C2's origination while position i is + STILL unrecorded and asserts the re-query returns the SAME + index i, whereupon the client stops and surfaces the refusal + rather than looping — proving the loop distinguishes the + benign stale-query race from a genuine fault through the + entitled query alone; a **completed-world stop witness + (NEW-18)** — the actual fresh designated client is run against + a world whose canonical sequence is fully recorded: the query + returns the typed `complete` variant (asserted against the + closed DTO — a result value, not an error and not an index), + and the client stops, submitting zero originations and zero + other seed-key commands — proving the terminal branch is + defined, typed, and honored; a **designation-derived completion (NEW-12/NEW-13/NEW-19)** — origin A originates a prefix extending past workspace creation — so the remaining suffix consists of ordinary @@ -1414,8 +1556,29 @@ Binding on the implementing PRs: authority plus its own eligibility; a subsequent read attempt by that successor against a committed pre-succession seed record is refused — proving succession recovers completion without - conferring read or tenant authority; a **non-canonical content - refusal (NEW-19)** — a designation holding no grant (the + conferring read or tenant authority; an **active-window + boundary witness (NEW-19)** — in a world whose next unrecorded + canonical position IS an ordinary workspace-content example + position, a designation holding no grant submits, in that SAME + state: (a) that position's exact canonical tuple, which + succeeds under the designation-derived authority; (b) a + non-canonical content command against the seed workspace — a + second kanban item — which is refused by the owning content + contract's authorization with nothing written; and (c) a + content command against a workspace outside the seed set, + refused likewise; this witness is discriminating where the + post-completion refusal below is not — an incorrect evaluator + scoped by completion state rather than by canonical key (one + granting the designation all seed-workspace writes while + seeding is incomplete) passes the post-completion test but + fails branches (b) and (c) here, because they refuse while + seeding is still incomplete; after branch (a) commits, read + attempts by the acting designation and by a later successor + against BOTH predecessor-created and successor-created seed + content are refused — the bounded origination response is the + only disclosure either ever receives; a **non-canonical content + refusal (NEW-19)** — the post-completion variant of the same + boundary: a designation holding no grant (the self-revocation world, post-completion) submits, against the seed workspace, an ordinary content command whose (operation, key) is outside the canonical seed key set — a second, @@ -1423,13 +1586,18 @@ Binding on the implementing PRs: content contract's authorization with nothing written — proving the designation-derived authority stops at the canonical set and confers no general workspace authority; a - **result-disclosure witness (NEW-19)** — a successor's + **result-disclosure witness (NEW-19/NEW-20)** — a successor's content-position origination response and recorded outcome are - asserted to contain exactly the canonical outcome fields + asserted to carry, as their entire state-derived content, + exactly the canonical outcome fields (created row id, resolved parent id, canonical key, payload digest) and no attribute of any pre-existing record beyond the - resolved parent id — proving origination under the - designation-derived authority discloses nothing further; a + resolved parent id, while the response's envelope carries the + request's own correlation ids per contract 5 §4.3 — asserted + present, asserted equal to the request's, and derived from no + stored record — proving origination under the + designation-derived authority discloses nothing further and + still conforms to contract 5's result envelope; a **post-completion harmlessness control (NEW-16)** — with the seed sequence fully complete, the origin is banned and an eligible platform admin B @@ -1661,9 +1829,17 @@ contracts and are not additions: hierarchy-authority evaluation (the company, estate, project, and workspace positions); RBAC §§2–3's workspace-content authorization evaluation (the ordinary example-content - positions); and the native-kanban SOT's workspace-scoped + positions); the native-kanban SOT's workspace-scoped command authorization (REQ-TEN-001, Amendment A1 §8.1.3) for - the kanban example positions. For exactly the fresh + the kanban example positions; and — because RBAC §1 declares + its three authority layers (platform role, hierarchy grants, + workspace membership) exhaustive and "none substitutable" — + RBAC §1 itself, amended with a narrow ratified exception: for + exactly the mechanical scope below, the epoch's current + designation is a fourth, disclosed authority source, and + outside that scope §1's exhaustive rule stands unchanged, the + designation substituting for no layer on any other surface, + key, or command. For exactly the fresh origination of a currently-unoriginated canonical seed position, the epoch record's current designation itself satisfies that one component; the scope is mechanically @@ -1677,16 +1853,23 @@ contracts and are not additions: record, and nothing outside the canonical seed key set; it is evaluated per submission and writes nothing beyond the command's own canonical writes; and a successful origination's - response and recorded outcome are bounded to exactly the + response and recorded outcome are bounded, in their + state-derived content, to exactly the command's canonical outcome fields (created row id, resolved parent id, canonical key, payload digest) — the §4.3 - result-disclosure boundary. Third, the **seed-progress query** + result-disclosure boundary, whose responses remain ordinary + contract 5 §4 result DTOs carrying the mandated non-state + correlation envelope, amending nothing in contract 5. Third, + the **seed-progress query** (§4.3) — an addition to contract 5 §4's command-envelope surface, the owning contract of the item 4 fence table whose recording existence it reads: - one mapped read surface returning only the epoch's - next unrecorded canonical position index or a completion - marker, authorized for exactly the current designation, the + one mapped read surface whose result DTO conforms to contract + 5 §4.1/§4.3 (explicit DTO, correlation echoed) and whose + state-derived content is only the closed §4.3 discriminated + union — the epoch's next unrecorded canonical position index + (`next`) or the typed completion variant (`complete`) — + authorized for exactly the current designation, the screening evaluated before any fence state with every non-designated submitter refused with the constant-shape conflict byte-shape-identically across recorded and unrecorded