Skip to content

The stream header width belongs to the record version - #1746

Merged
fog-workflows[bot] merged 1 commit into
working-1.6from
fix/multicast-header-record-version
Sep 9, 2026
Merged

fog-workflows[bot] merged 1 commit into
working-1.6from
fix/multicast-header-record-version

Conversation

@mastacontrola

Copy link
Copy Markdown
Member

Server half of FOGProject/fos#179. Client half is FOGProject/fos#180.

The problem

The multicast identity header is 128 bytes. That number lived in STREAM_HEADER_FORMAT and STREAM_HEADER_BYTES here, and again as a dd bs=1 count=128 in FOS. Nothing on the wire carries the width, so the two sides cannot negotiate it, and no check compared them. ADR-0018 recorded it as a known gap.

The failure mode was already safe — a mismatched width feeds the decompressor the wrong bytes and the deploy fails — but it fails a long way from its cause.

The fix

Make the width a property of the record version. A FOGMC1 record is 128 bytes, and nothing else.

tests/multicast-streams-are-self-identifying.test.php now pins the pair rather than the number: the format's magic and the byte width are asserted together, with a message that says what to do. FOS pins the same pair on its side. So a width change that keeps the magic fails a check on whichever side changed it.

Changing the width therefore means bumping the magic, and an old client then meets FOGMC2, fails its tag test, and names the version it cannot read.

This is deliberately per-repo enforcement. Neither repo has to check the other out and neither CI depends on the other. The FOS harness compares the two directly when both trees sit on one machine, and prints a line when it could not.

Verification

Mutation-verified — each turns the test red on the named check:

  • STREAM_HEADER_FORMAT widened to %-152s and STREAM_HEADER_BYTES to 160, magic unchanged → "a FOGMC1 record is 128 bytes"
  • magic bumped to FOGMC2, width unchanged → "the record magic is FOGMC1"

Full suite 349 passed / 0 failed. Both phpstan passes clean. us-spelling clean.

Downstream

None. No route, no schema, no class list.

🤖 Generated with Claude Code

https://claude.ai/code/session_01A767exFmz6sQUcuZofqE1V

The multicast identity header is 128 bytes, and that number is also
written into FOS as a dd count. Nothing on the wire carries it, so the two
sides cannot negotiate it and nothing compared them.

Make the width a property of the record version instead: a FOGMC1 record is
128 bytes, on this side and on FOS's. The test pins the PAIR rather than the
number, so a width change that keeps the magic fails here. Changing the
width therefore means bumping the magic, and an old client meets FOGMC2,
fails its tag test and names the version it cannot read -- instead of
taking the wrong number of bytes off a record it cannot frame and dying
somewhere inside the decompressor.

That is the whole enforcement, and it is deliberately per-repo: neither
side has to check the other out, and neither CI depends on the other. The
FOS harness compares the two directly when both trees are on one machine,
and says when it could not.

Verified by mutation: widening the constants while keeping FOGMC1, and
bumping the magic while keeping the width, each turn the test red on the
named check.

The paired client change is FOGProject/fos#180, which closes fos#179.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A767exFmz6sQUcuZofqE1V
@fog-workflows
fog-workflows Bot enabled auto-merge September 9, 2026 16:08
@fog-workflows
fog-workflows Bot added this pull request to the merge queue Sep 9, 2026
Merged via the queue into working-1.6 with commit 47ea627 Sep 9, 2026
11 checks passed
@fog-workflows
fog-workflows Bot deleted the fix/multicast-header-record-version branch September 9, 2026 16:16
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