Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
0947e23
The logical half of the closure recut: an incomplete closure can name…
Aug 23, 2026
7b5270c
Rename the fused format to what it is: commit_closure_json_v1, with n…
Aug 23, 2026
4b418e0
Merge remote-tracking branch 'origin/main' into session/closure-recut
Aug 23, 2026
8751801
Two-arm references: positions name what is here, content addresses na…
Aug 23, 2026
5dc74a6
Strip the temporary verification drivers
Aug 23, 2026
19d021b
A target carrying both arms was silently answering with one of them (…
Aug 23, 2026
d735c8b
Publication standings, in a vocabulary no format owns -- and the arm …
Aug 23, 2026
3892cf1
Hoist two comment blocks to module-item grain: DESIGN 4c refuses a bo…
Aug 23, 2026
8dcac7f
Merge branch 'session/closure-recut' into session/load-standings
Aug 23, 2026
1efe07e
Two version names for one realization, and an admission wall two revi…
Aug 23, 2026
1e7a6cc
Merge branch 'session/closure-recut' into session/load-standings
Aug 23, 2026
4d26a39
Fix the stacked-rename dangling import: the witness pointed at commit…
Aug 23, 2026
c856db5
Repoint the eight image.dag citations at the module that exists
Aug 23, 2026
f8b4337
Merge session/closure-recut: the image.dag citation repair
Aug 23, 2026
ade8ad4
Select the target arm on presence, so a broken `at` is refused agains…
Aug 23, 2026
6aad5a2
Merge session/closure-recut: presence-based target arm selection
Aug 23, 2026
51a085a
Fix both quadratic folds in uncontained_targets, and make the order they
Aug 23, 2026
9f7c13a
Fix both quadratic folds in uncontained_targets, and make the order they
Aug 23, 2026
065dfbc
Merge session/closure-recut: cost-shape fix and the order claim that …
Aug 23, 2026
7bc262a
Split the encode refusal domain out of the decode one, so the load cl…
Aug 23, 2026
ed9ed89
Bind the partial-closure admission to its subject, so a token for A c…
Aug 23, 2026
45b5891
Narrow the repository encode refusal to the one cause encoding can pr…
Aug 23, 2026
a5450f4
Say only what the evidence establishes: an uncontained target, not th…
Aug 23, 2026
4fbc5e5
Correct the driver's coverage invariant: an identity set, not a count
Aug 23, 2026
e7e04b5
Merge main: fleet witness repairs and stage0 mirror
Aug 23, 2026
5d2e6db
Merge session/closure-recut (incl. main)
Aug 23, 2026
1169041
Merge session/load-standings (incl. main)
Aug 23, 2026
f0845da
Merge main (#9012): live_deploy cost split
Aug 23, 2026
f268829
Merge session/load-standings
Aug 23, 2026
5d81f8c
Merge session/closure-recut
Aug 23, 2026
35c8d2d
Delete the temporary ProcessExit drivers: their dissolution trigger h…
Aug 23, 2026
1d8a6db
Merge remote-tracking branch 'origin/main' into pickup/carrier-exactness
Aug 23, 2026
fb2e496
One authority for what reading a named JSON member can fail with
Aug 23, 2026
6039778
SCM: close an authority-escalation path and a bearer-token admission …
gunbai-bot[bot] Aug 23, 2026
8c707a7
Merge main (00ad29e) into session/load-standings
Aug 23, 2026
4c2edd5
Merge session/load-standings (now carrying main) into scm-member-auth…
Aug 23, 2026
345defa
Merge remote-tracking branch 'origin/main' into HEAD
Aug 24, 2026
602dc6c
Merge remote-tracking branch 'origin/session/load-standings' into ses…
Aug 24, 2026
e96d33e
Merge main (852a7287987, incl. #8973 squashed) — resolve the vocabula…
Aug 25, 2026
9677129
Delete the four function definitions the main merge duplicated
Aug 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 80 additions & 77 deletions dag/gunbc/scm/commit_closure_json_v2.dag

Large diffs are not rendered by default.

98 changes: 98 additions & 0 deletions dag/gunbc/scm/json_member.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
module gunbc.scm.json_member

// READING A NAMED MEMBER OFF A JSON OBJECT IS ONE OPERATION WITH ONE FAILURE POPULATION, and this
// module owns both. It was previously homed inside gunbc.scm.commit_closure_json_v2 with its failure
// typed as THAT module's ClosureDocRefusal, which is the layer inversion DESIGN section 3 names: a
// domain-neutral facility carrying a domain's vocabulary. The measured cost was not stylistic. Every
// repository-envelope member read -- `checked_out`, `identity_rule`, `root`, `message` -- had to
// report its failure as RepositoryDecodeClosureDocRefusal, so "the repository envelope names no
// checked_out member" was reported to the operator as "the closure document is malformed". That is
// authority substitution: one carrier's vocabulary borrowed to answer for another's, with nothing
// false in either half and the arrow between them invented.
//
// The refusal population here is exactly what reading a named member can fail with, and nothing
// wider. A domain wraps it in one arm rather than restating its members, so a new member-read
// failure mode is added once here and every domain's classifier refuses to compile until it says
// what the new mode means for it.

import std.types { Bool, Int, List, String }
import extdeps.languages.json.parse {
JsonMemberLookup,
JsonMemberFound,
JsonMemberAbsent,
JsonMemberDuplicated,
JsonMemberNotAnObject,
json_object_unique_member,
}
import extdeps.languages.json.emit {
JsonValue,
JsonNull,
JsonBool,
JsonNumber,
JsonString,
JsonArray,
JsonObject,
}

// FOUR DISTINCT FACTS, NEVER AN ABSENT VALUE. json_object_unique_member already separates a missing
// member from a duplicated one from a non-object subject, and collapsing them into an Optional here
// would be the state-space conflation DESIGN section 5 names. The duplicate arm is the one that
// earns its keep on its own: a JSON object carrying the key twice is precisely the shape a naive
// last-wins reader accepts while holding two answers, so it must refuse rather than pick.
//
// MemberReadWrongShape is produced BOTH here and by callers, and that is deliberate rather than a
// leak. read_member narrows only as far as the three shapes it can name; a caller wanting a string
// where an array is equally well-formed JSON narrows the rest of the way and reports the same fact.
// The fact is "reading member K off this object did not yield what the format declares", and who
// finished the narrowing does not change it.
type MemberReadRefusal
= MemberReadSubjectNotObject
| MemberReadMissing { key: String }
| MemberReadDuplicated { key: String }
| MemberReadWrongShape { key: String }

// The shape-AGNOSTIC read: the member is present and unique, or it is one of the three lookup
// failures. A caller whose format admits several JSON shapes at one key -- a nullable reference,
// say -- matches the value itself rather than re-inlining the three failure arms.
type MemberPresence
= MemberValue { value: JsonValue }
| MemberLookupFailed { cause: MemberReadRefusal }

fn read_member_value(v: JsonValue, key: String) -> MemberPresence {
match json_object_unique_member(v: v, key: key) {
JsonMemberAbsent => MemberLookupFailed { cause: MemberReadMissing { key: key } }
JsonMemberDuplicated { count: _ } => MemberLookupFailed { cause: MemberReadDuplicated { key: key } }
JsonMemberNotAnObject => MemberLookupFailed { cause: MemberReadSubjectNotObject }
JsonMemberFound { value: found } => MemberValue { value: found }
}
}

type MemberRead
= MemberString { value: String }
| MemberArray { elements: List<JsonValue> }
| MemberObject { value: JsonValue }
| MemberFailed { cause: MemberReadRefusal }

fn read_member(v: JsonValue, key: String) -> MemberRead {
match read_member_value(v: v, key: key) {
MemberLookupFailed { cause: c } => MemberFailed { cause: c }
MemberValue { value: found } =>
match found {
JsonString { value: s } => MemberString { value: s }
JsonArray { elements: es } => MemberArray { elements: es }
JsonObject { members: _ } => MemberObject { value: found }
JsonNull => MemberFailed { cause: MemberReadWrongShape { key: key } }
JsonBool { value: _ } => MemberFailed { cause: MemberReadWrongShape { key: key } }
JsonNumber { lexeme: _ } => MemberFailed { cause: MemberReadWrongShape { key: key } }
}
}
}

fn read_string_member(v: JsonValue, key: String) -> MemberRead {
match read_member(v: v, key: key) {
MemberString { value: s } => MemberString { value: s }
MemberFailed { cause: c } => MemberFailed { cause: c }
MemberArray { elements: _ } => MemberFailed { cause: MemberReadWrongShape { key: key } }
MemberObject { value: _ } => MemberFailed { cause: MemberReadWrongShape { key: key } }
}
}
67 changes: 29 additions & 38 deletions dag/gunbc/scm/repository_envelope.dag
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,23 @@ import extdeps.languages.json.emit {
json_object,
json_string,
}
import extdeps.languages.json.parse {
JsonMemberFound,
JsonMemberAbsent,
JsonMemberDuplicated,
JsonMemberNotAnObject,
json_object_unique_member,
}

import gunbc.scm.json_member {
MemberReadRefusal,
MemberReadWrongShape,
MemberValue,
MemberLookupFailed,
MemberString,
MemberArray,
MemberFailed,
read_member,
read_member_value,
read_string_member,
}
import gunbc.scm.object_store { ObjectId, ObjectStore, empty_store, object_id_eq }
import gunbc.scm.commit_closure { uncontained_targets }
import gunbc.scm.commit_closure_json_v2 {
ClosureDocRefusal,
ClosureDocMemberMissing,
ClosureDocMemberDuplicated,
ClosureDocMemberWrongShape,
ClosureDocNotAnObject,
ClosureDocFormatUnrecognized,
ClosureDocRootUnresolved,
ClosureDocEdgeTargetUnresolved,
DecodeAcc,
DecodePositions,
Expand All @@ -68,11 +67,6 @@ import gunbc.scm.commit_closure_json_v2 {
TargetDecode,
TargetDecoded,
TargetDecodeFailed,
read_string_member,
MemberString,
MemberArray,
MemberFailed,
read_member,
}

// THE ENCODING IS NOT CANONICAL WITH RESPECT TO INSERTION HISTORY, and that is declared here rather
Expand Down Expand Up @@ -166,6 +160,8 @@ type RepositoryEncodeRefusal
// reader finds a declared gap instead of re-deriving it.
type RepositoryDecodeRefusal
= RepositoryDecodeClosureDocRefusal { cause: ClosureDocRefusal }
| RepositoryMemberReadRefused { cause: MemberReadRefusal }
| RepositoryFormatUnrecognized { found: String }
| RepositoryIdentityRuleUnrecognized { found: String }
| RepositoryCommitRootReferenceUnresolved { reference: String }
| RepositoryCheckoutReferenceUnresolved { reference: String }
Expand Down Expand Up @@ -512,11 +508,11 @@ fn decode_commit_members(positions: DecodePositions, acc: CommitDecodeAcc, value
refusal: acc.refusal,
}
_ =>
CommitDecodeAcc { commits: acc.commits, refusal: Present { value: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberWrongShape { key: "message" } } } }
CommitDecodeAcc { commits: acc.commits, refusal: Present { value: RepositoryMemberReadRefused { cause: MemberReadWrongShape { key: "message" } } } }
}
}
_ =>
CommitDecodeAcc { commits: acc.commits, refusal: Present { value: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberWrongShape { key: "root" } } } }
CommitDecodeAcc { commits: acc.commits, refusal: Present { value: RepositoryMemberReadRefused { cause: MemberReadWrongShape { key: "root" } } } }
}
}
}
Expand Down Expand Up @@ -545,22 +541,22 @@ fn repository_format_of(tag: String) -> RepositoryFormat {

fn decode_repository(v: JsonValue) -> RepositoryDecodeOutcome {
match read_string_member(v: v, key: "format") {
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: c } }
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: c } }
MemberString { value: format } =>
match repository_format_of(tag: format) {
RepositoryFormatUnknown { found: f } =>
RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocFormatUnrecognized { found: f } } }
RepositoryDecodeRefused { cause: RepositoryFormatUnrecognized { found: f } }
RepositoryFormatV1 => decode_repository_v1(v: v)
}
_ => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberWrongShape { key: "format" } } }
_ => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: MemberReadWrongShape { key: "format" } } }
}
}

// EXACTLY v1. Every member population below is v1's, and this body is frozen once a v1 document
// exists anywhere.
fn decode_repository_v1(v: JsonValue) -> RepositoryDecodeOutcome {
match read_string_member(v: v, key: "identity_rule") {
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: c } }
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: c } }
MemberString { value: rule } =>
if rule != repository_node_identity_rule_tag {
RepositoryDecodeRefused { cause: RepositoryIdentityRuleUnrecognized { found: rule } }
Expand All @@ -574,21 +570,21 @@ fn decode_repository_v1(v: JsonValue) -> RepositoryDecodeOutcome {
Absent => decode_repository_body(v: v)
}
}
_ => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberWrongShape { key: "identity_rule" } } }
_ => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: MemberReadWrongShape { key: "identity_rule" } } }
}
}

fn decode_repository_body(v: JsonValue) -> RepositoryDecodeOutcome {
match read_member(v: v, key: "objects") {
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: c } }
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: c } }
MemberArray { elements: object_values } =>
match decode_object_table(object_values: object_values) {
DecodeAcc { store: store, positions: positions, next: _, refusal: table_refusal } =>
match table_refusal {
Present { value: c } => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: c } }
Absent =>
match read_member(v: v, key: "commits") {
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: c } }
MemberFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: c } }
MemberArray { elements: commit_values } =>
match fold(
commit_values,
Expand All @@ -604,11 +600,11 @@ fn decode_repository_body(v: JsonValue) -> RepositoryDecodeOutcome {
)
}
}
_ => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberWrongShape { key: "commits" } } }
_ => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: MemberReadWrongShape { key: "commits" } } }
}
}
}
_ => RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberWrongShape { key: "objects" } } }
_ => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: MemberReadWrongShape { key: "objects" } } }
}
}

