SPEC-v0.11 review round three: fourteen findings, and the scope question they answer - #197
Merged
Merged
Conversation
… about the scope Round two's section 4.6, written because two sections cancelled each other, cancelled against a rule round two added in the same commit. Section 3.2 required every anchor's seq to exceed the last; section 4.6 requires anchoring a checkpoint far below the head, at the pruned-through seq. So the checkpoint anchor was refused, so every prune was refused, forever. The section that names the cross-module class reproduced it one round later. Fixed by giving anchors a kind: interval and checkpoint are ordered separately. **The "superseded" defence needed a provider call that did not exist.** Section 4.6 claims an attacker who launders an erasure must leave an anchored checkpoint an operator can see. The frozen provider had make, check and latest, and the only anchor history the kernel could read was the local table, which section 3.3 establishes is a cache the writer under suspicion can trim. The provider gains since(seq), which is enumeration answered outside, and the prune verifies the anchors it is about to supersede while the rows that would settle it still exist. **The ledger window was not computable.** A ledger row carries no window and no limit; those travel on Charge, from the authority document, because state.py must not read policy. Resolving it inside the prune would reinstate the dependency section 4.2 removes, and a row whose grant is gone has no window at all. The operator supplies it: ctrlrun prune --older-than. **anchor_unavailable leaves the break set.** A transport failure is not a finding about evidence, and a set that conflates them teaches operators to ignore the ones that matter: a briefly unreachable timestamp authority would have graded G28 fail, indistinguishable from a truncation. Refusing to act when you cannot ask is fail-closed; reporting tampering when you cannot ask is a false positive. anchor_repudiated joins it, because check() answering no had no name and it is the provider's one substantive answer. **G32 is new.** G28 graded truncation against an anchor and G29 graded a prune against the chain; the interaction section 4.6 exists to fix was graded by neither, which is how two correct sections ship cancelling each other. Also: rule 2 and section 8's G29 still stated the absolute where section 10 had moved to a delta; that delta compared kinds rather than (kind, seq), so one pre-existing break disarmed the guard for that kind everywhere; a refused prune would have left a receipt asserting an erasure that never happened; section 9 had no row for item 1, which amends a frozen protocol and adds a public type; and three line-number citations into the other repository were wrong within a day, so they are cited by their words now. Section 12.3 records the round counts, and what they diagnose. Almost every high finding after round one lives in the interaction between the anchor and retention, not in either alone. That is evidence for the scope question section 1 leaves to the maintainer, and it is sharper evidence than existed when section 1 was written. Signed-off-by: arpan <contact@arpanghoshal.com>
|
Warning Review limit reachedNext included review available in 36 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
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 |
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 #196. Third round, on the rule that gave v0.9 and v0.10 three each.
§4.6 cancelled against a rule added in the same commit
Round two wrote §4.6 because two sections cancelled each other. It then cancelled against §3.2's
new monotonicity rule, added in that same commit:
seqis at or below the one before it is refused."seq.Anchoring hourly and pruning at ninety days, the checkpoint sits far below the newest anchor. So
the checkpoint anchor is refused, so every prune is refused, forever. §4.6 exists because a
deployment should not have to choose between pruning and a permanent tamper signal; as drafted it
landed on the first horn.
Fixed by giving anchors a
kind:intervalandcheckpointare ordered separately.The "superseded" defence needed a call that did not exist
§4.6 claims an attacker who launders an erasure must leave an anchored checkpoint an operator can
see. The frozen provider had
make,check,latestand no enumeration, so the only anchorhistory the kernel could read was the local table, which §3.3 spends a subsection establishing is a
cache the writer under suspicion can trim. Delete every local row at or below the laundering
checkpoint and
latest()shows nothing.Two fixes, both needed: the provider gains
since(seq), answered outside; and the pruneverifies the anchors it is about to supersede while the rows that would settle it still exist.
The ledger window was not computable
A ledger row carries
grant_id,metric,amount,effect_key,attempt,consumed_at,released_at. No window, no limit. Those travel onCharge, andstate.pysays why: a storethat resolved a grant's budgets would be reading the policy.
So resolving it inside the prune reinstates exactly the dependency §4.2 removes, and a row whose
grant is no longer in the document has no window at all. The operator supplies it:
ctrlrun prune --older-than. The kernel checks the rule rather than deriving the input, which isSPEC-v0.9.md§5.4's shape again.anchor_unavailableleaves the break setA transport failure is not a finding about evidence. In the set, a briefly unreachable timestamp
authority grades
G28fail, indistinguishable in the report from a truncation.SPEC-v0.10.md'supstream_unverifiedis the precedent and cuts the other way: it is a decision-time refusal, nota break in a verification report. Refusing to act when you cannot ask is fail-closed; reporting
tampering when you cannot ask is a false positive, and it is §3.4's own argument one level out.
anchor_repudiatedjoins the set, becausecheck()answering no had no name and it is theprovider's one substantive answer.
G32G28graded truncation against an anchor,G29graded a prune against the chain, and theinteraction §4.6 exists to fix was graded by neither. A guarantee for each half and none for the
pair is how two correct sections ship cancelling each other.
Also
Rule 2 and §8's
G29still stated the absolute where §10 had moved to a delta; that delta comparedkinds rather than
(kind, seq), so one pre-existing break disarmed the guard for that kindeverywhere; a refused prune would have left a receipt asserting an erasure that never happened;
§9 had no row for item 1, which amends a frozen protocol and adds a public type; and three
line-number citations into the other repository were wrong within a day, so they are cited by their
words now.
What three rounds actually diagnose
Almost every high finding after round one lives in the interaction between the anchor (item 2) and
retention (item 3), not in either alone: the honest prune breaking every older anchor, the
checkpoint anchor refused by the anchor ordering, the laundering attack, the uncomputable window. The
anchor alone and the reader alone generated few defects and no high ones after round one.
§1 leaves open whether this is one milestone or two. That question is now answerable from
measurements, and §12.3 records them. It remains the maintainer's.
Every cross-reference resolves. No em dashes.
Not merging.