Skip to content

fix(binding-kafka): use each producer stream's own authorization for cache encode - #2425

Open
jfallows wants to merge 2 commits into
developfrom
claude/zilla-plus-pii-status-nfzbgr
Open

fix(binding-kafka): use each producer stream's own authorization for cache encode#2425
jfallows wants to merge 2 commits into
developfrom
claude/zilla-plus-pii-status-nfzbgr

Conversation

@jfallows

@jfallows jfallows commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Description

KafkaCacheClientProduceFan captured the authorization of whichever producer stream first created the per-topic-partition fan, then reused that single value — along with a shared transformKey/transformValue encoder pair — for every subsequent producer writing to the same partition. KafkaCacheClientProduceStream already tracked its own authorization, but the encode call sites (onClientInitialData ×2, onClientInitialFlush) never used it.

This moves transformKey/transformValue from the fan onto the stream and threads stream.authorization through writeProduceEntryStart/writeProduceEntryContinue, so each message is encoded using the authorization of the producer stream that actually produced it, not the first producer to touch the partition.

To make this observable in an oss-only test, the engine's generic TestModel gains an opt-in transformAuthorizations: [N, M] config list: an ordered list of the authorization values expected to reach the model, in message-arrival order. Each completed value consumes the next entry from this list (tracked on the shared ModelHandler, not the pipeline instance that observed it — a shared/hoisted pipeline handling multiple messages must still be checked against each message's own expected value) and is rejected outright on mismatch, surfacing as an ordinary REJECTED → stream RESET, the same signal already used by the existing message.value.rejected/message.values.rejected scenarios. A new k3po scenario (message.values.authorization.distinct) drives two producers with distinct authorization values through a live engine and asserts each message reaches the model with its own value, not the other's.

Verified test-first: the new CacheProduceIT test fails with a clean, fast rejection (not a hang/timeout) against the pre-fix code, and passes against the fix. Full ProduceIT and CacheProduceIT suites, runtime/engine and config/engine.conf unit tests, and checkstyle/license checks all pass with no regressions.

The new scenario's peer-to-peer counterpart is intentionally omitted, with the reasoning documented inline in ProduceIT.java: a pre-existing k3po-harness limitation (unrelated to this change, and already present for the never-covered message.values.parallel scenario) prevents a third notify/await-gated connect from being peer-verified in this harness.

Fixes # (issue)


Generated by Claude Code

claude added 2 commits August 24, 2026 22:56
…cache encode

KafkaCacheClientProduceFan captured the authorization of whichever
producer stream first created the per-topic-partition fan, then reused
that single value (and a shared transformKey/transformValue encoder
pair) for every subsequent producer writing to the same partition.
KafkaCacheClientProduceStream already tracked its own authorization but
it went unused by the encode call sites. Move transformKey/transformValue
onto the stream and thread stream.authorization through
writeProduceEntryStart/Continue so each message is encoded using the
authorization of the stream that actually produced it.

Extend the engine's generic TestModel with an opt-in
transform: { authorization: true } flag so tests can observe which
authorization value reached the model encoder via stamped output
bytes, and add a k3po scenario (two sequential producers, distinct
authorization) plus engine-driven and peer-to-peer IT coverage.
…eject checks

TestModel previously exposed a transform: { authorization: true } flag that
stamped the authorization value into output bytes so a test could recover it
after the fact. Replace it with transform.authorizations: [N, M] -- an
ordered list of expected authorization values -- and reject the value
outright when a mismatch is observed. The check is applied per completed
value, keyed off a shared counter on the handler rather than the position of
the pipeline instance that observed it, since a shared/hoisted pipeline
handling multiple messages must still be checked against each message's own
expected value.

Fix the corresponding k3po scenario's message ordering to match the actual,
now-verified arrival order, and hoist the new schema property to a top-level
sibling of transform/fields rather than nesting it under transform, which
a two-properties-deep array-typed nested property does not validate under
the current JSON schema patch mechanism.

@jfallows jfallows left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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.

2 participants