Expand All @@ -622,14 +618,9 @@ fn decode_repository_checkout(
positions: DecodePositions,
commits: List<RepositoryCommit>
) -> RepositoryDecodeOutcome {
match json_object_unique_member(v: v, key: "checked_out") {
JsonMemberAbsent =>
RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberMissing { key: "checked_out" } } }
JsonMemberDuplicated { count: _ } =>
RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberDuplicated { key: "checked_out" } } }
JsonMemberNotAnObject =>
RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocNotAnObject } }
JsonMemberFound { value: found } =>
match read_member_value(v: v, key: "checked_out") {
MemberLookupFailed { cause: c } => RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: c } }
MemberValue { value: found } =>
match found {
JsonNull =>
RepositoryDecoded {
Expand All @@ -647,7 +638,7 @@ fn decode_repository_checkout(
}
}
_ =>
RepositoryDecodeRefused { cause: RepositoryDecodeClosureDocRefusal { cause: ClosureDocMemberWrongShape { key: "checked_out" } } }
RepositoryDecodeRefused { cause: RepositoryMemberReadRefused { cause: MemberReadWrongShape { key: "checked_out" } } }
}
}
}
9 changes: 0 additions & 9 deletions dag/test/claim/scm_commit_closure_json_v2_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ import gunbc.scm.commit_closure_json_v2 {
ClosureDocRefused,
ClosureDocRefusal,
ClosureDocFormatUnrecognized,
ClosureDocMemberMissing,
ClosureDocMemberDuplicated,
ClosureDocEdgeTargetUnresolved,
ClosureDocRootUnresolved,
ClosureDocUnknownConnectiveTag,
Expand Down Expand Up @@ -657,13 +655,6 @@ fn scm_image_atom_object_members(kind_members: List<JsonKeyValue>, extra: List<J
)
}

