Answer the SPEC-v0.10 review round: eighteen findings, two more of my own - #173
Merged
rohanrkamath merged 2 commits intoSep 13, 2026
Merged
Conversation
An adversarial round against SPEC-v0.10 returned eighteen defects. All were checked against the tree before being answered; every one below was real. Two more are mine, found while reading item 3's and item 4's targets. The two that change the design. Control._suspend re-decides authority and takes no hop. It is the lease extension: control.py:2218 evaluates again and control.py:2227 raises AuthorityDenied, and the comment above it says why, that without it v0.3 section 5.7's "a chain of any depth is cut by one write" is false for exactly the actions in flight. Under section 2.3.2 the decision at execute's top is pinned to the hop and this one was not, so a receiver holding any grant of its own keeps its reservation across a round trip after the hop is cut. New section 3.4.3, with a table of where each path takes its hop from and why the context variable is right at _suspend and wrong at resume. Section 3.4.2's justification was also inverted: resume records and does not re-decide, which control.py:1847 says in a comment, so a hop there fixes which grant the receipt names, not blast radius. Three of six hop refusals report no_authority with no id. matches_shape filters on subject, action, resource and environment before any outcome is collected, so a hop that does not cover them falls out of the loop and evaluate returns no_authority with grant_id None. That is the milestone's headline refusal reported as "you hold no authority at all", with nothing to hand inspect --hop, and section 6.3 promised a command with its argument filled in. authority_hop now covers a presented hop that does not match the action's shape, carrying data.dimension. Section 2.3.3 has the probe. Also: -41013 was already ctrlrun.not_a_human, shipped in SPEC-mcp-operator and tested; retaken as -41016, the first free code. Rules 2 and 3 of section 2.3.2 contradicted each other on a revoked hop and covered no expired one; liveness is struck from rule 2. Section 2.3.1's narrative was false of the probe it displays, which shows an action inside the envelope, not outside it. A relay breaks rule 3 and G26: DELEGATION_CREATED is action-less by construction, so the created hop is linked to the action that created it by nothing but a timestamp; the event gains action_id and G26 becomes "a hop is named on both sides", graded over a chain with a middle. CreatedVia's rollback denies every action in the deployment, not one delegation, which makes the first hop the irreversible step; new section 9.3. The gateway reads no caller metadata and threads no task, and needs_approval routes through evaluate with neither, so section 9 froze no surface item 1 could wire. Section 4.4's load error is not implementable at load and would have stopped verify loading the example section 7.3 requires. Section 7.1's G25 requirement had no implementable construction. Section 6.2's chain[] needed a helper that does not exist and was singular where T470 is plural. The resumed-leg discriminator must be key presence, not value. Three citations were semantically wrong while line-accurate: contained_dimension has seven callers and a hop adds none, max_delegation_depth is a section key not a grant key, and require_v7 gates grant entries while upstream: is an action-entry key. Mine. The ordered list of section 5.2 cannot live inside the two _secure methods: policy_unapproved is decided at control.py:1293 above authority, while _observe_secure is not called until :1526, so a _secure-only refactor leaves v0.9 section 4.2.1b's second case broken and its generated pair test green. Measured, one action, one document: enforce raises policy_unapproved and observe reports no_authority. And section 4.2 pinned by digest while section 4.3 made the pinned certificates trust anchors, which a digest cannot be; a certificate-valued key is added, and a probe shows a CA-signed leaf with VERIFY_X509_PARTIAL_CHAIN admits the pinned server and refuses a swapped one. 48 line citations, all resolving. Tests T470-T507 plus T488a and T499a. Documentation only. No code changes. Signed-off-by: arpan <contact@arpanghoshal.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Round one's answer said a presented hop that does not match the action's shape reports authority_hop with data.dimension naming which of subject, actions, resources or environments failed. Grant.matches_shape (authority.py:534) returns a bool and returns False at the first failure, so that value exists on the stack and is discarded, and section 9 named nothing that could supply it. unmatched_shape(grant, action) -> str | None returns the first failing row, and matches_shape becomes a call to it so the two cannot drift. That is contained_dimension's shape applied to the other half of v0.3 section 4.3's iff, which is also why it is not a second walk inside evaluate. Found while reading the answer before writing code against it. Signed-off-by: arpan <contact@arpanghoshal.com>
This was referenced Sep 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #172. Documentation only, no code changes. Item 0's required spec review round, and
its answers.
An adversarial round ran against
SPEC-v0.10.mdin a session that did not write it, under theprobe-before-you-assert rule. It returned eighteen findings. I checked every one against the
tree before answering it; all eighteen were real. Two more are mine, found while reading item
3's and item 4's targets.
The two that change the design
Control._suspendre-decides authority, and §2.3.2 never reached it_suspendis the lease extension.control.py:2218evaluates authority again andcontrol.py:2227raisesAuthorityDenied, and the comment above it says exactly why:Under §2.3.2 the decision at
execute's top is pinned to the hop; this one was not. So a receiverholding any grant of its own keeps its reservation across the round trip after the hop is revoked,
and revocation fails to cut the in-flight action that check exists to cut. That is §10's row "there
is no fallback", inverted.
New §3.4.3 carries it, with a table of where each path takes its hop from:
executefrom thecaller,
_suspendfrom the context variable (same call, same stack),resumefrom the durableevent (a different call, whose ambient context is unrelated). T488a is the test, shaped so it cannot
pass for the wrong reason.
The same finding corrected §3.4.2's justification, which was inverted.
resumerecords and doesnot re-decide, which
control.py:1847says in a comment, so a hop there fixes which grant thereceipt names, not blast radius. I had borrowed an argument that does not apply.
Three of six hop refusals report
no_authoritywith no idmatches_shape(authority.py:536) filters on subject, action, resource and environment before anyoutcome is collected. P9, the only grant the principal holds being the hop:
That is the milestone's headline refusal, "this hop does not authorise this action", reported as
"you hold no authority at all" with nothing to hand
ctrlrun inspect --hop, while §6.3 promisesevery refusal naming a delegation prints a command with its argument filled in. G24's own catalogue
comment set the precedent: it reports
authority_task"rather than a bare no_authority so anoperator can tell this from having no grant at all".
authority_hopnow covers a presented hop that does not match the action's shape, carryingdata.dimension. §2.3.3 has the probe and the argument.The rest, in one table
-41013was already taken byctrlrun.not_a_human, shipped inSPEC-mcp-operator§9.3 and tested. One namespace, and I spent an allocated number-41016, the first free code after-41015. §4.5 records that a new identifier in a shared namespace is searched for before it is spentCreatedVia's rollback denies every action in the deployment, not one delegation.authority.py:118-123says so in the sourceDELEGATION_CREATEDis action-less by construction (control.py:4316), so the created hop is linked to its action by a timestampaction_idwhen the hop was created inside an action; G26 becomesa hop is named on both sidesand must be graded over a chain with a middleverifyloading the example §7.3 requiresupstream_unverifiedat decision timeverifycannot mint a root, and a sibling delegation makes the control a coin flip onsecrets.token_hexN/Areason addedneeds_approvalroutes throughevaluatewith no hop, so the predicate disagrees withexecuteone frame upchain[]needed a helper that does not exist (contained_dimensioncomputes the complement) and was singular where T470 is pluralnarrowed_dimensions, explicitly a reporting helper that decides nothing, so §2.2's one-relation rule holds{"hop": …, "task": None}missing_parent_idcarries is by construction unreadable, so the printed command must failcontained_dimensionhas seven callers and a hop adds none;max_delegation_depthis anauthority:key, not a grant key;require_v7gates grant entries whileupstream:is an action-entry keyMy two
§5.2's ordered list cannot live inside the two
_securemethods.policy_unapprovedis decidedby
_require_approvedatcontrol.py:1293, above authority at:1298, and returns early whenobserving;
_observe_secureis not called until:1526. P7, one action, one document:An item unifying only the two methods leaves that case exactly as broken and its generated pair
test passes, because the pair set is built from a list that never covered it. The order to declare
is already a comment at
control.py:1296. T499a is the test.§4.2 pinned by digest while §4.3 made the pinned certificates trust anchors. A digest cannot be
a trust anchor;
load_verify_locationstakes PEM. P8, against a CA-signed leaf:The mechanism works, so §4.2 gains a certificate-valued key for check 3, the digest serves checks 1
and 2, and pinning by digest alone is stated as getting two checks rather than three. §9 gains the
ssl_context=rowgateway/transport.py:155needs.What the review confirmed as correct
Worth recording, because most of the document held. It reproduced P1, P5 and P5(b) byte for byte;
stress-tested transitivity far harder than I did (1,043 grants, 2,910 contained pairs, 5,058
triples, 0 violations, plus 13,024 pairs checked for soundness over 10,800 situations); confirmed
the title widths, the schema arithmetic, §5.1's ordering line numbers, §3.4.2's event claims, the
no-migration analysis, and all 33 citations, independently, 0 unresolved.
Checks
off-by-one errors introduced during this edit were caught by that check and fixed.
T470toT507, contiguous, plusT488aandT499a(theT91d/T223bsuffix convention).
What a second round should look at
The reviewer's own list, carried forward rather than closed: the remaining
_authority_resultcallsites (
Control.evaluateatcontrol.py:865, and the observe path); contextvar hygiene now that_HOPjoins_TASK,_AUTHORITY_GRANT_ID,_AUTHORITY_RESULTand_BUDGET_CHARGES, with anested suspend-and-resume case; §5 as a whole, which got the least attention; §4 against a real TLS
listener; and whether adding
hopto the receipt moves the hashed shape in a way G11 notices.Not merging and not tagging.