Skip to content

guard: varve rotated the rolling trust root — the new realms file would orphan our pin, and the diff looks like a no-op (AFD-112) - #255

Merged
avrabe merged 2 commits into
mainfrom
guard/varve-realm-rotation
Sep 7, 2026
Merged

guard: varve rotated the rolling trust root — the new realms file would orphan our pin, and the diff looks like a no-op (AFD-112)#255
avrabe merged 2 commits into
mainfrom
guard/varve-realm-rotation

Conversation

@avrabe

@avrabe avrabe commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

guard: varve rotated the rolling trust root — taking the new realms file would orphan our pin, and the diff looks like a no-op (AFD-112)

varve v0.32.1 is NOT the consumer-API release we asked for on varve#130. Its own
notes: "There is no code change from v0.32.0 — no behaviour, no CLI, no format."
It exists to publish a rotated rolling trust root, 4e771dc6... -> 7d3b892e...

Our correct action is to do nothing, and that is varve's own instruction. Layers
2026.08.0..2026.09.1 are signed by the OLD root; 2026.09.2 will be the first signed
by the new one. We pin 2026.08.4 and carry the OLD root — the correct pairing.
Verified rather than assumed: varve verify reports "layer 2026.08.4 ... verified:
signature OK, 11 tool(s) match their signed digests". It exits 1 only on PATH
shadowing, which is the advisory class AFD-111 just separated out — the two
checkers agree.

Also ran varve's own falsification test from the release notes: the published
rolling.pub and varve-realms.toml name the same root. AGREE.

THE HAZARD. The published varve-realms.toml is byte-identical to ours except the
trust-root line — measured, the diff is empty once that line is masked. So
"vendor the new realms file" reads in review as a one-line no-op and produces:

error: manifest signature verification failed: ... No valid signatures

This repo runs an autonomous 4h loop that bumps pins on evidence; it bumped rivet
and spar to the pin earlier today. A rule that lives only in a release note is a
rule that loop will not see. tools/varve/check-realm.sh makes it executable and
refuses a realm/pin pairing whose root cannot verify the pinned layer, in EITHER
direction, plus an unrecognised root. --self-test runs five rows and BOTH failure
modes are observed failing, including the trap itself. The layer comparison is
numeric, not lexical: 2026.09.10 must sort ABOVE the 2026.09.2 boundary, and a
string compare puts it below.

varve-core 0.32.1 against our four asks — two landed:
(a) held-payload kind + locate: LANDED. kind::PayloadKind (8 variants,
is_dispatchable() true only for Tool, UnknownKind for forward-compat).
Locate exists at library level via store::payload_rel_path and
Store::find_anywhere, reaching kinds the CLI has no export verb for.
(b) the crate can say verified at all: LANDED. reverify::verify_installed()
re-verifies an installed layer against the trust root, and
verify::PinnedKeyVerifier is a public constructible ManifestVerifier. So a
reader can make a real verified claim instead of the weaker sentence we
promised on varve#130.
(c) crate/format version self-report: NOT landed. No pub fn version, no
FORMAT_VERSION.
(d) query by type/field: NOT landed beyond discover::find_pin.

AND THE CATALOGUE-READER PREMISE IS STILL NOT MET — checked, not assumed. No layer
carries a hardware-catalogue payload. The pinned layer's only held payloads are
rivet-sdlc/0.34.0 and spar-aadl/0.40.0, single .crate files we consume neither of.
Building the reader now would be building against nothing — the same stale-premise
error as AFD-107, caught this time before writing code rather than after.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

avrabe and others added 2 commits September 7, 2026 14:42
…ile would orphan our pin, and the diff looks like a no-op (AFD-112)

varve v0.32.1 is NOT the consumer-API release we asked for on varve#130. Its own
notes: "There is no code change from v0.32.0 — no behaviour, no CLI, no format."
It exists to publish a rotated rolling trust root, 4e771dc6... -> 7d3b892e...

Our correct action is to do nothing, and that is varve's own instruction. Layers
2026.08.0..2026.09.1 are signed by the OLD root; 2026.09.2 will be the first signed
by the new one. We pin 2026.08.4 and carry the OLD root — the correct pairing.
Verified rather than assumed: `varve verify` reports "layer 2026.08.4 ... verified:
signature OK, 11 tool(s) match their signed digests". It exits 1 only on PATH
shadowing, which is the advisory class AFD-111 just separated out — the two
checkers agree.

Also ran varve's own falsification test from the release notes: the published
rolling.pub and varve-realms.toml name the same root. AGREE.

THE HAZARD. The published varve-realms.toml is byte-identical to ours except the
trust-root line — measured, the diff is empty once that line is masked. So
"vendor the new realms file" reads in review as a one-line no-op and produces:

  error: manifest signature verification failed: ... No valid signatures

This repo runs an autonomous 4h loop that bumps pins on evidence; it bumped rivet
and spar to the pin earlier today. A rule that lives only in a release note is a
rule that loop will not see. tools/varve/check-realm.sh makes it executable and
refuses a realm/pin pairing whose root cannot verify the pinned layer, in EITHER
direction, plus an unrecognised root. --self-test runs five rows and BOTH failure
modes are observed failing, including the trap itself. The layer comparison is
numeric, not lexical: 2026.09.10 must sort ABOVE the 2026.09.2 boundary, and a
string compare puts it below.

varve-core 0.32.1 against our four asks — two landed:
  (a) held-payload kind + locate: LANDED. kind::PayloadKind (8 variants,
      is_dispatchable() true only for Tool, UnknownKind for forward-compat).
      Locate exists at library level via store::payload_rel_path and
      Store::find_anywhere, reaching kinds the CLI has no export verb for.
  (b) the crate can say `verified` at all: LANDED. reverify::verify_installed()
      re-verifies an installed layer against the trust root, and
      verify::PinnedKeyVerifier is a public constructible ManifestVerifier. So a
      reader can make a real verified claim instead of the weaker sentence we
      promised on varve#130.
  (c) crate/format version self-report: NOT landed. No pub fn version, no
      FORMAT_VERSION.
  (d) query by type/field: NOT landed beyond discover::find_pin.

AND THE CATALOGUE-READER PREMISE IS STILL NOT MET — checked, not assumed. No layer
carries a hardware-catalogue payload. The pinned layer's only held payloads are
rivet-sdlc/0.34.0 and spar-aadl/0.40.0, single .crate files we consume neither of.
Building the reader now would be building against nothing — the same stale-premise
error as AFD-107, caught this time before writing code rather than after.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…out to a subdirectory

The step ran at the workspace root and exited 127 with 'No such file or
directory', which reads like a missing script rather than a wrong cwd. CI
caught it, which is what the gate is for.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avrabe
avrabe merged commit 6c15153 into main Sep 7, 2026
9 checks passed
@avrabe
avrabe deleted the guard/varve-realm-rotation branch September 7, 2026 12:55
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.

1 participant