Lock in custom-serializer-on-send guarantee (CritterWatch#261 H1 analysis)#3012
Merged
Conversation
…he send path Verification for CritterWatch#261 (H1): a custom IMessageSerializer attached at the rule/endpoint level via .To(uri).DefaultSerializer(custom) must actually produce the outgoing envelope (and therefore the wire bytes), not be silently replaced by the global System.Text.Json default. The existing serialization_configuration tests only assert the serializer is *attached* to the endpoint (endpoint.DefaultSerializer.ShouldBeSameAs(...)). This adds a send-path assertion: route a message via runtime.RoutingFor(...).RouteForSend(...) and confirm the outgoing envelope for the overridden endpoint carries the custom serializer + content type and that envelope.Serializer.Write(envelope) is what produces the payload — while a sibling endpoint with no override stays on the global STJ default. This locks in the framework guarantee analyzed for the release: the rule-level DefaultSerializer survives Endpoint.Compile()'s `??=` global fallback and is selected by MessageRoute on the send path. No production code change — the mechanism already works. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 3, 2026
Merged
Merged
This was referenced Jun 15, 2026
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.
Pre-release verification for the H1 hypothesis in CritterWatch#261: "Wolverine SQS endpoint not honoring the rule-level
DefaultSerializer."Conclusion: the framework honors custom serializers
Traced the send path end to end — the mechanism is sound, no production bug:
x.To(uri).DefaultSerializer(custom)→SubscriberConfigurationdelayse.DefaultSerializer = custom, whose setterRegisterSerializer(custom)s it (keyed bycustom.ContentType) and stores it on the Endpoint.Endpoint.Compile()usesDefaultSerializer ??= runtime.Options.DefaultSerializer— so an endpoint-level custom serializer is not overwritten by the global STJ default.MessageRoutecapturesSerializer = endpoint.DefaultSerializer, andCreateForSendingsetsenvelope.Serializer = Serializer+envelope.ContentType = Serializer.ContentType. The sending agent then writes the wire bytes viaenvelope.Serializer.Write(envelope).So a custom
IMessageSerializer(e.g. a Brotli-compressing one) is the serializer that produces the wire payload — provided the rule lands on the endpoint the message routes to.On the URI-mismatch sub-hypothesis (H2)
AmazonSqsTransport.findEndpointByUrifalls back toQueues[uri.OriginalString.Split("//")[1].TrimEnd('/')], sosqs://critterwatchandsqs://critterwatch/resolve to the same queue endpoint — the trailing-slash difference seen in the logs does not split the serializer onto a phantom endpoint at the framework level.The #261 symptom is therefore most likely on the CritterWatch-extension / host-config side (H3 host-level
DefaultSerializeroverride afterAddCritterWatchMonitoring, H4Wolverine.CritterWatch 0.7.0version regression, or H5 strip not running) — the diagnostic logging in that comment will localize it. Not a Wolverine framework defect.What this PR adds
The existing
serialization_configurationtests only assert the serializer is attached to the endpoint. This adds a send-path regression test that routes a message throughruntime.RoutingFor(...).RouteForSend(...)and asserts:envelope.Serializer.Write(envelope)is what produces the payload,SystemTextJsonSerializer.No production code change — this locks in the guarantee so a future regression (e.g. a
Compile()ordering change that lets the global default clobber an endpoint override) is caught.serialization_configurationsuite green (8/8).🤖 Generated with Claude Code