fn scm_image_refused(loaded: ClosureDocLoadOutcome) -> Bool {
match loaded {
ClosureDocRefused { cause: _ } => true
ClosureDocLoaded { store: _, root: _ } => false
}
}

test fn scm_image_an_unknown_envelope_member_refuses() -> Bool {
scm_image_refused(
loaded: decode_closure_document(
Expand Down
8 changes: 4 additions & 4 deletions dag/test/claim/scm_commit_closure_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ import gunbc.scm.object_store {
import v2.std.collection { empty_map }
import extdeps.languages.json.emit { serialize_json, json_object, json_kv, json_string, JsonValue, JsonObject }
import extdeps.languages.json.parse { parse_json }
import gunbc.scm.json_member { MemberReadDuplicated, MemberReadWrongShape }
import gunbc.scm.commit_closure_json_v2 {
ClosureDocRefusal,
ClosureDocIncompleteWithoutAdmission,
ClosureDocEncodeRefusal,
ClosureDocTargetNotOneArm,
ClosureDocMemberDuplicated,
ClosureDocMemberWrongShape,
ClosureDocMemberReadRefused,
TargetDecode,
TargetDecoded,
TargetDecodeFailed,
Expand Down Expand Up @@ -465,7 +465,7 @@ test fn a_duplicated_at_is_refused_against_at() -> Bool {
) {
TargetDecodeFailed { cause: c } =>
match c {
ClosureDocMemberDuplicated { key: k } => k == "at"
ClosureDocMemberReadRefused { cause: MemberReadDuplicated { key: k } } => k == "at"
_ => false
}
TargetDecoded { target: _ } => false
Expand All @@ -481,7 +481,7 @@ test fn a_non_string_at_is_refused_against_at() -> Bool {
) {
TargetDecodeFailed { cause: c } =>
match c {
ClosureDocMemberWrongShape { key: k } => k == "at"
ClosureDocMemberReadRefused { cause: MemberReadWrongShape { key: k } } => k == "at"
_ => false
}
TargetDecoded { target: _ } => false
Expand Down
7 changes: 5 additions & 2 deletions dag/test/claim/scm_load_standing_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import gunbc.scm.load_standing {
LoadDocumentMalformed, LoadIdentityCollision,
standing_may_supersede_generation, standing_loaded,
}
import gunbc.scm.json_member { MemberReadSubjectNotObject }
import gunbc.scm.commit_closure_json_v2 {
ClosureDocRefusal, ClosureDocFormatUnrecognized, ClosureDocObjectCollision,
ClosureDocNotAnObject, ClosureDocMemberMissing, ClosureDocUnknownKindTag,
ClosureDocMemberReadRefused, ClosureDocUnknownKindTag,
ClosureDocUnexpectedMember, ClosureDocEnvelopeMembers, ClosureDocEdgeTargetUnresolved,
ClosureDocTargetNotOneArm,
closure_document_load_standing, loaded_closure_standing,
Expand Down Expand Up @@ -144,7 +145,9 @@ test fn an_honest_collision_is_its_own_standing_and_never_supersedes() -> Bool {
let collision = closure_document_load_standing(
cause: ClosureDocObjectCollision { identity: ls_full().root }
)
let malformed = closure_document_load_standing(cause: ClosureDocNotAnObject)
let malformed = closure_document_load_standing(
cause: ClosureDocMemberReadRefused { cause: MemberReadSubjectNotObject }
)
standing_eq(a: collision, b: LoadIdentityCollision)
&& standing_eq(a: malformed, b: LoadDocumentMalformed)
&& !standing_may_supersede_generation(standing: collision)
Expand Down
Loading
Loading