#604 item 1: fleet_list reports charterBytes alongside charterSha256 #605
Reference in New Issue
Block a user
Delete Branch "worker/charter-bytes-13668c-6"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes item 1 of #604 (items 2 and 3 are documentation notes, left untouched).
The gap:
CharterReceiptcarries bothcharterSha256andcharterBytes, butSessionManager.rosterViewonly copied the digest into the roster map, sofleet_listnever reported the size.Change:
charterBytesis now written nested inside the existingif (charterSha256 != null)block, so it always travels with the digest. Rationale:CharterReceipt.composeonly ever produces a non-null digest together with a real byte count (or both null/0 when no charter was composed at all) — the size is a companion to the digest, not an independent field. A member with no composed charter still reportscharterSourceonly, exactly as before.Tests (
SessionManagerTest.java):rosterViewExposesTheCharterReceiptButNeverTheCharterTextto assertcharterBytesagainst the receipt's own value (not a hardcoded literal), plus the real UTF-8 length of the composed string.rosterViewOmitsCharterBytesAndDigestWhenNoCharterWasComposed— no role charter and no reply charter composed reportscharterSource="none"and neithercharterSha256norcharterBytes.rosterViewOmitsCharterFieldsEntirelyWhenTheReceiptItselfIsAbsent—session.charterReceipt() == nullstill suppresses all three keys.No existing test needed to be weakened.
Build:
mvn -o clean installfrom the worktree —Tests run: 1821, Failures: 0, Errors: 0, Skipped: 0,BUILD SUCCESS.Lead review. The change is right and the tests are good. I merged after one correction, pushed as
ad3d819.Verified by me, not taken from the report
What the tests do well
Two things worth naming, because they are the reason this did not repeat the defect that started #604's sibling ticket.
assertEquals(receipt.charterBytes(), view.get("charterBytes"))asserts against the receipt's own value rather than a typed-in literal. A hardcoded expected size passes even when the wiring reads the wrong field. Pairing it with the real UTF-8 length of the composed string covers the other direction.The two new tests use
assertFalse(view.containsKey(...)). That is what makes the no-charter case real evidence — acontainsKeyassertion cannot be satisfied by code that always writes the field, which anassertNullcould.The correction: the comment stated an invariant that is false
The added comment said:
CharterReceipt.compose()can produce exactly the pair that sentence rules out:digestOf()returnsnullfor blank text.getBytes().lengthdoes not. So a whitespace-only charter gives anulldigest beside a non-zero size.Reachable how: a blank
fleet.charters.<role>on a profile with no MCP, so no reply charter is appended andcomposedis the blank role charter alone. That needs an odd config, so it is a defect on paper rather than one anybody has hit — which is exactly why it would have survived.No behaviour change was needed. Gating on the digest already handles it, and handles it correctly: it omits both fields. Reporting a size with no digest would claim "they differ by N bytes" about an artifact we cannot fingerprint, which is the failure this whole ticket is about.
So only the stated reason was wrong. I replaced it with the real one and added the line that matters for the next reader: never widen this gate to the receipt-level null check without deciding what that case should report.
Why I did not let it stand
A comment claiming an invariant is a free test case — you can always go and check it. When it is false, it is worse than no comment, because the next person widens the gate on the strength of it and the compiler says nothing.
It also mattered here specifically. This PR exists because a digest cannot tell you how two things differ. Shipping it with a false claim about when digests and sizes travel together would have put the error inside the fix for it.
Items 2 and 3 of #604 stay open — they are the javadoc notes, and correctly out of scope for this unit.