Skip to content

Plan v0.29.0: multi-realm distribution, and a corrected ingestion premise - #100

Merged
avrabe merged 2 commits into
mainfrom
plan/v0.29.0
Aug 21, 2026
Merged

Plan v0.29.0: multi-realm distribution, and a corrected ingestion premise#100
avrabe merged 2 commits into
mainfrom
plan/v0.29.0

Conversation

@avrabe

@avrabe avrabe commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Three requirements tagged release: v0.29.0, and a correction to research I got wrong.

The correction

I reported that bytecodealliance publishes no verifiable provenance. That was wrong, and the maintainer caught it. I had listed release assets and filtered for cosign/sums filenames — GitHub build attestations are not release assets, so the way I looked could not have found them.

Measured properly, with negative controls:

repo provenance
bytecodealliance/wasm-tools verifies — bogus file rejected (exit 1)
bytecodealliance/wit-bindgen none (exit 1)
bytecodealliance/cargo-component no release assets at all

Both of my earlier recommendations — "fork everything, upstream is unverifiable" and "ingest upstream and disclaim it" — rested on a premise I hadn't checked properly.

The finding is better than either option

Build provenance is stronger than a sums file. A sums file says these bytes hash to this. An attestation binds the artifact to a workflow, a repository and a source commit — observed: publish.yml@refs/heads/main, commit 3ef3cefc….

That is exactly what [tool.source] has always wanted to record and couldn't, and it's the field we spent v0.28.0 adding disclaimers to because varve never verifies it.

What lands

  • REQ-INGEST-001 — provenance as a first-class second ingestion mode; record which mechanism vouched for each tool inside the signed payload; refuse a tool with neither by default, so "could not verify" is never the silent path. The pulseengine forks keep their place as the answer for tools upstream doesn't cover (wit-bindgen), not as a blanket workaround.
  • REQ-LAYERREPO-001 — assembly moves out of varve, one repo per realm, with the assembler consumed from varve as a released artifact. A copy per realm is a copy that drifts — the same defect as a gate testing a re-implementation.
  • REQ-REALM2-001 — a real bytecodealliance realm, composed across two roots, exercised by the system gate rather than a fixture.

Why REQ-REALM2-001 is the one that matters

Composition has been fixture-only since v0.23.0, and every defect it has had was found by review or by a persona, never by use: a diamond refused as a cycle, cross-realm verification dead under test, an export following only the root, an install check that was direct-only.

Two real realms will settle #91 by collision rather than by argument — two realms shipping wasm-tools is not hypothetical.

Staging

