Cross-provider audit M4/M5/M6 (Anthropic Messages builder):
- Non-base64 data: URIs rode as ImageSource::Url — url sources are
http(s) only → 400; and the two image paths parsed data URIs
differently (user path split on first comma, tool-result path on
';base64,').
- No media-type whitelist: image/svg+xml and param-carrying headers
('image/webp;name=x') reached the wire → 400.
- Empty user content shipped empty arrays/text blocks → 400.
One shared parse_base64_image_data_uri (raster whitelist: jpeg/png/gif/
webp) now serves both paths; rejected images degrade to a SHORT
'[unsupported image]' placeholder (never the multi-megabyte payload);
empty user turns get '[empty message]' (mirrors the assistant guard).
Part 6 of the cross-provider replay audit.
Verified: sampling-types 292 + downstream green, clippy clean.