Repository navigation
transport: the framer's head piece states its declared body length (declared_len), for 1.5.5's pre-body download cap - #1032
Open
MattJackson wants to merge 2 commits into
Open
MattJackson wants to merge 2 commits into
MattJackson wants to merge 2 commits into
Conversation
…eclared_len) ARCHITECT ruling (1.5.5 parity, plugins.fetch's pre-body download cap): 1.5.5 refused an honest over-cap declared body length before reading a body byte. In 1.6.0 the download runs on the host connector, which sees only the table's pieces: the head field block never carries the declared length (abi::transport::fields, its own rule, unchanged), and conn::Piece had no field for it. The framer's HEAD piece gains a neutral declared_len, "the body length the message's head declared on the wire, if it stated one": * abi::transport::FramePiece appends `declared_len: u64` @40 (size 40 -> 48), present under the new flag PIECE_HAS_DECLARED_LEN = 128, the encoding `code` and `retry_after_secs` already use. Pre-tag v1 layout edit, transport ABI version unchanged; abi-layout.golden, layout_golden.rs and include/busbar_plugin.h updated together. check_framer admits the bit, on a field block only (framer.piece.declared_len_not_fields otherwise). * sdk_hyper::Piece gains `declared_len: Option<u64>`; fill sets the flag and value. * conn::Piece gains `declared_len: Option<u64>`, lowered as WirePiece.declared_len @72 (72 -> 80) under WirePiece PIECE_HAS_DECLARED_LEN = 4, so a plugin reading the table sees it too. * busbar-core-connector carries it from the framer's piece (Got) into the table's piece untouched; every other piece literal names it absent. RED: connector_tests::a_framers_declared_body_length_reaches_the_tables_head_piece (a TestDoor framer over a real far end states 2^40 on its head field block; the table's Fields piece carries Some(2^40); a framer stating none yields None). Also conn_lowering_tests (it crosses the WirePiece lowering), sdk_hyper fill_states_a_heads_declared_length_where_it_declared_one, and transport_check_tests a_declared_length_rides_a_field_block_only.
MattJackson
added a commit
that referenced
this pull request
Oct 14, 2026
… base, so it compiles against #787's FramePiece (fault in the old _reserved byte) #787's FramePiece states the framer's fault reading in the byte that was `_reserved` (the breaker plane-fault work); the datagram rig landed on predev against the old layout and named `_reserved: 0`, which #787's tree does not have (E0560). FramePiece has no constructor or Default, so the literal names the four fields the rig sets and takes the rest from an all-zero piece (code, status class, FAULT_NONE, no retry), as the contract and loader tests' `z()` pieces do. An appended field (#1032's declared_len) no longer breaks it. Every other FramePiece and WirePiece literal in the tree was checked: the rest are built from `z()` or already name the current fields.
… appended declared_len at zero compile/clippy/test were red on busbar-transport-ws (pinned f8ba71d), whose door builds a FramePiece literal field by field and so missed the appended declared_len. The pin moves to 140691cf2e, f8ba71d plus one change: the literal ends in `..std::mem::zeroed()` (FramePiece is plain repr(C) integers; zero is every field's absent value), so this and any later append compile. The framer states no declared length. ws's own dev carries the off-line door changes (#1012/#1019) and repins with them.
This branch has not been deployed
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.
Why (ARCHITECT ruling, 1.5.5 parity)
1.5.5's
plugins.fetchdownloader refused an honest over-cap declared length before reading any body byte: "GET {url}: declared Content-Length {len} exceeds the {cap}-byte plugins.fetch download cap" (v1.5.5 source; the same text sits in predev'scrates/busbar-kernel/src/preflight.rstoday). In 1.6.0 the download moves onto the host connector (#805,crates/busbar-core-connector/src/fetch.rs), and the connector cannot see the declared length:crates/busbar-contract/src/abi/transport/fields.rs:14-16says the framer drops it because the pieces carry the body the framer already unframed;busbar_contract::conn::Piecehad no length field.fields.rs:14-16 stays true. The declared length is not a field and never enters the block. It travels as its own typed value on the head piece, the way
codeandretry_after_secsalready do.The change
A neutral
declared_len: "the body length the message's head declared on the wire, if it stated one". It is a statement, not a count of delivered bytes.abi::transport::FramePieceappendsdeclared_len: u64at offset 40 (size 40 -> 48). It is present under the new flagPIECE_HAS_DECLARED_LEN = 128, the HAS-flag encodingcode/retry_after_secsuse (absent = flag clear, value 0). This is a pre-release layout change and the transport ABI version is unchanged (ARCHITECT).tests/golden/abi-layout.golden,tests/layout_golden.rsandinclude/busbar_plugin.hare updated together (#define, struct field, size and offset asserts, in the generator's format).check_frameradmits the bit only on a field block; anywhere else it isframer.piece.declared_len_not_fields.sdk_hyper::Piecegainsdeclared_len: Option<u64>, andfillsets the flag and value, so a Rust framer states it.conn::Piecegainsdeclared_len: Option<u64>. Its mechanical loweringabi::host::conn::WirePieceappendsdeclared_lenat offset 72 (72 -> 80) underWirePieceflagPIECE_HAS_DECLARED_LEN = 4, so a plugin reading the table sees it too.Got) into the table's piece untouched, with no interpretation. Every other piece literal in the workspace names it absent.RED
busbar-core-connectorconnector_tests::a_framers_declared_body_length_reaches_the_tables_head_piece: aTestDoorframer (newfields/declared_lenknobs), driven over a real loopback far end through the connector's table, states 2^40 on its head field block. The table'sFieldspiece carriesdeclared_len == Some(2^40). A framer stating none yieldsNone.conn_lowering_tests::every_operation_crosses_the_lowering: it crosses theWirePiecelowering both ways (Some/None).sdk_hyperfill_states_a_heads_declared_length_where_it_declared_one.transport_check_tests::a_declared_length_rides_a_field_block_only.layout_golden,abi-header).No skip, no
#[ignore].Next
#805's
fetch.rsconsumesPiece::declared_lento refuse an over-cap download before the first body byte. No oracle cell covers the over-cap refusal; the url cell isegress.fetch|plugins|url.Why every transport plugin repins past this (row 81)
FramePiecegrows 40 -> 48 bytes andWirePiece72 -> 80. Both are array-element / out structs, so the stride changes. No check crosses the host/plugin boundary for them:FramePiecehas nosizefield and each side only asserts its own build (const _: () = assert!(size_of::<FramePiece>() == ..));WirePiece.sizeis written by the host and validated by no plugin; the loader (plugin-loaderdispatch/load.rstable::<K>) checks only the ops table'sslots/size. A transport framer built at an older pin and dropped in would therefore mis-stride the piece arrays while passing the unchanged ABI version check. Pre-tag, appends are guarded by the layout golden without a version bump (BUSBAR-1.6.0.md l.1211; R9), so the guard is row 81: every roster transport plugin (tcp, stdio, webrtc; http/ws/grpc with their door changes) is repinned past this commit.