Two releases, not one. v0.29.0 is distribution with an outward-facing result. v0.30.0 is inward verification: the wasm-subset MC/DC investigation (#97), check-status (DD-023 clause 6), the three uncovered adapters (#99), and the error sweep (#60). REQ-ADVISORY-002 and REQ-SYSTEST-002 move to v0.30.0 so their open clauses sit in the release that closes them rather than trailing a shipped one.

rivet validate PASS.

avrabe and others added 2 commits August 21, 2026 12:58
…mise

Research finding that changes the plan, and a correction to my own
earlier claim.

I reported that bytecodealliance publishes no verifiable provenance. That
was WRONG, and the maintainer said so. I had listed release ASSETS and
filtered for cosign/sums filenames — GitHub build attestations are not
release assets, so the way I looked could not have found them. Measured
properly, with negative controls:

  bytecodealliance/wasm-tools     attestation verifies; bogus file rejected
  bytecodealliance/wit-bindgen    no attestation (exit 1)
  bytecodealliance/cargo-component  no release assets at all

So upstream verification EXISTS and is not uniform. Both of my earlier
answers — "fork everything because upstream is unverifiable" and "ingest
upstream and disclaim" — were built on a premise I had not checked
properly.

The real finding is better than either: build provenance is STRONGER than
a sums file. A sums file says these bytes hash to this. An attestation
binds the artifact to a workflow, a repository and a source commit
(observed `publish.yml@refs/heads/main`, commit 3ef3cefc) — which is
exactly what `[tool.source]` has always wanted to record and could not,
and which we spent v0.28.0 disclaiming because the sha256 there is never
verified.

REQ-INGEST-001 makes provenance a first-class second ingestion mode,
records WHICH mechanism vouched for each tool inside the signed payload,
and refuses a tool with neither by default — so "we could not verify
this" is never the silent path. The forks keep their place, but as the
answer for tools upstream does not cover (wit-bindgen), not as a blanket
workaround.

REQ-LAYERREPO-001 moves assembly out of varve, one repo per realm, with
the assembler consumed FROM varve as a released artifact rather than
copied — a copy per realm is a copy that drifts, the same defect as a
gate testing a re-implementation.

REQ-REALM2-001 is the one that matters. Composition has been exercised
only by fixtures since v0.23.0, and every defect it has had was found by
review or by a persona, never by use: a diamond refused as a cycle,
cross-realm verification dead under test, an export following only the
root, an install check that was direct-only. Two real realms will settle
varve#91 by collision rather than by argument — two realms shipping
`wasm-tools` is not hypothetical.

Staged as two releases rather than one. v0.29.0 is distribution and has
an outward-facing result; v0.30.0 is inward verification work (the wasm
subset + MC/DC investigation, check-status, the three uncovered
adapters, the error sweep). REQ-ADVISORY-002 and REQ-SYSTEST-002 move to
v0.30.0 with it, so their open clauses sit in the release that closes
them instead of trailing a shipped one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu
The layer went stale in days, not months. Measured 2026-08-21, shortly
after 2026.08.3 was published: rivet v0.33.1 -> v0.34.0, spar v0.36.0 ->
v0.40.0 (four minors), synth v0.55.0 -> v0.58.0, witness v0.39.0 ->
v0.43.0, ordeal v0.18.0 -> v0.19.0. A consumer on `rolling` is not
getting a rolling toolchain; they are getting whatever was current the
last time a human remembered. That is the requirement input.

So the manual 2026.08.4 refresh is NOT being cut. Nothing is broken —
the layer is behind, not wrong — 2026.08.3 already proved the VSIX and
per-platform path end to end, and a hand-cut layer now is work that gets
redone in the layers repo within the same release. The staleness is
evidence for automating, not for one more manual dispatch.

DD-024 is the part worth arguing about. Automating the whole pipeline —
scan, assemble, sign, publish, hourly — is the obvious reading of "make
it automatic", and it is wrong for varve specifically:

`channel = "rolling"` is NOT a trust boundary. It is an annotation inside
a layer signed by the SAME realm root as `qualified`. The realm is the
boundary. So automating the rolling channel means the root key signs
unattended, dozens of times a week — one release after we published
`docs root-ceremony`, which says to use that key as rarely as possible,
air-gapped, two-person rule, every use a ceremony entry. A key used by a
cron job is a CI credential whatever the ceremony document calls it.

And it is unrecoverable: varve has no revocation and no rotation, both
stated in threat-model and root-ceremony. A layer published in error
cannot be withdrawn — the only remedy is a yank, needing the same key —
and an upstream compromise would reach every rolling consumer within the
hour with no window for anyone to notice.

So: automate the TOIL, not the JUDGEMENT. The scanner notices, diffs,
assembles and runs the full assembly gate, then opens a PR. A person
merges. The merge signs. Every signature stays something someone chose to
make.

Two clauses come from watching how automation actually fails: an
unverifiable new release blocks THAT TOOL, not the whole proposal (one
unattested upstream must not freeze the other seven), and the job is
silent when nothing moved (a scheduled task that reports hourly is one
people filter out of their inbox).

Recorded as rejected-for-now, and the right shape if unattended
publishing is ever wanted: a SEPARATE realm with its own root for
machine-signed layers. That is what realms are for, and it lets consumers
opt into lower assurance knowingly rather than by not reading.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu
@avrabe
avrabe merged commit 8794b0b into main Aug 21, 2026
18 checks passed
@avrabe
avrabe deleted the plan/v0.29.0 branch August 21, 2026 12:04
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