Skip to content

fix(oci): falcon-rate shipped as a core module — export cabi_realloc, fail loud, assert the header - #323

Merged
avrabe merged 1 commit into
mainfrom
fix/rate-component-encoding
Jul 29, 2026
Merged

fix(oci): falcon-rate shipped as a core module — export cabi_realloc, fail loud, assert the header#323
avrabe merged 1 commit into
mainfrom
fix/rate-component-encoding

Conversation

@avrabe

@avrabe avrabe commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

jess caught a real bug in v1.129.0. falcon-rate:1.129.0 was published as a raw core module (0061736d01000000), not a component (0061736d0d000100) — meld fuse rejects it outright, so their consumption path stopped at step one. I pulled the published blob and confirmed it independently.

Three compounding bugs, mine at the root:

1. Root cause — my no_std conversion dropped cabi_realloc

wit-bindgen-rt provides cabi_realloc only #[cfg(not(target_env = "p2"))] — on wasm32-wasip2 it expects std to supply the symbol. no_std has no std, so wasm-component-ld failed:

error: failed to encode component
Caused by: module does not export a function named `cabi_realloc`

Why I missed it: my local verification used wasip1, where wit-bindgen-rt does provide it — so it componentized fine. The release build targets wasip2. Now exported explicitly from the no_std path, backed by the same single-threaded allocator.

2. Silent failure — the build swallowed the error

build-components.sh ended that invocation in || true: the error was printed and ignored, and the script fell through to a stale pre-componentization artifact. Build failures now stop the bundle.

3. No validation — nothing checked the payload

The OCI config.mediaType says "component" regardless of the actual bytes, so metadata cannot catch this (jess's point). Now asserts the 8-byte header on every component before it enters the bundle.

The assert is verified against the real artifacts:

REJECTED  the published falcon-rate:1.129.0   (0061736d01000000)  ← the bug
accepted  falcon-mixer (good component)       (0061736d0d000100)
accepted  the fixed rate build                (0061736d0d000100)

Verified after the fix

  • wasip2 build produces a component: 4581 bytes (was a 3749-byte core module)
  • still zero wasi:* imports
  • through-wasm closed-loop proof unchanged: converges 0.193 s, |err| 0.0059 rad/s

Correcting my own claim

I said "15× smaller" — that compared a core module against components. Componentized it's ~4.6 KB vs 53–60 KB: still a large win (~12×), but not the number I quoted. jess caught that too.

Refs: jess#167, #314 (the no_std conversion that introduced this).

🤖 Generated with Claude Code

…+ fail loud + assert the header

jess pulled falcon-rate:1.129.0 and found it is a raw CORE MODULE
(0061736d01000000), not a component (0061736d0d000100) — `meld fuse` rejects it
outright, so the consumption path stopped at step one. Confirmed independently
by pulling the published blob. Three compounding bugs, mine at the root:

1. ROOT CAUSE — my no_std conversion (#314) dropped the `cabi_realloc` export.
   wit-bindgen-rt provides it only `#[cfg(not(target_env = "p2"))]` — on
   wasm32-wasip2 it expects std to supply the symbol. no_std has no std, so
   `wasm-component-ld` failed: "module does not export a function named
   `cabi_realloc`". (The local wasip1 build DID componentize, which is why this
   passed my earlier check — the release target is wasip2.) Now exported from
   the no_std path, backed by the same single-threaded allocator.

2. SILENT FAILURE — build-components.sh ended the build in `|| true`, so that
   error was printed and ignored; the script fell through to a stale
   pre-componentization artifact and bundled it. Build failures now stop the
   bundle.

3. NO VALIDATION — nothing checked the payload. The OCI config mediaType says
   "component" regardless of the bytes, so metadata cannot catch this. Now
   asserts the 8-byte header on every component before it enters the bundle;
   verified the assert REJECTS the published 1.129.0 artifact and ACCEPTS both
   good components.

Verified after the fix: wasip2 build produces a component (4581 bytes, was a
3749-byte core module), still ZERO wasi imports, and the through-wasm
closed-loop proof is unchanged — converges 0.193 s, |err| 0.0059 rad/s.

Also corrects the record: the "15x smaller" claim compared a core module against
components. Componentized it is ~4.6 KB vs 53-60 KB — still a large win
(~12x), just not the number I quoted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvusAXYbHLyv3uTzfBcMbG
@avrabe
avrabe enabled auto-merge (squash) July 29, 2026 16:35
@avrabe
avrabe merged commit 89b325a into main Jul 29, 2026
13 checks passed
@avrabe
avrabe deleted the fix/rate-component-encoding branch July 29, 2026 16:45
avrabe added a commit that referenced this pull request Jul 30, 2026
#325)

FV-FALCON-OCI-001 claimed distribution was "validated end-to-end" on v1.127/
v1.128. That evidence was NOT sufficient, and jess proved it in the field:
falcon-rate:1.129.0 shipped as a raw core module. My check confirmed the OCI
config mediaType — which reads "component" regardless of the payload — so it
verified the WRAPPER, not the BYTES.

Record it honestly rather than quietly re-verifying: the gap, its root cause
(no_std dropped `cabi_realloc`, wit-bindgen-rt only provides it when std is
linked; the build failure was then swallowed by `|| true`), and the four
strengthenings that close it (#323, #324) — cabi_realloc exported, build
failures abort, an 8-byte HEADER assert on every component (verified to REJECT
the published 1.129.0 artifact), and by-name artifact selection.

This is the release-planning loop working as intended: a field regression
re-opens the requirement's verification rather than being patched silently.

Also defers SWREQ-FALCON-MATHF32-P06 (Cody-Waite argument reduction) from
v1.130 to v1.131 — an explicit, logged scope move, not a silent slip. It is the
multi-week proof of the four and is not ready; v1.130 is a fix release that
republishes falcon-rate as a real component.

rivet validate: PASS.


Claude-Session: https://claude.ai/code/session_01HvusAXYbHLyv3uTzfBcMbG

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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