Skip to content

Scope codec and intent frame; D0's intent and purpose use them (d0_store_operation_wall PR 2/5) - #12476

Merged
gunbai-bot[bot] merged 12 commits into
mainfrom
lively-dove-256-pr2
Sep 28, 2026
Merged

gunbai-bot[bot] merged 12 commits into
mainfrom
lively-dove-256-pr2

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

PR 2 of the d0_store_operation_wall sequence (#12458 is PR 1). It is independent of #12458 and branches off main.

Why. The fabric store door must learn which scope the operator approved for the operation it is admitting. The approval broker records no scope: it brokers one authority, and its request stores purpose and revision only. Adding a field to the stored request would break the operator's phone app, whose apps/approve-ios Wire.swift decodes that JSON against a strict field allowlist.

The approved revision is already the SHA-256 of the operation's intent text. So proud-deer-538 ruled option A: the intent text states its scope, through ONE typed codec that the filer writes and the store reads. The store never parses free text.

What lands.

  • std.effect_grant verb_of_label / namespace_tree_of_label: the exact inverses of the existing labels.
  • std.scoped_authorization:
    • authorization_scope_wire / parse_authorization_scope_wire: verb, tree, path and action as four fields. A scope with no unambiguous wire is refused at encode, and decode admits only what encode writes (checked by round trip).
    • authorization_scope_eq: exact scope identity.
    • The intent frame, intent_frame_head / parse_intent_scopes: a schema line, then one scope= line per scope. A verifier reads the scopes by position with no domain knowledge. An intent with no decodable scope has no frame, so it is refused rather than read as requiring nothing.
  • gunbc.spark.pair_serving_d0:
    • D0's intent (schema v1 → v2) is written through the frame, and parse_d0_intent_text refuses any text whose frame does not state exactly D0's scope.
    • The filed purpose is now rendered from the same typed scope and subject (d0_purpose). The operator's notification shows the purpose, not the intent text. Before this change D0's purpose was a constant sentence, so the operator approved without seeing the scope or the hosts. The operator now reads a rendering of what the store will check.
    • The schema bump is safe because no D0 filing exists: the wall has kept D0 from running.

Consumers. The D0 filing and parse execute the codec in this PR. The fabric store door (PR 3) consumes parse_intent_scopes over the frozen filing whose SHA-256 is the approved revision.

Evidence. The new witnesses are in test.claim.scoped_authorization_scope_wire (round trip across all four trees, no-wire refusals, undecodable bytes, frame read-back, frame RED) and in pair_serving_d0_witness (the_intent_text_states_its_scope_in_the_shared_frame). They have not executed before CI: remote claim_batch was OOM-killed on BuildBuddy after corpus warm, even for this std-only file. The floor lane is their first run.

🤖 Generated with Claude Code

Brian Searls and others added 4 commits September 28, 2026 01:10
… and purpose use them

The fabric store door (d0_store_operation_wall) must learn the approved scope
of an operation without a broker or phone-app change (proud-deer-538, option
A): the approved revision is the sha256 of the intent text, so the intent
text states its scope through ONE typed codec that filer and verifier share.

- std.effect_grant: verb_of_label / namespace_tree_of_label, the labels'
  exact inverses.
- std.scoped_authorization: authorization_scope_wire /
  parse_authorization_scope_wire (round-trip checked), authorization_scope_eq,
  and the intent frame (intent_frame_head / parse_intent_scopes): a schema
  line then one scope= line per scope; no decodable scope, no frame.
- gunbc.spark.pair_serving_d0: the intent (schema v2) is written and read
  through the frame; the filed purpose is rendered from the same typed scope
  and subject, so the operator's notification shows what the store checks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…on is_empty bare-provider debt row (floor UnimportedBareProvider)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-provider debt row

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…mment back on authorization_scopes_render (review 72009)

d0_intent_text returns String? and every caller carries the refusal: the
hash, the parser's round-trip check, the door (D0RunRefused before any
filing is frozen) and the witnesses (a refused intent fails them, never
passes by two empty strings comparing equal). The 'could not be digested'
messages now name both causes of an absent intent.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Addressing review 72009 in fcc900a. Both findings are fixed.

  1. The rationale comment is back directly above authorization_scopes_render.
  2. d0_intent_text returns String?, and the refusal now happens at the filer. d0_intent_hash, the parser's round-trip check, and the D0 door (D0RunRefused before any filing is frozen) all carry it. Tests match on it too, so a refused intent fails them rather than passing because two empty strings compare equal.

— sent from lively-dove-256

Brian Searls and others added 7 commits September 28, 2026 03:32
… 72048)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ute: route-gap enrolment plus a wet-lane schedule

d0_intent_text returns String? (review 72009), which edits three existing
witnesses whose effects (DigestStdin, Dir) have no hermetic route. The
changed-witness gate admits them as HermeticRouteGapHeldAndWetPassed when
the route gap is enrolled AND they are scheduled on the local-repo wet lane
AND pass there on this candidate; this adds the first two facts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… live candidate

Scheduling it on the wet lane executed it for the first time, and it failed:
it asserted a first run refuses before filing, a premise that went stale when
the V4.1 candidate was keyed on 2026-09-24 (v41_runtime_candidate
the_live_candidate_is_keyed_end_to_end). A first run now either refuses and
freezes nothing, or freezes exactly the filing it asks over; either way the
rerun, other-revision and other-transaction claims hold for what was frozen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…en door witness's hunk context lands in it

Its body is unchanged, but the diff hunk rewriting the next witness's
comment carries three context lines inside it, so the changed-witness gate
attributes the change to it. Route-gap enrolment plus a wet-lane schedule
admit it as HermeticRouteGapHeldAndWetPassed, and it executes for real.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…72135)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit bf2834c Sep 28, 2026
6 checks passed
@gunbai-bot
gunbai-bot Bot deleted the lively-dove-256-pr2 branch September 28, 2026 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants