Skip to main content

gaze_proxy/codecs/
anthropic.rs

1use std::collections::{BTreeMap, HashSet};
2use std::ops::Range;
3
4use zeroize::Zeroizing;
5
6#[cfg(test)]
7use std::cell::Cell;
8
9use gaze_types::inspection::{
10    ContentBlockIndexV1, JsonNodeOrdinalV1, JsonShapeNodeV1, JsonShapeSummaryV1,
11    JsonShapeTruncationCodeV1, JsonTypeCodeV1, ProjectionAvailabilityV1,
12    ProjectionOmissionReasonV1, SseDeltaKindV1, SseEntryOrdinalV1, SseEventKindV1,
13    SseTimelineEntryV1, SseTimelineMetaV1, MAX_JSON_SHAPE_NODES_V1,
14};
15
16use crate::codec::{
17    BodyCodec, CodecError, CodecErrorCode, CodecLimits, CodecPhase, InspectionParsedFactsV1,
18    InspectionStructuralProjectionV1, OpaqueCarrierScheme, OutputProvenance, ProvedRequestBody,
19    ProvedResponseBody, RequestTransformContext, ResponseTransformContext, WireFormat,
20};
21
22pub const ANTHROPIC_PROXY_PING_FRAME: &[u8] = b"event: ping\ndata: {\"type\":\"ping\"}\n\n";
23pub const ANTHROPIC_PROXY_ERROR_FRAME: &[u8] = b"event: error\ndata: {\"type\":\"error\",\"error\":{\"type\":\"api_error\",\"message\":\"proxy_validation_failed\"}}\n\n";
24const MAX_ANTHROPIC_REQUEST_BODY_BYTES: usize = 2 * 1024 * 1024;
25// Mirror the frozen default JSON-depth ceiling for wrapper syntax inside one string.
26const MAX_ANGLE_WRAPPER_DEPTH: usize = 128;
27
28#[cfg(test)]
29#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
30pub(crate) struct InspectionConstructionCountsV1 {
31    pub(crate) json_sources_built: usize,
32    pub(crate) sse_sources_built: usize,
33    pub(crate) sse_timelines_built: usize,
34}
35
36#[cfg(test)]
37thread_local! {
38    static INSPECTION_CONSTRUCTION_COUNTS: Cell<InspectionConstructionCountsV1> =
39        const { Cell::new(InspectionConstructionCountsV1 {
40            json_sources_built: 0,
41            sse_sources_built: 0,
42            sse_timelines_built: 0,
43        }) };
44}
45
46#[cfg(test)]
47pub(crate) fn reset_inspection_construction_counts() {
48    INSPECTION_CONSTRUCTION_COUNTS.with(|counts| {
49        counts.set(InspectionConstructionCountsV1::default());
50    });
51}
52
53#[cfg(test)]
54pub(crate) fn inspection_construction_counts() -> InspectionConstructionCountsV1 {
55    INSPECTION_CONSTRUCTION_COUNTS.with(Cell::get)
56}
57
58#[cfg(test)]
59fn record_inspection_construction(update: impl FnOnce(&mut InspectionConstructionCountsV1)) {
60    INSPECTION_CONSTRUCTION_COUNTS.with(|cell| {
61        let mut counts = cell.get();
62        update(&mut counts);
63        cell.set(counts);
64    });
65}
66
67#[derive(Clone, Copy, Debug, Default)]
68pub struct AnthropicMessagesCodec;
69
70impl BodyCodec for AnthropicMessagesCodec {
71    fn protect_request(
72        &self,
73        input: &[u8],
74        ctx: &mut RequestTransformContext<'_>,
75    ) -> Result<ProvedRequestBody, CodecError> {
76        ctx.clear_opaque_carrier();
77        ctx.replace_content_block_index(None);
78        if ctx.format() != WireFormat::Json {
79            return Err(codec_error(
80                CodecErrorCode::InvalidWireFormat,
81                CodecPhase::RequestParse,
82            ));
83        }
84        if input.len()
85            > ctx
86                .limits()
87                .max_body_bytes()
88                .min(MAX_ANTHROPIC_REQUEST_BODY_BYTES)
89        {
90            return Err(codec_error(
91                CodecErrorCode::BodyLimitExceeded,
92                CodecPhase::RequestParse,
93            ));
94        }
95        let mut document = parse_json(input, ctx.limits(), CodecPhase::RequestParse)?;
96        let mut ledger = CoverageLedger::new(document.occurrence_count);
97        transform_request_root(&mut document.root, input, ctx, &mut ledger)
98            .map_err(|code| request_codec_error(code, CodecPhase::RequestProtection, ctx))?;
99        ledger
100            .finish()
101            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
102        let expected_signed = collect_signed_slices(&document.root, input)
103            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
104        let expected_authorized = collect_authorized_wire_chunks(&document.root)
105            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
106        let (bytes, mut provenance) = write_document(&document, input)
107            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
108        if bytes.len()
109            > ctx
110                .limits()
111                .max_body_bytes()
112                .min(MAX_ANTHROPIC_REQUEST_BODY_BYTES)
113        {
114            return Err(codec_error(
115                CodecErrorCode::BodyLimitExceeded,
116                CodecPhase::RequestProof,
117            ));
118        }
119        if !ctx
120            .limits()
121            .output_within_growth_limit(input.len(), bytes.len())
122        {
123            return Err(codec_error(
124                CodecErrorCode::GrowthLimitExceeded,
125                CodecPhase::RequestProof,
126            ));
127        }
128        let mut reparsed = parse_json(&bytes, ctx.limits(), CodecPhase::RequestProof)?;
129        let mut final_ledger = CoverageLedger::new(reparsed.occurrence_count);
130        transform_request_root(&mut reparsed.root, &bytes, ctx, &mut final_ledger)
131            .map_err(|code| request_codec_error(code, CodecPhase::RequestProof, ctx))?;
132        final_ledger
133            .finish()
134            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
135        if !json_semantically_equal(&document.root, &reparsed.root) {
136            return Err(codec_error(
137                CodecErrorCode::InternalCoverageFailure,
138                CodecPhase::RequestProof,
139            ));
140        }
141        let (reproved, _) = write_document(&reparsed, &bytes)
142            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
143        if reproved != bytes {
144            return Err(codec_error(
145                CodecErrorCode::InternalCoverageFailure,
146                CodecPhase::RequestProof,
147            ));
148        }
149        prove_request_logical_domains(&reparsed.root, reparsed.occurrence_count, ctx)
150            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
151        provenance.set_occurrence_count(reparsed.occurrence_count);
152        verify_final_wire_proof(&bytes, &provenance, &expected_authorized, &expected_signed)
153            .map_err(|code| codec_error(code, CodecPhase::RequestProof))?;
154        provenance.mark_final_buffer_verified();
155        if ctx.inspection_projection_requested() && provenance.signed_opaque_ranges().is_empty() {
156            Ok(ProvedRequestBody::new_with_inspection_parsed_facts(
157                bytes,
158                WireFormat::Json,
159                provenance,
160                InspectionParsedFactsV1::AnthropicJson(JsonInspectionParsedFactsV1 {
161                    root: reparsed.root,
162                }),
163            ))
164        } else {
165            Ok(ProvedRequestBody::new(bytes, WireFormat::Json, provenance))
166        }
167    }
168
169    fn restore_response(
170        &self,
171        input: &[u8],
172        ctx: &mut ResponseTransformContext<'_>,
173    ) -> Result<ProvedResponseBody, CodecError> {
174        if input.len() > ctx.limits().max_body_bytes() {
175            return Err(codec_error(
176                CodecErrorCode::BodyLimitExceeded,
177                CodecPhase::ResponseParse,
178            ));
179        }
180        match ctx.format() {
181            WireFormat::Json => restore_json_response(input, ctx),
182            WireFormat::Sse => self.restore_sse_chunks([input], ctx),
183            WireFormat::Empty if input.is_empty() => {
184                let mut provenance = OutputProvenance::default();
185                provenance.mark_final_buffer_verified();
186                Ok(ProvedResponseBody::new(
187                    Vec::new(),
188                    WireFormat::Empty,
189                    provenance,
190                ))
191            }
192            WireFormat::Utf8Text => restore_text_response(input, ctx),
193            WireFormat::Ndjson => restore_ndjson_response(input, ctx),
194            WireFormat::Empty => Err(codec_error(
195                CodecErrorCode::InvalidWireFormat,
196                CodecPhase::ResponseParse,
197            )),
198        }
199    }
200}
201
202impl AnthropicMessagesCodec {
203    pub fn restore_sse_chunks<I, B>(
204        &self,
205        chunks: I,
206        ctx: &mut ResponseTransformContext<'_>,
207    ) -> Result<ProvedResponseBody, CodecError>
208    where
209        I: IntoIterator<Item = B>,
210        B: AsRef<[u8]>,
211    {
212        if ctx.format() != WireFormat::Sse {
213            return Err(codec_error(
214                CodecErrorCode::InvalidWireFormat,
215                CodecPhase::SseDecode,
216            ));
217        }
218        let mut decoder = SseDecoder::new(ctx.limits());
219        for chunk in chunks {
220            decoder.push(chunk.as_ref())?;
221        }
222        let input_len = decoder.input_len();
223        let frames = decoder.finish()?;
224        let proved = restore_sse_frames(frames, ctx)?;
225        if !ctx
226            .limits()
227            .output_within_growth_limit(input_len, proved.bytes().len())
228        {
229            return Err(codec_error(
230                CodecErrorCode::GrowthLimitExceeded,
231                CodecPhase::SseReplay,
232            ));
233        }
234        Ok(proved)
235    }
236}
237
238fn codec_error(code: CodecErrorCode, phase: CodecPhase) -> CodecError {
239    CodecError::new(code, phase)
240}
241
242fn request_codec_error(
243    code: CodecErrorCode,
244    phase: CodecPhase,
245    ctx: &RequestTransformContext<'_>,
246) -> CodecError {
247    codec_error(code, phase).with_opaque_carrier(
248        (code == CodecErrorCode::OpaqueMediaUninspected)
249            .then(|| ctx.opaque_carrier())
250            .flatten(),
251    )
252}
253
254fn restore_json_response(
255    input: &[u8],
256    ctx: &mut ResponseTransformContext<'_>,
257) -> Result<ProvedResponseBody, CodecError> {
258    let mut document = parse_json(input, ctx.limits(), CodecPhase::ResponseParse)?;
259    let mut ledger = CoverageLedger::new(document.occurrence_count);
260    transform_response_root(&mut document.root, input, ctx, &mut ledger)
261        .map_err(|code| codec_error(code, CodecPhase::ResponseRestore))?;
262    ledger
263        .finish()
264        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
265    validate_adjacent_response_text(&document.root, ctx)
266        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
267    let expected_signed = collect_signed_slices(&document.root, input)
268        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
269    let expected_authorized = collect_authorized_wire_chunks(&document.root)
270        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
271    let (bytes, mut provenance) = write_document(&document, input)
272        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
273    if !ctx
274        .limits()
275        .output_within_growth_limit(input.len(), bytes.len())
276    {
277        return Err(codec_error(
278            CodecErrorCode::GrowthLimitExceeded,
279            CodecPhase::ResponseProof,
280        ));
281    }
282    let reparsed = parse_json(&bytes, ctx.limits(), CodecPhase::ResponseProof)?;
283    let mut final_ledger = CoverageLedger::new(reparsed.occurrence_count);
284    account_subtree(&reparsed.root, &mut final_ledger)
285        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
286    final_ledger
287        .finish()
288        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
289    if !json_semantically_equal(&document.root, &reparsed.root) {
290        return Err(codec_error(
291            CodecErrorCode::InternalCoverageFailure,
292            CodecPhase::ResponseProof,
293        ));
294    }
295    let (reproved, _) = write_document(&reparsed, &bytes)
296        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
297    if reproved != bytes {
298        return Err(codec_error(
299            CodecErrorCode::InternalCoverageFailure,
300            CodecPhase::ResponseProof,
301        ));
302    }
303    provenance.set_occurrence_count(reparsed.occurrence_count);
304    verify_final_wire_proof(&bytes, &provenance, &expected_authorized, &expected_signed)
305        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
306    provenance.mark_final_buffer_verified();
307    if ctx.inspection_projection_requested() && provenance.signed_opaque_ranges().is_empty() {
308        Ok(ProvedResponseBody::new_with_inspection_parsed_facts(
309            bytes,
310            WireFormat::Json,
311            provenance,
312            InspectionParsedFactsV1::AnthropicJson(JsonInspectionParsedFactsV1 {
313                root: reparsed.root,
314            }),
315        ))
316    } else {
317        Ok(ProvedResponseBody::new(bytes, WireFormat::Json, provenance))
318    }
319}
320
321fn validate_adjacent_response_text(
322    root: &JsonNode,
323    ctx: &mut ResponseTransformContext<'_>,
324) -> Result<(), CodecErrorCode> {
325    let JsonKind::Object(root_members) = &root.kind else {
326        return Err(CodecErrorCode::UnsupportedResponseSurface);
327    };
328    let content = root_members
329        .iter()
330        .find(|member| member.key.value == "content")
331        .ok_or(CodecErrorCode::UnsupportedResponseSurface)?;
332    let JsonKind::Array(blocks) = &content.value.kind else {
333        return Err(CodecErrorCode::UnsupportedResponseSurface);
334    };
335    let mut logical = String::new();
336    let mut authorized = Vec::<Range<usize>>::new();
337    for block in blocks {
338        if object_string(block, "type")? != "text" {
339            continue;
340        }
341        let JsonKind::Object(members) = &block.kind else {
342            return Err(CodecErrorCode::UnsupportedResponseSurface);
343        };
344        let text = members
345            .iter()
346            .find(|member| member.key.value == "text")
347            .ok_or(CodecErrorCode::UnsupportedResponseSurface)?;
348        let JsonKind::String(value) = &text.value.kind else {
349            return Err(CodecErrorCode::UnsupportedResponseSurface);
350        };
351        let base = logical.len();
352        logical.push_str(&value.value);
353        authorized.extend(
354            value
355                .authorized
356                .iter()
357                .map(|range| base + range.start..base + range.end),
358        );
359    }
360    ctx.validate(&logical, &authorized)
361}
362
363fn restore_text_response(
364    input: &[u8],
365    ctx: &mut ResponseTransformContext<'_>,
366) -> Result<ProvedResponseBody, CodecError> {
367    let text = std::str::from_utf8(input)
368        .map_err(|_| codec_error(CodecErrorCode::InvalidUtf8, CodecPhase::ResponseParse))?;
369    let restored = ctx
370        .restore(text)
371        .map_err(|code| codec_error(code, CodecPhase::ResponseRestore))?;
372    guard_mutable_text_response(&restored.text)
373        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
374    ctx.validate(&restored.text, &restored.authorized_output_ranges)
375        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
376    if !ctx
377        .limits()
378        .output_within_growth_limit(input.len(), restored.text.len())
379    {
380        return Err(codec_error(
381            CodecErrorCode::GrowthLimitExceeded,
382            CodecPhase::ResponseProof,
383        ));
384    }
385    let output = restored.text.into_bytes();
386    let mut provenance = OutputProvenance::default();
387    let mut expected_authorized = Vec::new();
388    for range in restored.authorized_output_ranges {
389        expected_authorized.push(
390            output
391                .get(range.clone())
392                .ok_or_else(|| {
393                    codec_error(
394                        CodecErrorCode::InternalCoverageFailure,
395                        CodecPhase::ResponseProof,
396                    )
397                })?
398                .to_vec(),
399        );
400        provenance.record_authorized(range);
401    }
402    let final_text = std::str::from_utf8(&output)
403        .map_err(|_| codec_error(CodecErrorCode::InvalidUtf8, CodecPhase::ResponseProof))?;
404    guard_mutable_text_response(final_text)
405        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
406    ctx.validate(final_text, provenance.authorized_output_ranges())
407        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
408    verify_final_wire_proof(&output, &provenance, &expected_authorized, &[])
409        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
410    provenance.mark_final_buffer_verified();
411    Ok(ProvedResponseBody::new(
412        output,
413        WireFormat::Utf8Text,
414        provenance,
415    ))
416}
417
418fn restore_ndjson_response(
419    input: &[u8],
420    ctx: &mut ResponseTransformContext<'_>,
421) -> Result<ProvedResponseBody, CodecError> {
422    let text = std::str::from_utf8(input)
423        .map_err(|_| codec_error(CodecErrorCode::InvalidUtf8, CodecPhase::ResponseParse))?;
424    let mut output = Vec::with_capacity(input.len());
425    let mut provenance = OutputProvenance::default();
426    let mut expected_authorized = Vec::<Vec<u8>>::new();
427    let mut expected_signed = Vec::<Vec<u8>>::new();
428    let mut expected_authorized_ranges = Vec::<Range<usize>>::new();
429    let mut expected_signed_ranges = Vec::<Range<usize>>::new();
430    for line in text.split_inclusive('\n') {
431        let (body, newline) = line
432            .strip_suffix('\n')
433            .map_or((line, ""), |body| (body, "\n"));
434        if body.trim().is_empty() {
435            output.extend_from_slice(newline.as_bytes());
436            continue;
437        }
438        let proved = restore_json_response(body.as_bytes(), ctx)?;
439        let offset = output.len();
440        for range in proved.provenance().authorized_output_ranges() {
441            append_expected_wire_chunk(
442                proved.bytes(),
443                range,
444                offset,
445                &mut expected_authorized_ranges,
446                &mut expected_authorized,
447            )
448            .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
449        }
450        for range in proved.provenance().signed_opaque_ranges() {
451            append_expected_wire_chunk(
452                proved.bytes(),
453                range,
454                offset,
455                &mut expected_signed_ranges,
456                &mut expected_signed,
457            )
458            .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
459        }
460        output.extend_from_slice(proved.bytes());
461        for range in proved.provenance().authorized_output_ranges() {
462            provenance.record_authorized(offset + range.start..offset + range.end);
463        }
464        for range in proved.provenance().signed_opaque_ranges() {
465            provenance.record_signed(offset + range.start..offset + range.end);
466        }
467        output.extend_from_slice(newline.as_bytes());
468    }
469    if output.len() > ctx.limits().max_body_bytes() {
470        return Err(codec_error(
471            CodecErrorCode::BodyLimitExceeded,
472            CodecPhase::ResponseProof,
473        ));
474    }
475    if !ctx
476        .limits()
477        .output_within_growth_limit(input.len(), output.len())
478    {
479        return Err(codec_error(
480            CodecErrorCode::GrowthLimitExceeded,
481            CodecPhase::ResponseProof,
482        ));
483    }
484    let final_occurrence_count = reprove_ndjson_output(&output, ctx.limits())?;
485    provenance.set_occurrence_count(final_occurrence_count);
486    verify_final_wire_proof(&output, &provenance, &expected_authorized, &expected_signed)
487        .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
488    provenance.mark_final_buffer_verified();
489    Ok(ProvedResponseBody::new(
490        output,
491        WireFormat::Ndjson,
492        provenance,
493    ))
494}
495
496fn reprove_ndjson_output(output: &[u8], limits: CodecLimits) -> Result<usize, CodecError> {
497    let text = std::str::from_utf8(output)
498        .map_err(|_| codec_error(CodecErrorCode::InvalidUtf8, CodecPhase::ResponseProof))?;
499    let mut occurrence_count = 0usize;
500    for line in text.split_inclusive('\n') {
501        let body = line.strip_suffix('\n').unwrap_or(line);
502        if body.trim().is_empty() {
503            continue;
504        }
505        let document = parse_json(body.as_bytes(), limits, CodecPhase::ResponseProof)?;
506        let mut ledger = CoverageLedger::new(document.occurrence_count);
507        account_subtree(&document.root, &mut ledger)
508            .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
509        ledger
510            .finish()
511            .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
512        prove_response_root_shape(&document.root)
513            .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
514        let (reproved, _) = write_document(&document, body.as_bytes())
515            .map_err(|code| codec_error(code, CodecPhase::ResponseProof))?;
516        if reproved != body.as_bytes() {
517            return Err(codec_error(
518                CodecErrorCode::InternalCoverageFailure,
519                CodecPhase::ResponseProof,
520            ));
521        }
522        occurrence_count = occurrence_count
523            .checked_add(document.occurrence_count)
524            .ok_or_else(|| {
525                codec_error(CodecErrorCode::NodeLimitExceeded, CodecPhase::ResponseProof)
526            })?;
527    }
528    Ok(occurrence_count)
529}
530
531struct JsonDocument {
532    root: JsonNode,
533    occurrence_count: usize,
534}
535
536struct JsonNode {
537    occurrence: usize,
538    span: Range<usize>,
539    raw_preserve: bool,
540    kind: JsonKind,
541}
542
543enum JsonKind {
544    Object(Vec<JsonMember>),
545    Array(Vec<JsonNode>),
546    String(JsonString),
547    Number(String),
548    Bool(bool),
549    Null,
550}
551
552pub(crate) struct JsonInspectionParsedFactsV1 {
553    root: JsonNode,
554}
555
556pub(crate) struct SseInspectionParsedFactsV1 {
557    frames: Vec<SseFrame>,
558    complete: bool,
559}
560
561struct JsonInspectionProjectionSourceV1 {
562    root: JsonNode,
563}
564
565struct SseInspectionProjectionSourceV1 {
566    frames: Vec<SseFrame>,
567    complete: bool,
568}
569
570impl SseInspectionParsedFactsV1 {
571    pub(crate) fn project(self) -> InspectionStructuralProjectionV1 {
572        #[cfg(test)]
573        record_inspection_construction(|counts| counts.sse_sources_built += 1);
574        SseInspectionProjectionSourceV1 {
575            frames: self.frames,
576            complete: self.complete,
577        }
578        .project()
579    }
580}
581
582impl SseInspectionProjectionSourceV1 {
583    fn project(self) -> InspectionStructuralProjectionV1 {
584        #[cfg(test)]
585        record_inspection_construction(|counts| counts.sse_timelines_built += 1);
586        let entries = self
587            .complete
588            .then(|| {
589                self.frames
590                    .into_iter()
591                    .filter_map(|frame| frame.inspection_fact)
592                    .enumerate()
593                    .map(|(ordinal, fact)| {
594                        let ordinal = u32::try_from(ordinal).ok()?;
595                        Some(SseTimelineEntryV1::new(
596                            SseEntryOrdinalV1::new(ordinal),
597                            fact.event_kind,
598                            fact.delta_kind,
599                            fact.content_block,
600                        ))
601                    })
602                    .collect::<Option<Vec<_>>>()
603            })
604            .flatten();
605        let sse_timeline = entries
606            .and_then(|entries| SseTimelineMetaV1::try_new(entries).ok())
607            .map_or_else(
608                || {
609                    ProjectionAvailabilityV1::Omitted(
610                        ProjectionOmissionReasonV1::ProjectionFailedClosed,
611                    )
612                },
613                ProjectionAvailabilityV1::Present,
614            );
615        InspectionStructuralProjectionV1 {
616            json_shape: ProjectionAvailabilityV1::Omitted(
617                ProjectionOmissionReasonV1::UnsupportedFormat,
618            ),
619            sse_timeline,
620        }
621    }
622}
623
624impl JsonInspectionParsedFactsV1 {
625    pub(crate) fn project(self) -> InspectionStructuralProjectionV1 {
626        #[cfg(test)]
627        record_inspection_construction(|counts| counts.json_sources_built += 1);
628        JsonInspectionProjectionSourceV1 { root: self.root }.project()
629    }
630}
631
632impl JsonInspectionProjectionSourceV1 {
633    fn project(self) -> InspectionStructuralProjectionV1 {
634        let mut nodes = Vec::with_capacity(MAX_JSON_SHAPE_NODES_V1.min(64));
635        let mut truncated = false;
636        collect_json_shape(&self.root, &mut nodes, &mut truncated);
637        let truncation = if truncated {
638            JsonShapeTruncationCodeV1::NodeLimit
639        } else {
640            JsonShapeTruncationCodeV1::Complete
641        };
642        let json_shape = JsonShapeSummaryV1::try_new(nodes, truncation).map_or_else(
643            |_| {
644                ProjectionAvailabilityV1::Omitted(
645                    ProjectionOmissionReasonV1::ProjectionFailedClosed,
646                )
647            },
648            ProjectionAvailabilityV1::Present,
649        );
650        InspectionStructuralProjectionV1 {
651            json_shape,
652            sse_timeline: ProjectionAvailabilityV1::Omitted(
653                ProjectionOmissionReasonV1::UnsupportedFormat,
654            ),
655        }
656    }
657}
658
659fn collect_json_shape(node: &JsonNode, output: &mut Vec<JsonShapeNodeV1>, truncated: &mut bool) {
660    if output.len() >= MAX_JSON_SHAPE_NODES_V1 {
661        *truncated = true;
662        return;
663    }
664    let ordinal = JsonNodeOrdinalV1::new(output.len() as u32);
665    let type_code = match &node.kind {
666        JsonKind::Object(_) => JsonTypeCodeV1::Object,
667        JsonKind::Array(_) => JsonTypeCodeV1::Array,
668        JsonKind::String(_) => JsonTypeCodeV1::String,
669        JsonKind::Number(_) => JsonTypeCodeV1::Number,
670        JsonKind::Bool(_) => JsonTypeCodeV1::Boolean,
671        JsonKind::Null => JsonTypeCodeV1::Null,
672    };
673    output.push(JsonShapeNodeV1::new(ordinal, type_code));
674    match &node.kind {
675        JsonKind::Object(members) => {
676            for member in members {
677                collect_json_shape(&member.value, output, truncated);
678            }
679        }
680        JsonKind::Array(values) => {
681            for value in values {
682                collect_json_shape(value, output, truncated);
683            }
684        }
685        JsonKind::String(_) | JsonKind::Number(_) | JsonKind::Bool(_) | JsonKind::Null => {}
686    }
687}
688
689struct JsonMember {
690    key_occurrence: usize,
691    key: JsonString,
692    value: JsonNode,
693}
694
695struct JsonString {
696    value: String,
697    authorized: Vec<Range<usize>>,
698}
699
700struct JsonParser<'a> {
701    bytes: &'a [u8],
702    position: usize,
703    limits: CodecLimits,
704    nodes: usize,
705    next_occurrence: usize,
706}
707
708fn parse_json(
709    input: &[u8],
710    limits: CodecLimits,
711    phase: CodecPhase,
712) -> Result<JsonDocument, CodecError> {
713    if input.len() > limits.max_body_bytes() {
714        return Err(codec_error(CodecErrorCode::BodyLimitExceeded, phase));
715    }
716    std::str::from_utf8(input).map_err(|_| codec_error(CodecErrorCode::InvalidUtf8, phase))?;
717    let mut parser = JsonParser {
718        bytes: input,
719        position: 0,
720        limits,
721        nodes: 0,
722        next_occurrence: 0,
723    };
724    parser.skip_whitespace();
725    let root = parser
726        .parse_value(0)
727        .map_err(|code| codec_error(code, phase))?;
728    parser.skip_whitespace();
729    if parser.position != input.len() {
730        return Err(codec_error(CodecErrorCode::InvalidJson, phase));
731    }
732    Ok(JsonDocument {
733        root,
734        occurrence_count: parser.next_occurrence,
735    })
736}
737
738impl JsonParser<'_> {
739    fn parse_value(&mut self, depth: usize) -> Result<JsonNode, CodecErrorCode> {
740        if depth > self.limits.max_json_depth() {
741            return Err(CodecErrorCode::DepthLimitExceeded);
742        }
743        self.nodes = self
744            .nodes
745            .checked_add(1)
746            .ok_or(CodecErrorCode::NodeLimitExceeded)?;
747        if self.nodes > self.limits.max_json_nodes() {
748            return Err(CodecErrorCode::NodeLimitExceeded);
749        }
750        let occurrence = self.occurrence();
751        let start = self.position;
752        let kind = match self.peek() {
753            Some(b'{') => self.parse_object(depth + 1)?,
754            Some(b'[') => self.parse_array(depth + 1)?,
755            Some(b'"') => JsonKind::String(self.parse_string()?),
756            Some(b't') => {
757                self.consume_literal(b"true")?;
758                JsonKind::Bool(true)
759            }
760            Some(b'f') => {
761                self.consume_literal(b"false")?;
762                JsonKind::Bool(false)
763            }
764            Some(b'n') => {
765                self.consume_literal(b"null")?;
766                JsonKind::Null
767            }
768            Some(b'-' | b'0'..=b'9') => JsonKind::Number(self.parse_number()?),
769            _ => return Err(CodecErrorCode::InvalidJson),
770        };
771        Ok(JsonNode {
772            occurrence,
773            span: start..self.position,
774            raw_preserve: false,
775            kind,
776        })
777    }
778
779    fn parse_object(&mut self, depth: usize) -> Result<JsonKind, CodecErrorCode> {
780        self.position += 1;
781        self.skip_whitespace();
782        let mut members = Vec::new();
783        let mut keys = HashSet::new();
784        if self.peek() == Some(b'}') {
785            self.position += 1;
786            return Ok(JsonKind::Object(members));
787        }
788        loop {
789            if self.peek() != Some(b'"') {
790                return Err(CodecErrorCode::InvalidJson);
791            }
792            let key_occurrence = self.occurrence();
793            let key = self.parse_string()?;
794            if !key.value.is_ascii() {
795                return Err(CodecErrorCode::InvalidJson);
796            }
797            if !keys.insert(key.value.clone()) {
798                return Err(CodecErrorCode::DuplicateObjectKey);
799            }
800            self.skip_whitespace();
801            if self.take() != Some(b':') {
802                return Err(CodecErrorCode::InvalidJson);
803            }
804            self.skip_whitespace();
805            let value = self.parse_value(depth)?;
806            members.push(JsonMember {
807                key_occurrence,
808                key,
809                value,
810            });
811            self.skip_whitespace();
812            match self.take() {
813                Some(b',') => self.skip_whitespace(),
814                Some(b'}') => break,
815                _ => return Err(CodecErrorCode::InvalidJson),
816            }
817        }
818        Ok(JsonKind::Object(members))
819    }
820
821    fn parse_array(&mut self, depth: usize) -> Result<JsonKind, CodecErrorCode> {
822        self.position += 1;
823        self.skip_whitespace();
824        let mut values = Vec::new();
825        if self.peek() == Some(b']') {
826            self.position += 1;
827            return Ok(JsonKind::Array(values));
828        }
829        loop {
830            values.push(self.parse_value(depth)?);
831            self.skip_whitespace();
832            match self.take() {
833                Some(b',') => self.skip_whitespace(),
834                Some(b']') => break,
835                _ => return Err(CodecErrorCode::InvalidJson),
836            }
837        }
838        Ok(JsonKind::Array(values))
839    }
840
841    fn parse_string(&mut self) -> Result<JsonString, CodecErrorCode> {
842        if self.take() != Some(b'"') {
843            return Err(CodecErrorCode::InvalidJson);
844        }
845        let mut value = String::new();
846        loop {
847            let byte = self.take().ok_or(CodecErrorCode::InvalidJson)?;
848            match byte {
849                b'"' => break,
850                b'\\' => self.parse_escape(&mut value)?,
851                0x00..=0x1f => return Err(CodecErrorCode::InvalidJson),
852                0x20..=0x7f => value.push(char::from(byte)),
853                _ => {
854                    let start = self.position - 1;
855                    let remaining = std::str::from_utf8(&self.bytes[start..])
856                        .map_err(|_| CodecErrorCode::InvalidUtf8)?;
857                    let character = remaining
858                        .chars()
859                        .next()
860                        .ok_or(CodecErrorCode::InvalidUtf8)?;
861                    value.push(character);
862                    self.position = start + character.len_utf8();
863                }
864            }
865            if value.len() > self.limits.max_string_bytes() {
866                return Err(CodecErrorCode::StringLimitExceeded);
867            }
868        }
869        Ok(JsonString {
870            value,
871            authorized: Vec::new(),
872        })
873    }
874
875    fn parse_escape(&mut self, output: &mut String) -> Result<(), CodecErrorCode> {
876        match self.take().ok_or(CodecErrorCode::InvalidJson)? {
877            b'"' => output.push('"'),
878            b'\\' => output.push('\\'),
879            b'/' => output.push('/'),
880            b'b' => output.push('\u{0008}'),
881            b'f' => output.push('\u{000c}'),
882            b'n' => output.push('\n'),
883            b'r' => output.push('\r'),
884            b't' => output.push('\t'),
885            b'u' => {
886                let first = self.parse_hex_quad()?;
887                let scalar = if (0xd800..=0xdbff).contains(&first) {
888                    if self.take() != Some(b'\\') || self.take() != Some(b'u') {
889                        return Err(CodecErrorCode::InvalidJson);
890                    }
891                    let second = self.parse_hex_quad()?;
892                    if !(0xdc00..=0xdfff).contains(&second) {
893                        return Err(CodecErrorCode::InvalidJson);
894                    }
895                    0x1_0000 + (((u32::from(first) - 0xd800) << 10) | (u32::from(second) - 0xdc00))
896                } else if (0xdc00..=0xdfff).contains(&first) {
897                    return Err(CodecErrorCode::InvalidJson);
898                } else {
899                    u32::from(first)
900                };
901                output.push(char::from_u32(scalar).ok_or(CodecErrorCode::InvalidJson)?);
902            }
903            _ => return Err(CodecErrorCode::InvalidJson),
904        }
905        Ok(())
906    }
907
908    fn parse_hex_quad(&mut self) -> Result<u16, CodecErrorCode> {
909        let mut value = 0u16;
910        for _ in 0..4 {
911            let digit = self
912                .take()
913                .and_then(hex_value)
914                .ok_or(CodecErrorCode::InvalidJson)?;
915            value = (value << 4) | u16::from(digit);
916        }
917        Ok(value)
918    }
919
920    fn parse_number(&mut self) -> Result<String, CodecErrorCode> {
921        let start = self.position;
922        if self.peek() == Some(b'-') {
923            self.position += 1;
924        }
925        match self.take() {
926            Some(b'0') if matches!(self.peek(), Some(b'0'..=b'9')) => {
927                return Err(CodecErrorCode::InvalidJson);
928            }
929            Some(b'0'..=b'9') => {
930                while matches!(self.peek(), Some(b'0'..=b'9')) {
931                    self.position += 1;
932                }
933            }
934            _ => return Err(CodecErrorCode::InvalidJson),
935        }
936        if self.peek() == Some(b'.') {
937            self.position += 1;
938            if !matches!(self.peek(), Some(b'0'..=b'9')) {
939                return Err(CodecErrorCode::InvalidJson);
940            }
941            while matches!(self.peek(), Some(b'0'..=b'9')) {
942                self.position += 1;
943            }
944        }
945        if matches!(self.peek(), Some(b'e' | b'E')) {
946            self.position += 1;
947            if matches!(self.peek(), Some(b'+' | b'-')) {
948                self.position += 1;
949            }
950            if !matches!(self.peek(), Some(b'0'..=b'9')) {
951                return Err(CodecErrorCode::InvalidJson);
952            }
953            while matches!(self.peek(), Some(b'0'..=b'9')) {
954                self.position += 1;
955            }
956        }
957        let raw = &self.bytes[start..self.position];
958        if raw.len() > self.limits.max_number_bytes() {
959            return Err(CodecErrorCode::NumberLimitExceeded);
960        }
961        Ok(std::str::from_utf8(raw)
962            .map_err(|_| CodecErrorCode::InvalidUtf8)?
963            .to_owned())
964    }
965
966    fn consume_literal(&mut self, literal: &[u8]) -> Result<(), CodecErrorCode> {
967        if self.bytes.get(self.position..self.position + literal.len()) != Some(literal) {
968            return Err(CodecErrorCode::InvalidJson);
969        }
970        self.position += literal.len();
971        Ok(())
972    }
973
974    fn occurrence(&mut self) -> usize {
975        let occurrence = self.next_occurrence;
976        self.next_occurrence += 1;
977        occurrence
978    }
979
980    fn skip_whitespace(&mut self) {
981        while matches!(self.peek(), Some(b' ' | b'\n' | b'\r' | b'\t')) {
982            self.position += 1;
983        }
984    }
985
986    fn peek(&self) -> Option<u8> {
987        self.bytes.get(self.position).copied()
988    }
989
990    fn take(&mut self) -> Option<u8> {
991        let value = self.peek()?;
992        self.position += 1;
993        Some(value)
994    }
995}
996
997fn hex_value(byte: u8) -> Option<u8> {
998    match byte {
999        b'0'..=b'9' => Some(byte - b'0'),
1000        b'a'..=b'f' => Some(byte - b'a' + 10),
1001        b'A'..=b'F' => Some(byte - b'A' + 10),
1002        _ => None,
1003    }
1004}
1005
1006struct CoverageLedger {
1007    visited: Vec<bool>,
1008}
1009
1010impl CoverageLedger {
1011    fn new(count: usize) -> Self {
1012        Self {
1013            visited: vec![false; count],
1014        }
1015    }
1016
1017    fn mark(&mut self, occurrence: usize) -> Result<(), CodecErrorCode> {
1018        let slot = self
1019            .visited
1020            .get_mut(occurrence)
1021            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
1022        if *slot {
1023            return Err(CodecErrorCode::InternalCoverageFailure);
1024        }
1025        *slot = true;
1026        Ok(())
1027    }
1028
1029    fn finish(self) -> Result<(), CodecErrorCode> {
1030        if self.visited.into_iter().all(|visited| visited) {
1031            Ok(())
1032        } else {
1033            Err(CodecErrorCode::InternalCoverageFailure)
1034        }
1035    }
1036}
1037
1038#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1039enum RequestCarrierClass {
1040    ReviewedConstant,
1041    RoutingControl,
1042    PromptMutable,
1043    PromptImmutable,
1044    MetadataMutable,
1045    SignedOpaque,
1046}
1047
1048#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1049enum PromptComponent {
1050    System,
1051    Tools,
1052    Messages,
1053}
1054
1055#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1056enum CarrierOrder {
1057    Semantic,
1058    Emitted,
1059}
1060
1061#[derive(Clone, Copy)]
1062enum SemanticObjectOrder {
1063    Closed(&'static [&'static str]),
1064    DecodedKeys,
1065}
1066
1067#[derive(Clone, Copy)]
1068struct FinalRequestCarrier<'a> {
1069    class: RequestCarrierClass,
1070    component: Option<PromptComponent>,
1071    text: &'a str,
1072}
1073
1074struct FinalRequestCarrierInventory<'a> {
1075    carriers: Vec<Option<FinalRequestCarrier<'a>>>,
1076    object_orders: Vec<Option<SemanticObjectOrder>>,
1077}
1078
1079impl<'a> FinalRequestCarrierInventory<'a> {
1080    fn new(occurrence_count: usize) -> Self {
1081        Self {
1082            carriers: vec![None; occurrence_count],
1083            object_orders: vec![None; occurrence_count],
1084        }
1085    }
1086
1087    fn classify(
1088        &mut self,
1089        occurrence: usize,
1090        text: &'a str,
1091        class: RequestCarrierClass,
1092        component: Option<PromptComponent>,
1093    ) -> Result<(), CodecErrorCode> {
1094        let slot = self
1095            .carriers
1096            .get_mut(occurrence)
1097            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
1098        if slot.is_some() {
1099            return Err(CodecErrorCode::InternalCoverageFailure);
1100        }
1101        *slot = Some(FinalRequestCarrier {
1102            class,
1103            component,
1104            text,
1105        });
1106        Ok(())
1107    }
1108
1109    fn set_object_order(
1110        &mut self,
1111        occurrence: usize,
1112        order: SemanticObjectOrder,
1113    ) -> Result<(), CodecErrorCode> {
1114        let slot = self
1115            .object_orders
1116            .get_mut(occurrence)
1117            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
1118        if slot.is_some() {
1119            return Err(CodecErrorCode::InternalCoverageFailure);
1120        }
1121        *slot = Some(order);
1122        Ok(())
1123    }
1124
1125    fn carrier(&self, occurrence: usize) -> Result<FinalRequestCarrier<'a>, CodecErrorCode> {
1126        self.carriers
1127            .get(occurrence)
1128            .and_then(Option::as_ref)
1129            .copied()
1130            .ok_or(CodecErrorCode::InternalCoverageFailure)
1131    }
1132
1133    fn object_order(&self, occurrence: usize) -> Result<SemanticObjectOrder, CodecErrorCode> {
1134        self.object_orders
1135            .get(occurrence)
1136            .and_then(Option::as_ref)
1137            .copied()
1138            .ok_or(CodecErrorCode::InternalCoverageFailure)
1139    }
1140
1141    fn prompt_component_present(&self, component: PromptComponent) -> bool {
1142        self.carriers.iter().flatten().any(|carrier| {
1143            carrier.component == Some(component)
1144                && matches!(
1145                    carrier.class,
1146                    RequestCarrierClass::PromptMutable | RequestCarrierClass::PromptImmutable
1147                )
1148        })
1149    }
1150
1151    fn metadata_present(&self) -> bool {
1152        self.carriers
1153            .iter()
1154            .flatten()
1155            .any(|carrier| carrier.class == RequestCarrierClass::MetadataMutable)
1156    }
1157
1158    fn validate_complete(&self, root: &JsonNode) -> Result<(), CodecErrorCode> {
1159        let mut expected_carriers = vec![false; self.carriers.len()];
1160        let mut expected_objects = vec![false; self.object_orders.len()];
1161        collect_inventory_expectations(root, &mut expected_carriers, &mut expected_objects)?;
1162        if expected_carriers
1163            .iter()
1164            .zip(&self.carriers)
1165            .any(|(expected, carrier)| *expected != carrier.is_some())
1166            || expected_objects
1167                .iter()
1168                .zip(&self.object_orders)
1169                .any(|(expected, order)| *expected != order.is_some())
1170        {
1171            return Err(CodecErrorCode::InternalCoverageFailure);
1172        }
1173        Ok(())
1174    }
1175}
1176
1177const ROOT_SEMANTIC_FIELDS: &[&str] = &[
1178    "system",
1179    "tools",
1180    "messages",
1181    "metadata",
1182    "model",
1183    "service_tier",
1184    "max_tokens",
1185    "top_k",
1186    "temperature",
1187    "top_p",
1188    "stream",
1189    "stop_sequences",
1190    "thinking",
1191    "tool_choice",
1192    "cache_control",
1193];
1194const MESSAGE_SEMANTIC_FIELDS: &[&str] = &["role", "content"];
1195const TEXT_BLOCK_SEMANTIC_FIELDS: &[&str] = &["type", "text", "cache_control"];
1196const TOOL_USE_BLOCK_SEMANTIC_FIELDS: &[&str] = &["type", "id", "name", "input", "cache_control"];
1197const TOOL_RESULT_BLOCK_SEMANTIC_FIELDS: &[&str] = &[
1198    "type",
1199    "tool_use_id",
1200    "content",
1201    "is_error",
1202    "cache_control",
1203];
1204const DOCUMENT_BLOCK_SEMANTIC_FIELDS: &[&str] =
1205    &["type", "source", "title", "context", "cache_control"];
1206const SEARCH_BLOCK_SEMANTIC_FIELDS: &[&str] = &[
1207    "type",
1208    "title",
1209    "context",
1210    "text",
1211    "content",
1212    "cache_control",
1213];
1214const THINKING_BLOCK_SEMANTIC_FIELDS: &[&str] = &["type", "thinking", "signature", "cache_control"];
1215const REDACTED_THINKING_BLOCK_SEMANTIC_FIELDS: &[&str] = &["type", "data", "cache_control"];
1216const DOCUMENT_SOURCE_SEMANTIC_FIELDS: &[&str] = &["type", "media_type", "data", "text", "content"];
1217const TOOL_SEMANTIC_FIELDS: &[&str] = &[
1218    "name",
1219    "type",
1220    "description",
1221    "input_schema",
1222    "cache_control",
1223];
1224const SCHEMA_SEMANTIC_FIELDS: &[&str] = &[
1225    "type",
1226    "title",
1227    "description",
1228    "properties",
1229    "required",
1230    "$defs",
1231    "items",
1232    "additionalProperties",
1233    "anyOf",
1234    "allOf",
1235    "oneOf",
1236    "examples",
1237    "default",
1238    "const",
1239    "enum",
1240    "$ref",
1241    "$id",
1242    "$schema",
1243    "format",
1244    "pattern",
1245    "minimum",
1246    "maximum",
1247];
1248const CACHE_CONTROL_SEMANTIC_FIELDS: &[&str] = &["type", "ttl"];
1249const THINKING_CONTROL_SEMANTIC_FIELDS: &[&str] = &["type", "budget_tokens"];
1250const TOOL_CHOICE_SEMANTIC_FIELDS: &[&str] = &["type", "name", "disable_parallel_tool_use"];
1251
1252fn collect_inventory_expectations(
1253    node: &JsonNode,
1254    carriers: &mut [bool],
1255    objects: &mut [bool],
1256) -> Result<(), CodecErrorCode> {
1257    let mark = |slots: &mut [bool], occurrence: usize| -> Result<(), CodecErrorCode> {
1258        let slot = slots
1259            .get_mut(occurrence)
1260            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
1261        if *slot {
1262            return Err(CodecErrorCode::InternalCoverageFailure);
1263        }
1264        *slot = true;
1265        Ok(())
1266    };
1267    match &node.kind {
1268        JsonKind::Object(members) => {
1269            mark(objects, node.occurrence)?;
1270            for member in members {
1271                mark(carriers, member.key_occurrence)?;
1272                collect_inventory_expectations(&member.value, carriers, objects)?;
1273            }
1274        }
1275        JsonKind::Array(values) => {
1276            for value in values {
1277                collect_inventory_expectations(value, carriers, objects)?;
1278            }
1279        }
1280        JsonKind::String(_) => mark(carriers, node.occurrence)?,
1281        JsonKind::Number(_) | JsonKind::Bool(_) | JsonKind::Null => {}
1282    }
1283    Ok(())
1284}
1285
1286fn collect_final_request_carriers<'a>(
1287    root: &'a JsonNode,
1288    occurrence_count: usize,
1289) -> Result<FinalRequestCarrierInventory<'a>, CodecErrorCode> {
1290    let mut inventory = FinalRequestCarrierInventory::new(occurrence_count);
1291    classify_request_root(root, &mut inventory)?;
1292    inventory.validate_complete(root)?;
1293    Ok(inventory)
1294}
1295
1296fn classify_request_root<'a>(
1297    node: &'a JsonNode,
1298    inventory: &mut FinalRequestCarrierInventory<'a>,
1299) -> Result<(), CodecErrorCode> {
1300    let members = object_members(node)?;
1301    inventory.set_object_order(
1302        node.occurrence,
1303        SemanticObjectOrder::Closed(ROOT_SEMANTIC_FIELDS),
1304    )?;
1305    for member in members {
1306        classify_key(
1307            member,
1308            RequestCarrierClass::ReviewedConstant,
1309            None,
1310            inventory,
1311        )?;
1312        match member.key.value.as_str() {
1313            "model" => classify_string_node(
1314                &member.value,
1315                RequestCarrierClass::RoutingControl,
1316                None,
1317                inventory,
1318            )?,
1319            "service_tier" => classify_string_node(
1320                &member.value,
1321                RequestCarrierClass::ReviewedConstant,
1322                None,
1323                inventory,
1324            )?,
1325            "stop_sequences" => classify_string_array(
1326                &member.value,
1327                RequestCarrierClass::RoutingControl,
1328                None,
1329                inventory,
1330            )?,
1331            "system" => classify_request_system(&member.value, inventory)?,
1332            "messages" => classify_request_messages(&member.value, inventory)?,
1333            "tools" => classify_request_tools(&member.value, inventory)?,
1334            "metadata" => classify_arbitrary_value(
1335                &member.value,
1336                RequestCarrierClass::MetadataMutable,
1337                None,
1338                inventory,
1339            )?,
1340            "thinking" => classify_thinking_control(&member.value, inventory)?,
1341            "tool_choice" => classify_tool_choice_control(&member.value, inventory)?,
1342            "cache_control" => classify_cache_control(&member.value, inventory)?,
1343            "max_tokens" | "top_k" | "temperature" | "top_p" | "stream" => {}
1344            _ => return Err(CodecErrorCode::InternalCoverageFailure),
1345        }
1346    }
1347    Ok(())
1348}
1349
1350fn classify_request_system<'a>(
1351    node: &'a JsonNode,
1352    inventory: &mut FinalRequestCarrierInventory<'a>,
1353) -> Result<(), CodecErrorCode> {
1354    match &node.kind {
1355        JsonKind::String(_) => classify_string_node(
1356            node,
1357            RequestCarrierClass::PromptMutable,
1358            Some(PromptComponent::System),
1359            inventory,
1360        ),
1361        JsonKind::Array(blocks) => {
1362            for block in blocks {
1363                classify_request_block(block, PromptComponent::System, inventory)?;
1364            }
1365            Ok(())
1366        }
1367        _ => Err(CodecErrorCode::InternalCoverageFailure),
1368    }
1369}
1370
1371fn classify_request_messages<'a>(
1372    node: &'a JsonNode,
1373    inventory: &mut FinalRequestCarrierInventory<'a>,
1374) -> Result<(), CodecErrorCode> {
1375    let JsonKind::Array(messages) = &node.kind else {
1376        return Err(CodecErrorCode::InternalCoverageFailure);
1377    };
1378    for message in messages {
1379        let members = object_members(message)?;
1380        inventory.set_object_order(
1381            message.occurrence,
1382            SemanticObjectOrder::Closed(MESSAGE_SEMANTIC_FIELDS),
1383        )?;
1384        for member in members {
1385            classify_key(
1386                member,
1387                RequestCarrierClass::ReviewedConstant,
1388                None,
1389                inventory,
1390            )?;
1391            match member.key.value.as_str() {
1392                "role" => classify_string_node(
1393                    &member.value,
1394                    RequestCarrierClass::ReviewedConstant,
1395                    None,
1396                    inventory,
1397                )?,
1398                "content" => {
1399                    classify_request_content(&member.value, PromptComponent::Messages, inventory)?
1400                }
1401                _ => return Err(CodecErrorCode::InternalCoverageFailure),
1402            }
1403        }
1404    }
1405    Ok(())
1406}
1407
1408fn classify_request_content<'a>(
1409    node: &'a JsonNode,
1410    component: PromptComponent,
1411    inventory: &mut FinalRequestCarrierInventory<'a>,
1412) -> Result<(), CodecErrorCode> {
1413    match &node.kind {
1414        JsonKind::String(_) => classify_string_node(
1415            node,
1416            RequestCarrierClass::PromptMutable,
1417            Some(component),
1418            inventory,
1419        ),
1420        JsonKind::Array(blocks) => {
1421            for block in blocks {
1422                classify_request_block(block, component, inventory)?;
1423            }
1424            Ok(())
1425        }
1426        _ => Err(CodecErrorCode::InternalCoverageFailure),
1427    }
1428}
1429
1430fn classify_request_block<'a>(
1431    node: &'a JsonNode,
1432    component: PromptComponent,
1433    inventory: &mut FinalRequestCarrierInventory<'a>,
1434) -> Result<(), CodecErrorCode> {
1435    let block_type = object_string(node, "type")?;
1436    let order = match block_type {
1437        "text" => TEXT_BLOCK_SEMANTIC_FIELDS,
1438        "tool_use" => TOOL_USE_BLOCK_SEMANTIC_FIELDS,
1439        "tool_result" => TOOL_RESULT_BLOCK_SEMANTIC_FIELDS,
1440        "document" => DOCUMENT_BLOCK_SEMANTIC_FIELDS,
1441        "search_result" | "custom_content" => SEARCH_BLOCK_SEMANTIC_FIELDS,
1442        "thinking" => THINKING_BLOCK_SEMANTIC_FIELDS,
1443        "redacted_thinking" => REDACTED_THINKING_BLOCK_SEMANTIC_FIELDS,
1444        _ => return Err(CodecErrorCode::InternalCoverageFailure),
1445    };
1446    let members = object_members(node)?;
1447    inventory.set_object_order(node.occurrence, SemanticObjectOrder::Closed(order))?;
1448    for member in members {
1449        classify_key(
1450            member,
1451            RequestCarrierClass::ReviewedConstant,
1452            None,
1453            inventory,
1454        )?;
1455        match (block_type, member.key.value.as_str()) {
1456            (_, "type") => classify_string_node(
1457                &member.value,
1458                RequestCarrierClass::ReviewedConstant,
1459                None,
1460                inventory,
1461            )?,
1462            (_, "cache_control") => classify_cache_control(&member.value, inventory)?,
1463            ("text", "text") => classify_string_node(
1464                &member.value,
1465                RequestCarrierClass::PromptMutable,
1466                Some(component),
1467                inventory,
1468            )?,
1469            ("tool_use", "id" | "name") | ("tool_result", "tool_use_id") => classify_string_node(
1470                &member.value,
1471                RequestCarrierClass::PromptImmutable,
1472                Some(component),
1473                inventory,
1474            )?,
1475            ("tool_use", "input") => classify_arbitrary_value(
1476                &member.value,
1477                RequestCarrierClass::PromptMutable,
1478                Some(component),
1479                inventory,
1480            )?,
1481            ("tool_result", "content") => {
1482                classify_request_content(&member.value, component, inventory)?
1483            }
1484            ("tool_result", "is_error") => {}
1485            ("document", "source") => {
1486                classify_document_source(&member.value, component, inventory)?
1487            }
1488            ("document", "title" | "context")
1489            | ("search_result" | "custom_content", "title" | "context" | "text" | "content") => {
1490                classify_arbitrary_value(
1491                    &member.value,
1492                    RequestCarrierClass::PromptMutable,
1493                    Some(component),
1494                    inventory,
1495                )?
1496            }
1497            ("thinking", "thinking") => classify_string_node(
1498                &member.value,
1499                RequestCarrierClass::PromptImmutable,
1500                Some(component),
1501                inventory,
1502            )?,
1503            ("thinking", "signature") | ("redacted_thinking", "data") => classify_string_node(
1504                &member.value,
1505                RequestCarrierClass::SignedOpaque,
1506                None,
1507                inventory,
1508            )?,
1509            _ => return Err(CodecErrorCode::InternalCoverageFailure),
1510        }
1511    }
1512    Ok(())
1513}
1514
1515fn classify_document_source<'a>(
1516    node: &'a JsonNode,
1517    component: PromptComponent,
1518    inventory: &mut FinalRequestCarrierInventory<'a>,
1519) -> Result<(), CodecErrorCode> {
1520    let members = object_members(node)?;
1521    inventory.set_object_order(
1522        node.occurrence,
1523        SemanticObjectOrder::Closed(DOCUMENT_SOURCE_SEMANTIC_FIELDS),
1524    )?;
1525    for member in members {
1526        classify_key(
1527            member,
1528            RequestCarrierClass::ReviewedConstant,
1529            None,
1530            inventory,
1531        )?;
1532        match member.key.value.as_str() {
1533            "type" => classify_string_node(
1534                &member.value,
1535                RequestCarrierClass::ReviewedConstant,
1536                None,
1537                inventory,
1538            )?,
1539            "media_type" => classify_string_node(
1540                &member.value,
1541                RequestCarrierClass::PromptImmutable,
1542                Some(component),
1543                inventory,
1544            )?,
1545            "data" | "text" | "content" => classify_arbitrary_value(
1546                &member.value,
1547                RequestCarrierClass::PromptMutable,
1548                Some(component),
1549                inventory,
1550            )?,
1551            _ => return Err(CodecErrorCode::InternalCoverageFailure),
1552        }
1553    }
1554    Ok(())
1555}
1556
1557fn classify_request_tools<'a>(
1558    node: &'a JsonNode,
1559    inventory: &mut FinalRequestCarrierInventory<'a>,
1560) -> Result<(), CodecErrorCode> {
1561    let JsonKind::Array(tools) = &node.kind else {
1562        return Err(CodecErrorCode::InternalCoverageFailure);
1563    };
1564    for tool in tools {
1565        let members = object_members(tool)?;
1566        inventory.set_object_order(
1567            tool.occurrence,
1568            SemanticObjectOrder::Closed(TOOL_SEMANTIC_FIELDS),
1569        )?;
1570        for member in members {
1571            classify_key(
1572                member,
1573                RequestCarrierClass::ReviewedConstant,
1574                None,
1575                inventory,
1576            )?;
1577            match member.key.value.as_str() {
1578                "name" => classify_string_node(
1579                    &member.value,
1580                    RequestCarrierClass::PromptImmutable,
1581                    Some(PromptComponent::Tools),
1582                    inventory,
1583                )?,
1584                "type" => classify_string_node(
1585                    &member.value,
1586                    RequestCarrierClass::ReviewedConstant,
1587                    None,
1588                    inventory,
1589                )?,
1590                "description" => classify_string_node(
1591                    &member.value,
1592                    RequestCarrierClass::PromptMutable,
1593                    Some(PromptComponent::Tools),
1594                    inventory,
1595                )?,
1596                "input_schema" => classify_request_schema(&member.value, inventory)?,
1597                "cache_control" => classify_cache_control(&member.value, inventory)?,
1598                _ => return Err(CodecErrorCode::InternalCoverageFailure),
1599            }
1600        }
1601    }
1602    Ok(())
1603}
1604
1605fn classify_request_schema<'a>(
1606    node: &'a JsonNode,
1607    inventory: &mut FinalRequestCarrierInventory<'a>,
1608) -> Result<(), CodecErrorCode> {
1609    let members = object_members(node)?;
1610    inventory.set_object_order(
1611        node.occurrence,
1612        SemanticObjectOrder::Closed(SCHEMA_SEMANTIC_FIELDS),
1613    )?;
1614    for member in members {
1615        classify_key(
1616            member,
1617            RequestCarrierClass::ReviewedConstant,
1618            None,
1619            inventory,
1620        )?;
1621        match member.key.value.as_str() {
1622            "description" | "title" | "examples" | "default" => classify_arbitrary_value(
1623                &member.value,
1624                RequestCarrierClass::PromptMutable,
1625                Some(PromptComponent::Tools),
1626                inventory,
1627            )?,
1628            "properties" => {
1629                classify_schema_map(&member.value, RequestCarrierClass::PromptMutable, inventory)?
1630            }
1631            "$defs" => classify_schema_map(
1632                &member.value,
1633                RequestCarrierClass::PromptImmutable,
1634                inventory,
1635            )?,
1636            "items" => classify_request_schema(&member.value, inventory)?,
1637            "additionalProperties" => {
1638                if matches!(member.value.kind, JsonKind::Object(_)) {
1639                    classify_request_schema(&member.value, inventory)?;
1640                }
1641            }
1642            "anyOf" | "allOf" | "oneOf" => {
1643                let JsonKind::Array(values) = &member.value.kind else {
1644                    return Err(CodecErrorCode::InternalCoverageFailure);
1645                };
1646                for value in values {
1647                    classify_request_schema(value, inventory)?;
1648                }
1649            }
1650            "required" => classify_string_array(
1651                &member.value,
1652                RequestCarrierClass::PromptImmutable,
1653                Some(PromptComponent::Tools),
1654                inventory,
1655            )?,
1656            "type" => classify_schema_type(&member.value, inventory)?,
1657            "$ref" | "$id" | "$schema" | "format" | "pattern" => classify_string_node(
1658                &member.value,
1659                RequestCarrierClass::PromptImmutable,
1660                Some(PromptComponent::Tools),
1661                inventory,
1662            )?,
1663            "const" => classify_schema_literal(&member.value, inventory)?,
1664            "enum" => {
1665                let JsonKind::Array(values) = &member.value.kind else {
1666                    return Err(CodecErrorCode::InternalCoverageFailure);
1667                };
1668                for value in values {
1669                    classify_schema_literal(value, inventory)?;
1670                }
1671            }
1672            "minimum" | "maximum" => {}
1673            _ => return Err(CodecErrorCode::InternalCoverageFailure),
1674        }
1675    }
1676    Ok(())
1677}
1678
1679fn classify_schema_map<'a>(
1680    node: &'a JsonNode,
1681    key_class: RequestCarrierClass,
1682    inventory: &mut FinalRequestCarrierInventory<'a>,
1683) -> Result<(), CodecErrorCode> {
1684    let members = object_members(node)?;
1685    inventory.set_object_order(node.occurrence, SemanticObjectOrder::DecodedKeys)?;
1686    for member in members {
1687        classify_key(member, key_class, Some(PromptComponent::Tools), inventory)?;
1688        classify_request_schema(&member.value, inventory)?;
1689    }
1690    Ok(())
1691}
1692
1693fn classify_schema_type<'a>(
1694    node: &'a JsonNode,
1695    inventory: &mut FinalRequestCarrierInventory<'a>,
1696) -> Result<(), CodecErrorCode> {
1697    match &node.kind {
1698        JsonKind::String(_) => {
1699            classify_string_node(node, RequestCarrierClass::ReviewedConstant, None, inventory)
1700        }
1701        JsonKind::Array(values) => {
1702            for value in values {
1703                classify_string_node(
1704                    value,
1705                    RequestCarrierClass::ReviewedConstant,
1706                    None,
1707                    inventory,
1708                )?;
1709            }
1710            Ok(())
1711        }
1712        _ => Err(CodecErrorCode::InternalCoverageFailure),
1713    }
1714}
1715
1716fn classify_schema_literal<'a>(
1717    node: &'a JsonNode,
1718    inventory: &mut FinalRequestCarrierInventory<'a>,
1719) -> Result<(), CodecErrorCode> {
1720    if matches!(node.kind, JsonKind::String(_)) {
1721        classify_string_node(
1722            node,
1723            RequestCarrierClass::PromptImmutable,
1724            Some(PromptComponent::Tools),
1725            inventory,
1726        )?;
1727    }
1728    Ok(())
1729}
1730
1731fn classify_arbitrary_value<'a>(
1732    node: &'a JsonNode,
1733    class: RequestCarrierClass,
1734    component: Option<PromptComponent>,
1735    inventory: &mut FinalRequestCarrierInventory<'a>,
1736) -> Result<(), CodecErrorCode> {
1737    match &node.kind {
1738        JsonKind::Object(members) => {
1739            inventory.set_object_order(node.occurrence, SemanticObjectOrder::DecodedKeys)?;
1740            for member in members {
1741                classify_key(member, class, component, inventory)?;
1742                classify_arbitrary_value(&member.value, class, component, inventory)?;
1743            }
1744            Ok(())
1745        }
1746        JsonKind::Array(values) => {
1747            for value in values {
1748                classify_arbitrary_value(value, class, component, inventory)?;
1749            }
1750            Ok(())
1751        }
1752        JsonKind::String(_) => classify_string_node(node, class, component, inventory),
1753        JsonKind::Bool(_) | JsonKind::Null => Ok(()),
1754        JsonKind::Number(_) => Err(CodecErrorCode::InternalCoverageFailure),
1755    }
1756}
1757
1758fn classify_cache_control<'a>(
1759    node: &'a JsonNode,
1760    inventory: &mut FinalRequestCarrierInventory<'a>,
1761) -> Result<(), CodecErrorCode> {
1762    classify_closed_constant_object(node, CACHE_CONTROL_SEMANTIC_FIELDS, inventory)
1763}
1764
1765fn classify_thinking_control<'a>(
1766    node: &'a JsonNode,
1767    inventory: &mut FinalRequestCarrierInventory<'a>,
1768) -> Result<(), CodecErrorCode> {
1769    classify_closed_constant_object(node, THINKING_CONTROL_SEMANTIC_FIELDS, inventory)
1770}
1771
1772fn classify_tool_choice_control<'a>(
1773    node: &'a JsonNode,
1774    inventory: &mut FinalRequestCarrierInventory<'a>,
1775) -> Result<(), CodecErrorCode> {
1776    let members = object_members(node)?;
1777    inventory.set_object_order(
1778        node.occurrence,
1779        SemanticObjectOrder::Closed(TOOL_CHOICE_SEMANTIC_FIELDS),
1780    )?;
1781    for member in members {
1782        classify_key(
1783            member,
1784            RequestCarrierClass::ReviewedConstant,
1785            None,
1786            inventory,
1787        )?;
1788        match member.key.value.as_str() {
1789            "type" => classify_string_node(
1790                &member.value,
1791                RequestCarrierClass::ReviewedConstant,
1792                None,
1793                inventory,
1794            )?,
1795            "name" => classify_string_node(
1796                &member.value,
1797                RequestCarrierClass::RoutingControl,
1798                None,
1799                inventory,
1800            )?,
1801            "disable_parallel_tool_use" => {}
1802            _ => return Err(CodecErrorCode::InternalCoverageFailure),
1803        }
1804    }
1805    Ok(())
1806}
1807
1808fn classify_closed_constant_object<'a>(
1809    node: &'a JsonNode,
1810    order: &'static [&'static str],
1811    inventory: &mut FinalRequestCarrierInventory<'a>,
1812) -> Result<(), CodecErrorCode> {
1813    let members = object_members(node)?;
1814    inventory.set_object_order(node.occurrence, SemanticObjectOrder::Closed(order))?;
1815    for member in members {
1816        classify_key(
1817            member,
1818            RequestCarrierClass::ReviewedConstant,
1819            None,
1820            inventory,
1821        )?;
1822        if matches!(member.value.kind, JsonKind::String(_)) {
1823            classify_string_node(
1824                &member.value,
1825                RequestCarrierClass::ReviewedConstant,
1826                None,
1827                inventory,
1828            )?;
1829        }
1830    }
1831    Ok(())
1832}
1833
1834fn classify_string_array<'a>(
1835    node: &'a JsonNode,
1836    class: RequestCarrierClass,
1837    component: Option<PromptComponent>,
1838    inventory: &mut FinalRequestCarrierInventory<'a>,
1839) -> Result<(), CodecErrorCode> {
1840    let JsonKind::Array(values) = &node.kind else {
1841        return Err(CodecErrorCode::InternalCoverageFailure);
1842    };
1843    for value in values {
1844        classify_string_node(value, class, component, inventory)?;
1845    }
1846    Ok(())
1847}
1848
1849fn classify_key<'a>(
1850    member: &'a JsonMember,
1851    class: RequestCarrierClass,
1852    component: Option<PromptComponent>,
1853    inventory: &mut FinalRequestCarrierInventory<'a>,
1854) -> Result<(), CodecErrorCode> {
1855    inventory.classify(member.key_occurrence, &member.key.value, class, component)
1856}
1857
1858fn classify_string_node<'a>(
1859    node: &'a JsonNode,
1860    class: RequestCarrierClass,
1861    component: Option<PromptComponent>,
1862    inventory: &mut FinalRequestCarrierInventory<'a>,
1863) -> Result<(), CodecErrorCode> {
1864    let JsonKind::String(value) = &node.kind else {
1865        return Err(CodecErrorCode::InternalCoverageFailure);
1866    };
1867    inventory.classify(node.occurrence, &value.value, class, component)
1868}
1869
1870fn object_members(node: &JsonNode) -> Result<&[JsonMember], CodecErrorCode> {
1871    let JsonKind::Object(members) = &node.kind else {
1872        return Err(CodecErrorCode::InternalCoverageFailure);
1873    };
1874    Ok(members)
1875}
1876
1877#[derive(Clone, Copy)]
1878enum RequestViewSelection {
1879    Prompt(PromptComponent),
1880    Metadata,
1881}
1882
1883fn build_prompt_component_view(
1884    root: &JsonNode,
1885    inventory: &FinalRequestCarrierInventory<'_>,
1886    component: PromptComponent,
1887    order: CarrierOrder,
1888    limit: usize,
1889) -> Result<Zeroizing<String>, CodecErrorCode> {
1890    let mut output = Zeroizing::new(String::new());
1891    append_request_view(
1892        root,
1893        inventory,
1894        RequestViewSelection::Prompt(component),
1895        order,
1896        limit,
1897        &mut output,
1898    )?;
1899    Ok(output)
1900}
1901
1902fn build_metadata_view(
1903    root: &JsonNode,
1904    inventory: &FinalRequestCarrierInventory<'_>,
1905    order: CarrierOrder,
1906    limit: usize,
1907) -> Result<Zeroizing<String>, CodecErrorCode> {
1908    let mut output = Zeroizing::new(String::new());
1909    append_request_view(
1910        root,
1911        inventory,
1912        RequestViewSelection::Metadata,
1913        order,
1914        limit,
1915        &mut output,
1916    )?;
1917    Ok(output)
1918}
1919
1920fn append_request_view(
1921    node: &JsonNode,
1922    inventory: &FinalRequestCarrierInventory<'_>,
1923    selection: RequestViewSelection,
1924    order: CarrierOrder,
1925    limit: usize,
1926    output: &mut String,
1927) -> Result<(), CodecErrorCode> {
1928    match &node.kind {
1929        JsonKind::Object(members) => match order {
1930            CarrierOrder::Emitted => {
1931                for member in members {
1932                    append_inventory_carrier(
1933                        member.key_occurrence,
1934                        inventory,
1935                        selection,
1936                        limit,
1937                        output,
1938                    )?;
1939                    append_request_view(&member.value, inventory, selection, order, limit, output)?;
1940                }
1941            }
1942            CarrierOrder::Semantic => {
1943                let mut ordered = Vec::new();
1944                ordered
1945                    .try_reserve(members.len())
1946                    .map_err(|_| CodecErrorCode::BodyLimitExceeded)?;
1947                ordered.extend(members);
1948                match inventory.object_order(node.occurrence)? {
1949                    SemanticObjectOrder::Closed(fields) => {
1950                        if ordered
1951                            .iter()
1952                            .any(|member| !fields.contains(&member.key.value.as_str()))
1953                        {
1954                            return Err(CodecErrorCode::InternalCoverageFailure);
1955                        }
1956                        ordered.sort_by_key(|member| {
1957                            fields
1958                                .iter()
1959                                .position(|field| *field == member.key.value)
1960                                .unwrap_or(fields.len())
1961                        });
1962                    }
1963                    SemanticObjectOrder::DecodedKeys => ordered.sort_by(|left, right| {
1964                        left.key.value.as_bytes().cmp(right.key.value.as_bytes())
1965                    }),
1966                }
1967                for member in ordered {
1968                    append_inventory_carrier(
1969                        member.key_occurrence,
1970                        inventory,
1971                        selection,
1972                        limit,
1973                        output,
1974                    )?;
1975                    append_request_view(&member.value, inventory, selection, order, limit, output)?;
1976                }
1977            }
1978        },
1979        JsonKind::Array(values) => {
1980            for value in values {
1981                append_request_view(value, inventory, selection, order, limit, output)?;
1982            }
1983        }
1984        JsonKind::String(_) => {
1985            append_inventory_carrier(node.occurrence, inventory, selection, limit, output)?;
1986        }
1987        JsonKind::Number(_) | JsonKind::Bool(_) | JsonKind::Null => {}
1988    }
1989    Ok(())
1990}
1991
1992fn append_inventory_carrier(
1993    occurrence: usize,
1994    inventory: &FinalRequestCarrierInventory<'_>,
1995    selection: RequestViewSelection,
1996    limit: usize,
1997    output: &mut String,
1998) -> Result<(), CodecErrorCode> {
1999    let carrier = inventory.carrier(occurrence)?;
2000    let include = match selection {
2001        RequestViewSelection::Prompt(component) => {
2002            carrier.component == Some(component)
2003                && matches!(
2004                    carrier.class,
2005                    RequestCarrierClass::PromptMutable | RequestCarrierClass::PromptImmutable
2006                )
2007        }
2008        RequestViewSelection::Metadata => carrier.class == RequestCarrierClass::MetadataMutable,
2009    };
2010    if include {
2011        append_bounded(output, carrier.text, limit)?;
2012    }
2013    Ok(())
2014}
2015
2016fn append_bounded(output: &mut String, value: &str, limit: usize) -> Result<(), CodecErrorCode> {
2017    let new_len = output
2018        .len()
2019        .checked_add(value.len())
2020        .ok_or(CodecErrorCode::BodyLimitExceeded)?;
2021    if new_len > limit {
2022        return Err(CodecErrorCode::BodyLimitExceeded);
2023    }
2024    output
2025        .try_reserve(value.len())
2026        .map_err(|_| CodecErrorCode::BodyLimitExceeded)?;
2027    output.push_str(value);
2028    Ok(())
2029}
2030
2031#[derive(Default)]
2032struct RequestViewProbeOutcome {
2033    would_mutate: bool,
2034    contains_opaque_carrier: bool,
2035}
2036
2037impl RequestViewProbeOutcome {
2038    fn include(&mut self, other: Self) {
2039        self.would_mutate |= other.would_mutate;
2040        self.contains_opaque_carrier |= other.contains_opaque_carrier;
2041    }
2042}
2043
2044fn probe_request_view(
2045    view: &str,
2046    ctx: &mut RequestTransformContext<'_>,
2047) -> Result<RequestViewProbeOutcome, CodecErrorCode> {
2048    let contains_opaque_carrier = match guard_request_mutable_text(view, ctx) {
2049        Ok(()) => false,
2050        Err(CodecErrorCode::OpaqueMediaUninspected) => true,
2051        Err(code) => return Err(code),
2052    };
2053    ctx.validate_token_shapes(view)?;
2054    let transformed = Zeroizing::new(ctx.probe_without_prefix_cache_write(view)?);
2055    Ok(RequestViewProbeOutcome {
2056        would_mutate: transformed.as_bytes() != view.as_bytes(),
2057        contains_opaque_carrier,
2058    })
2059}
2060
2061fn prove_prompt_order(
2062    root: &JsonNode,
2063    inventory: &FinalRequestCarrierInventory<'_>,
2064    order: CarrierOrder,
2065    limit: usize,
2066    ctx: &mut RequestTransformContext<'_>,
2067) -> Result<RequestViewProbeOutcome, CodecErrorCode> {
2068    let mut components = Vec::new();
2069    for component in [
2070        PromptComponent::System,
2071        PromptComponent::Tools,
2072        PromptComponent::Messages,
2073    ] {
2074        if inventory.prompt_component_present(component) {
2075            components.push((
2076                component,
2077                build_prompt_component_view(root, inventory, component, order, limit)?,
2078            ));
2079        }
2080    }
2081    if components.is_empty() {
2082        return Ok(RequestViewProbeOutcome::default());
2083    }
2084    let permutations: &[&[usize]] = match components.len() {
2085        1 => &[&[0]],
2086        2 => &[&[0, 1], &[1, 0]],
2087        3 => &[
2088            &[0, 1, 2],
2089            &[0, 2, 1],
2090            &[1, 0, 2],
2091            &[1, 2, 0],
2092            &[2, 0, 1],
2093            &[2, 1, 0],
2094        ],
2095        _ => return Err(CodecErrorCode::InternalCoverageFailure),
2096    };
2097    let mut outcome = RequestViewProbeOutcome::default();
2098    for permutation in permutations {
2099        let mut view = Zeroizing::new(String::new());
2100        for index in *permutation {
2101            append_bounded(&mut view, &components[*index].1, limit)?;
2102        }
2103        outcome.include(probe_request_view(&view, ctx)?);
2104    }
2105    Ok(outcome)
2106}
2107
2108fn prove_request_logical_domains(
2109    root: &JsonNode,
2110    occurrence_count: usize,
2111    ctx: &mut RequestTransformContext<'_>,
2112) -> Result<(), CodecErrorCode> {
2113    let inventory = collect_final_request_carriers(root, occurrence_count)?;
2114    let limit = ctx
2115        .limits()
2116        .max_body_bytes()
2117        .min(MAX_ANTHROPIC_REQUEST_BODY_BYTES);
2118    let mut outcome = RequestViewProbeOutcome::default();
2119    for order in [CarrierOrder::Semantic, CarrierOrder::Emitted] {
2120        outcome.include(prove_prompt_order(root, &inventory, order, limit, ctx)?);
2121    }
2122    if inventory.metadata_present() {
2123        for order in [CarrierOrder::Semantic, CarrierOrder::Emitted] {
2124            let view = build_metadata_view(root, &inventory, order, limit)?;
2125            outcome.include(probe_request_view(&view, ctx)?);
2126        }
2127    }
2128    if outcome.contains_opaque_carrier {
2129        Err(CodecErrorCode::OpaqueMediaUninspected)
2130    } else if outcome.would_mutate {
2131        Err(CodecErrorCode::ControlWouldMutate)
2132    } else {
2133        Ok(())
2134    }
2135}
2136
2137fn account_subtree(node: &JsonNode, ledger: &mut CoverageLedger) -> Result<(), CodecErrorCode> {
2138    ledger.mark(node.occurrence)?;
2139    match &node.kind {
2140        JsonKind::Object(members) => {
2141            for member in members {
2142                ledger.mark(member.key_occurrence)?;
2143                account_subtree(&member.value, ledger)?;
2144            }
2145        }
2146        JsonKind::Array(values) => {
2147            for value in values {
2148                account_subtree(value, ledger)?;
2149            }
2150        }
2151        JsonKind::String(_) | JsonKind::Number(_) | JsonKind::Bool(_) | JsonKind::Null => {}
2152    }
2153    Ok(())
2154}
2155
2156fn transform_request_root(
2157    node: &mut JsonNode,
2158    input: &[u8],
2159    ctx: &mut RequestTransformContext<'_>,
2160    ledger: &mut CoverageLedger,
2161) -> Result<(), CodecErrorCode> {
2162    ledger.mark(node.occurrence)?;
2163    let JsonKind::Object(members) = &mut node.kind else {
2164        return Err(CodecErrorCode::UnsupportedRequestSurface);
2165    };
2166    let mut saw_model = false;
2167    let mut saw_max_tokens = false;
2168    let mut saw_messages = false;
2169    for member in members {
2170        ledger.mark(member.key_occurrence)?;
2171        match member.key.value.as_str() {
2172            "model" => {
2173                request_nonempty_string_control(&mut member.value, ctx, ledger)?;
2174                saw_model = true;
2175            }
2176            "service_tier" => request_enum_string_control(
2177                &mut member.value,
2178                &["auto", "standard_only"],
2179                ctx,
2180                ledger,
2181            )?,
2182            "max_tokens" => {
2183                request_integer_control(&member.value, ledger, true)?;
2184                saw_max_tokens = true;
2185            }
2186            "top_k" => request_integer_control(&member.value, ledger, false)?,
2187            "temperature" | "top_p" => request_unit_interval_control(&member.value, ledger)?,
2188            "stream" => request_bool_control(&member.value, ledger)?,
2189            "stop_sequences" => request_string_array_control(&mut member.value, ctx, ledger)?,
2190            "system" => transform_request_system(&mut member.value, input, ctx, ledger)?,
2191            "messages" => {
2192                transform_request_messages(&mut member.value, input, ctx, ledger)?;
2193                saw_messages = true;
2194            }
2195            "tools" => transform_request_tools(&mut member.value, input, ctx, ledger)?,
2196            "metadata" => transform_request_mutable(&mut member.value, ctx, ledger)?,
2197            "thinking" => transform_thinking_control(&mut member.value, ctx, ledger)?,
2198            "tool_choice" => transform_tool_choice_control(&mut member.value, ctx, ledger)?,
2199            "cache_control" => transform_cache_control(&mut member.value, ctx, ledger)?,
2200            _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2201        }
2202    }
2203    if saw_model && saw_max_tokens && saw_messages {
2204        Ok(())
2205    } else {
2206        Err(CodecErrorCode::UnsupportedRequestSurface)
2207    }
2208}
2209
2210fn transform_request_messages(
2211    node: &mut JsonNode,
2212    input: &[u8],
2213    ctx: &mut RequestTransformContext<'_>,
2214    ledger: &mut CoverageLedger,
2215) -> Result<(), CodecErrorCode> {
2216    ledger.mark(node.occurrence)?;
2217    let JsonKind::Array(messages) = &mut node.kind else {
2218        return Err(CodecErrorCode::UnsupportedRequestSurface);
2219    };
2220    for message in messages {
2221        ledger.mark(message.occurrence)?;
2222        let JsonKind::Object(members) = &mut message.kind else {
2223            return Err(CodecErrorCode::UnsupportedRequestSurface);
2224        };
2225        let mut saw_role = false;
2226        let mut saw_content = false;
2227        for member in members {
2228            ledger.mark(member.key_occurrence)?;
2229            match member.key.value.as_str() {
2230                "role" => {
2231                    request_enum_string_control(
2232                        &mut member.value,
2233                        &["user", "assistant"],
2234                        ctx,
2235                        ledger,
2236                    )?;
2237                    saw_role = true;
2238                }
2239                "content" => {
2240                    transform_request_content(&mut member.value, input, ctx, ledger)?;
2241                    saw_content = true;
2242                }
2243                _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2244            }
2245        }
2246        if !saw_role || !saw_content {
2247            return Err(CodecErrorCode::UnsupportedRequestSurface);
2248        }
2249    }
2250    Ok(())
2251}
2252
2253fn transform_request_content(
2254    node: &mut JsonNode,
2255    input: &[u8],
2256    ctx: &mut RequestTransformContext<'_>,
2257    ledger: &mut CoverageLedger,
2258) -> Result<(), CodecErrorCode> {
2259    match &mut node.kind {
2260        JsonKind::String(_) => transform_request_string(node, ctx, ledger),
2261        JsonKind::Array(blocks) => {
2262            ledger.mark(node.occurrence)?;
2263            if blocks.is_empty() {
2264                return Err(CodecErrorCode::UnsupportedRequestSurface);
2265            }
2266            for (index, block) in blocks.iter_mut().enumerate() {
2267                transform_request_block_at_index(block, index, input, ctx, ledger)?;
2268            }
2269            Ok(())
2270        }
2271        _ => Err(CodecErrorCode::UnsupportedRequestSurface),
2272    }
2273}
2274
2275fn transform_request_system(
2276    node: &mut JsonNode,
2277    input: &[u8],
2278    ctx: &mut RequestTransformContext<'_>,
2279    ledger: &mut CoverageLedger,
2280) -> Result<(), CodecErrorCode> {
2281    match &mut node.kind {
2282        JsonKind::String(_) => transform_request_string(node, ctx, ledger),
2283        JsonKind::Array(blocks) => {
2284            ledger.mark(node.occurrence)?;
2285            if blocks.is_empty() {
2286                return Err(CodecErrorCode::UnsupportedRequestSurface);
2287            }
2288            for (index, block) in blocks.iter_mut().enumerate() {
2289                if object_string(block, "type")? != "text" {
2290                    return Err(CodecErrorCode::UnsupportedRequestSurface);
2291                }
2292                transform_request_block_at_index(block, index, input, ctx, ledger)?;
2293            }
2294            Ok(())
2295        }
2296        _ => Err(CodecErrorCode::UnsupportedRequestSurface),
2297    }
2298}
2299
2300fn transform_request_block_at_index(
2301    node: &mut JsonNode,
2302    index: usize,
2303    input: &[u8],
2304    ctx: &mut RequestTransformContext<'_>,
2305    ledger: &mut CoverageLedger,
2306) -> Result<(), CodecErrorCode> {
2307    let previous = ctx.replace_content_block_index(Some(index));
2308    let result = transform_request_block(node, input, ctx, ledger);
2309    ctx.replace_content_block_index(previous);
2310    result
2311}
2312
2313fn transform_request_block(
2314    node: &mut JsonNode,
2315    input: &[u8],
2316    ctx: &mut RequestTransformContext<'_>,
2317    ledger: &mut CoverageLedger,
2318) -> Result<(), CodecErrorCode> {
2319    let block_type = object_string(node, "type")?.to_owned();
2320    if !matches!(
2321        block_type.as_str(),
2322        "text"
2323            | "tool_use"
2324            | "tool_result"
2325            | "document"
2326            | "search_result"
2327            | "custom_content"
2328            | "thinking"
2329            | "redacted_thinking"
2330            | "image"
2331    ) {
2332        return Err(CodecErrorCode::UnsupportedRequestSurface);
2333    }
2334    if block_type == "image" {
2335        return Err(CodecErrorCode::OpaqueMediaUninspected);
2336    }
2337    if matches!(block_type.as_str(), "thinking" | "redacted_thinking") {
2338        validate_signed_request_block(node, input, ctx, ledger, &block_type)?;
2339        node.raw_preserve = true;
2340        return Ok(());
2341    }
2342    ledger.mark(node.occurrence)?;
2343    let JsonKind::Object(members) = &mut node.kind else {
2344        return Err(CodecErrorCode::UnsupportedRequestSurface);
2345    };
2346    let mut saw_text = false;
2347    let mut saw_id = false;
2348    let mut saw_name = false;
2349    let mut saw_input = false;
2350    let mut saw_tool_use_id = false;
2351    let mut saw_content = false;
2352    let mut saw_source = false;
2353    let mut saw_user_payload = false;
2354    for member in members {
2355        ledger.mark(member.key_occurrence)?;
2356        match (block_type.as_str(), member.key.value.as_str()) {
2357            (_, "type") => {
2358                request_enum_string_control(
2359                    &mut member.value,
2360                    &[block_type.as_str()],
2361                    ctx,
2362                    ledger,
2363                )?;
2364            }
2365            (_, "cache_control") => transform_cache_control(&mut member.value, ctx, ledger)?,
2366            ("text", "text") => {
2367                transform_request_string(&mut member.value, ctx, ledger)?;
2368                saw_text = true;
2369            }
2370            ("tool_use", "id") => {
2371                request_nonempty_string_control(&mut member.value, ctx, ledger)?;
2372                saw_id = true;
2373            }
2374            ("tool_use", "name") => {
2375                request_nonempty_string_control(&mut member.value, ctx, ledger)?;
2376                saw_name = true;
2377            }
2378            ("tool_use", "input") => {
2379                transform_request_mutable(&mut member.value, ctx, ledger)?;
2380                saw_input = true;
2381            }
2382            ("tool_result", "tool_use_id") => {
2383                request_nonempty_string_control(&mut member.value, ctx, ledger)?;
2384                saw_tool_use_id = true;
2385            }
2386            ("tool_result", "content") => {
2387                transform_request_content(&mut member.value, input, ctx, ledger)?;
2388                saw_content = true;
2389            }
2390            ("tool_result", "is_error") => request_bool_control(&member.value, ledger)?,
2391            ("document", "source") => {
2392                transform_request_document_source(&mut member.value, ctx, ledger)?;
2393                saw_source = true;
2394            }
2395            ("document", "title" | "context") => {
2396                transform_request_mutable(&mut member.value, ctx, ledger)?
2397            }
2398            ("search_result" | "custom_content", "title" | "context" | "text" | "content") => {
2399                transform_request_mutable(&mut member.value, ctx, ledger)?;
2400                saw_user_payload = true;
2401            }
2402            _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2403        }
2404    }
2405    let valid = match block_type.as_str() {
2406        "text" => saw_text,
2407        "tool_use" => saw_id && saw_name && saw_input,
2408        "tool_result" => saw_tool_use_id && saw_content,
2409        "document" => saw_source,
2410        "search_result" | "custom_content" => saw_user_payload,
2411        _ => false,
2412    };
2413    if valid {
2414        Ok(())
2415    } else {
2416        Err(CodecErrorCode::UnsupportedRequestSurface)
2417    }
2418}
2419
2420fn validate_signed_request_block(
2421    node: &JsonNode,
2422    input: &[u8],
2423    ctx: &mut RequestTransformContext<'_>,
2424    ledger: &mut CoverageLedger,
2425    block_type: &str,
2426) -> Result<(), CodecErrorCode> {
2427    account_subtree(node, ledger)?;
2428    let JsonKind::Object(members) = &node.kind else {
2429        return Err(CodecErrorCode::SignedSurfaceMalformed);
2430    };
2431    let mut has_payload = false;
2432    let mut has_signature = false;
2433    for member in members {
2434        match member.key.value.as_str() {
2435            "type" if string_value(&member.value)? == block_type => {}
2436            "cache_control" => validate_cache_control_probe(&member.value, ctx)?,
2437            "signature" => {
2438                ctx.validate_token_shapes(string_value(&member.value)?)?;
2439                has_signature = true;
2440            }
2441            "thinking" if block_type == "thinking" => {
2442                let text = string_value(&member.value)?;
2443                guard_request_mutable_text(text, ctx)?;
2444                ctx.validate_token_shapes(text)?;
2445                if ctx.probe_without_prefix_cache_write(text)? != text {
2446                    return Err(CodecErrorCode::SignedMutationRequired);
2447                }
2448                has_payload = true;
2449            }
2450            "data" if block_type == "redacted_thinking" => {
2451                ctx.validate_token_shapes(string_value(&member.value)?)?;
2452                has_payload = true;
2453            }
2454            _ => return Err(CodecErrorCode::SignedSurfaceMalformed),
2455        }
2456    }
2457    if !has_payload || (block_type == "thinking" && !has_signature) || node.span.end > input.len() {
2458        return Err(CodecErrorCode::SignedSurfaceMalformed);
2459    }
2460    Ok(())
2461}
2462
2463fn probe_signed_request_value(
2464    node: &JsonNode,
2465    ctx: &mut RequestTransformContext<'_>,
2466) -> Result<(), CodecErrorCode> {
2467    match &node.kind {
2468        JsonKind::String(value) => {
2469            ctx.validate_token_shapes(&value.value)?;
2470            if ctx.probe_without_prefix_cache_write(&value.value)? != value.value {
2471                return Err(CodecErrorCode::SignedMutationRequired);
2472            }
2473        }
2474        JsonKind::Object(members) => {
2475            for member in members {
2476                ctx.validate_token_shapes(&member.key.value)?;
2477                if ctx.probe_without_prefix_cache_write(&member.key.value)? != member.key.value {
2478                    return Err(CodecErrorCode::SignedMutationRequired);
2479                }
2480                probe_signed_request_value(&member.value, ctx)?;
2481            }
2482        }
2483        JsonKind::Array(values) => {
2484            for value in values {
2485                probe_signed_request_value(value, ctx)?;
2486            }
2487        }
2488        JsonKind::Number(_) | JsonKind::Bool(_) | JsonKind::Null => {}
2489    }
2490    Ok(())
2491}
2492
2493fn transform_request_document_source(
2494    node: &mut JsonNode,
2495    ctx: &mut RequestTransformContext<'_>,
2496    ledger: &mut CoverageLedger,
2497) -> Result<(), CodecErrorCode> {
2498    let source_type = object_string(node, "type")?.to_owned();
2499    if source_type != "text" && source_type != "content" {
2500        return Err(CodecErrorCode::OpaqueMediaUninspected);
2501    }
2502    ledger.mark(node.occurrence)?;
2503    let JsonKind::Object(members) = &mut node.kind else {
2504        return Err(CodecErrorCode::UnsupportedRequestSurface);
2505    };
2506    let mut saw_payload = false;
2507    for member in members {
2508        ledger.mark(member.key_occurrence)?;
2509        match member.key.value.as_str() {
2510            "type" => request_enum_string_control(
2511                &mut member.value,
2512                &[source_type.as_str()],
2513                ctx,
2514                ledger,
2515            )?,
2516            "media_type" => request_string_control(&mut member.value, ctx, ledger)?,
2517            "data" | "text" | "content" => {
2518                transform_request_mutable(&mut member.value, ctx, ledger)?;
2519                saw_payload = true;
2520            }
2521            _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2522        }
2523    }
2524    if saw_payload {
2525        Ok(())
2526    } else {
2527        Err(CodecErrorCode::UnsupportedRequestSurface)
2528    }
2529}
2530
2531fn transform_request_tools(
2532    node: &mut JsonNode,
2533    _input: &[u8],
2534    ctx: &mut RequestTransformContext<'_>,
2535    ledger: &mut CoverageLedger,
2536) -> Result<(), CodecErrorCode> {
2537    ledger.mark(node.occurrence)?;
2538    let JsonKind::Array(tools) = &mut node.kind else {
2539        return Err(CodecErrorCode::UnsupportedRequestSurface);
2540    };
2541    if tools.is_empty() {
2542        return Err(CodecErrorCode::UnsupportedRequestSurface);
2543    }
2544    for tool in tools {
2545        ledger.mark(tool.occurrence)?;
2546        let JsonKind::Object(members) = &mut tool.kind else {
2547            return Err(CodecErrorCode::UnsupportedRequestSurface);
2548        };
2549        let mut saw_name = false;
2550        let mut saw_schema = false;
2551        for member in members {
2552            ledger.mark(member.key_occurrence)?;
2553            match member.key.value.as_str() {
2554                "name" => {
2555                    request_nonempty_string_control(&mut member.value, ctx, ledger)?;
2556                    saw_name = true;
2557                }
2558                "type" => request_enum_string_control(&mut member.value, &["custom"], ctx, ledger)?,
2559                "cache_control" => transform_cache_control(&mut member.value, ctx, ledger)?,
2560                "description" => transform_request_string(&mut member.value, ctx, ledger)?,
2561                "input_schema" => {
2562                    if object_string(&member.value, "type")? != "object" {
2563                        return Err(CodecErrorCode::UnsupportedRequestSurface);
2564                    }
2565                    transform_request_schema(&mut member.value, ctx, ledger)?;
2566                    saw_schema = true;
2567                }
2568                _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2569            }
2570        }
2571        if !saw_name || !saw_schema {
2572            return Err(CodecErrorCode::UnsupportedRequestSurface);
2573        }
2574    }
2575    Ok(())
2576}
2577
2578fn transform_request_schema(
2579    node: &mut JsonNode,
2580    ctx: &mut RequestTransformContext<'_>,
2581    ledger: &mut CoverageLedger,
2582) -> Result<(), CodecErrorCode> {
2583    match &mut node.kind {
2584        JsonKind::Object(members) => {
2585            ledger.mark(node.occurrence)?;
2586            let mut property_key_map = Vec::<(String, String)>::new();
2587            let mut transformed_property_keys = HashSet::new();
2588            if let Some(properties_member) = members
2589                .iter()
2590                .find(|member| member.key.value == "properties")
2591            {
2592                let JsonKind::Object(properties) = &properties_member.value.kind else {
2593                    return Err(CodecErrorCode::UnsupportedRequestSurface);
2594                };
2595                for property in properties {
2596                    guard_request_mutable_text(&property.key.value, ctx)?;
2597                    ctx.validate_token_shapes(&property.key.value)?;
2598                    let transformed = ctx.protect(&property.key.value)?;
2599                    if !transformed_property_keys.insert(transformed.clone()) {
2600                        return Err(CodecErrorCode::TransformedKeyCollision);
2601                    }
2602                    property_key_map.push((property.key.value.clone(), transformed));
2603                }
2604            }
2605            for member in members {
2606                ledger.mark(member.key_occurrence)?;
2607                match member.key.value.as_str() {
2608                    "description" | "title" | "examples" | "default" => {
2609                        transform_request_mutable(&mut member.value, ctx, ledger)?
2610                    }
2611                    "properties" => {
2612                        ledger.mark(member.value.occurrence)?;
2613                        let JsonKind::Object(properties) = &mut member.value.kind else {
2614                            return Err(CodecErrorCode::UnsupportedRequestSurface);
2615                        };
2616                        for property in properties {
2617                            ledger.mark(property.key_occurrence)?;
2618                            property.key.value = property_key_map
2619                                .iter()
2620                                .find(|(original, _)| original == &property.key.value)
2621                                .map(|(_, transformed)| transformed.clone())
2622                                .ok_or(CodecErrorCode::InternalCoverageFailure)?;
2623                            transform_request_schema(&mut property.value, ctx, ledger)?;
2624                        }
2625                    }
2626                    "$defs" => {
2627                        ledger.mark(member.value.occurrence)?;
2628                        let JsonKind::Object(definitions) = &mut member.value.kind else {
2629                            return Err(CodecErrorCode::UnsupportedRequestSurface);
2630                        };
2631                        for definition in definitions {
2632                            ledger.mark(definition.key_occurrence)?;
2633                            guard_request_mutable_text(&definition.key.value, ctx)?;
2634                            ctx.validate_token_shapes(&definition.key.value)?;
2635                            if ctx.probe_without_prefix_cache_write(&definition.key.value)?
2636                                != definition.key.value
2637                            {
2638                                return Err(CodecErrorCode::ControlWouldMutate);
2639                            }
2640                            transform_request_schema(&mut definition.value, ctx, ledger)?;
2641                        }
2642                    }
2643                    "items" => transform_request_schema(&mut member.value, ctx, ledger)?,
2644                    "additionalProperties" => {
2645                        transform_additional_properties(&mut member.value, ctx, ledger)?
2646                    }
2647                    "anyOf" | "allOf" | "oneOf" => {
2648                        transform_schema_list(&mut member.value, ctx, ledger)?
2649                    }
2650                    "required" => transform_required_property_names(
2651                        &mut member.value,
2652                        &property_key_map,
2653                        ledger,
2654                    )?,
2655                    "type" => transform_schema_type(&mut member.value, ctx, ledger)?,
2656                    "$ref" | "$id" | "$schema" | "format" | "pattern" => {
2657                        request_string_control(&mut member.value, ctx, ledger)?
2658                    }
2659                    "const" => transform_schema_literal(&mut member.value, ctx, ledger)?,
2660                    "enum" => transform_schema_enum(&mut member.value, ctx, ledger)?,
2661                    "minimum" | "maximum" => {
2662                        request_number_literal_control(&member.value, ctx, ledger)?
2663                    }
2664                    _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2665                }
2666            }
2667            Ok(())
2668        }
2669        _ => Err(CodecErrorCode::UnsupportedRequestSurface),
2670    }
2671}
2672
2673fn transform_required_property_names(
2674    node: &mut JsonNode,
2675    property_key_map: &[(String, String)],
2676    ledger: &mut CoverageLedger,
2677) -> Result<(), CodecErrorCode> {
2678    ledger.mark(node.occurrence)?;
2679    let JsonKind::Array(values) = &mut node.kind else {
2680        return Err(CodecErrorCode::UnsupportedRequestSurface);
2681    };
2682    for value in values {
2683        ledger.mark(value.occurrence)?;
2684        let JsonKind::String(required) = &mut value.kind else {
2685            return Err(CodecErrorCode::UnsupportedRequestSurface);
2686        };
2687        required.value = property_key_map
2688            .iter()
2689            .find(|(original, _)| original == &required.value)
2690            .map(|(_, transformed)| transformed.clone())
2691            .ok_or(CodecErrorCode::UnsupportedRequestSurface)?;
2692    }
2693    Ok(())
2694}
2695
2696fn transform_request_mutable(
2697    node: &mut JsonNode,
2698    ctx: &mut RequestTransformContext<'_>,
2699    ledger: &mut CoverageLedger,
2700) -> Result<(), CodecErrorCode> {
2701    match &mut node.kind {
2702        JsonKind::Object(members) => {
2703            ledger.mark(node.occurrence)?;
2704            let mut transformed_keys = HashSet::new();
2705            for member in members {
2706                ledger.mark(member.key_occurrence)?;
2707                protect_key(&mut member.key, ctx)?;
2708                if !transformed_keys.insert(member.key.value.clone()) {
2709                    return Err(CodecErrorCode::TransformedKeyCollision);
2710                }
2711                transform_request_mutable(&mut member.value, ctx, ledger)?;
2712            }
2713            Ok(())
2714        }
2715        JsonKind::Array(values) => {
2716            ledger.mark(node.occurrence)?;
2717            for value in values {
2718                transform_request_mutable(value, ctx, ledger)?;
2719            }
2720            Ok(())
2721        }
2722        JsonKind::String(_) => transform_request_string(node, ctx, ledger),
2723        JsonKind::Bool(_) | JsonKind::Null => ledger.mark(node.occurrence),
2724        JsonKind::Number(_) => {
2725            ledger.mark(node.occurrence)?;
2726            Err(CodecErrorCode::UnsupportedRequestSurface)
2727        }
2728    }
2729}
2730
2731fn transform_request_string(
2732    node: &mut JsonNode,
2733    ctx: &mut RequestTransformContext<'_>,
2734    ledger: &mut CoverageLedger,
2735) -> Result<(), CodecErrorCode> {
2736    ledger.mark(node.occurrence)?;
2737    let JsonKind::String(value) = &mut node.kind else {
2738        return Err(CodecErrorCode::UnsupportedRequestSurface);
2739    };
2740    guard_request_mutable_text(&value.value, ctx)?;
2741    ctx.validate_token_shapes(&value.value)?;
2742    value.value = ctx.protect(&value.value)?;
2743    Ok(())
2744}
2745
2746fn protect_key(
2747    key: &mut JsonString,
2748    ctx: &mut RequestTransformContext<'_>,
2749) -> Result<(), CodecErrorCode> {
2750    guard_request_mutable_text(&key.value, ctx)?;
2751    ctx.validate_token_shapes(&key.value)?;
2752    key.value = ctx.protect(&key.value)?;
2753    Ok(())
2754}
2755
2756fn request_string_control(
2757    node: &mut JsonNode,
2758    ctx: &mut RequestTransformContext<'_>,
2759    ledger: &mut CoverageLedger,
2760) -> Result<(), CodecErrorCode> {
2761    ledger.mark(node.occurrence)?;
2762    let JsonKind::String(value) = &node.kind else {
2763        return Err(CodecErrorCode::UnsupportedRequestSurface);
2764    };
2765    guard_request_mutable_text(&value.value, ctx)?;
2766    ctx.validate_token_shapes(&value.value)?;
2767    if ctx.probe_without_prefix_cache_write(&value.value)? == value.value {
2768        Ok(())
2769    } else {
2770        Err(CodecErrorCode::ControlWouldMutate)
2771    }
2772}
2773
2774fn request_nonempty_string_control(
2775    node: &mut JsonNode,
2776    ctx: &mut RequestTransformContext<'_>,
2777    ledger: &mut CoverageLedger,
2778) -> Result<(), CodecErrorCode> {
2779    if string_value(node)?.is_empty() {
2780        return Err(CodecErrorCode::UnsupportedRequestSurface);
2781    }
2782    request_string_control(node, ctx, ledger)
2783}
2784
2785fn request_enum_string_control(
2786    node: &mut JsonNode,
2787    allowed: &[&str],
2788    ctx: &mut RequestTransformContext<'_>,
2789    ledger: &mut CoverageLedger,
2790) -> Result<(), CodecErrorCode> {
2791    if !allowed.contains(&string_value(node)?) {
2792        return Err(CodecErrorCode::UnsupportedRequestSurface);
2793    }
2794    request_string_control(node, ctx, ledger)
2795}
2796
2797fn request_string_array_control(
2798    node: &mut JsonNode,
2799    ctx: &mut RequestTransformContext<'_>,
2800    ledger: &mut CoverageLedger,
2801) -> Result<(), CodecErrorCode> {
2802    ledger.mark(node.occurrence)?;
2803    let JsonKind::Array(values) = &mut node.kind else {
2804        return Err(CodecErrorCode::UnsupportedRequestSurface);
2805    };
2806    for value in values {
2807        request_string_control(value, ctx, ledger)?;
2808    }
2809    Ok(())
2810}
2811
2812fn transform_cache_control(
2813    node: &mut JsonNode,
2814    ctx: &mut RequestTransformContext<'_>,
2815    ledger: &mut CoverageLedger,
2816) -> Result<(), CodecErrorCode> {
2817    ledger.mark(node.occurrence)?;
2818    let JsonKind::Object(members) = &mut node.kind else {
2819        return Err(CodecErrorCode::UnsupportedRequestSurface);
2820    };
2821    let mut saw_type = false;
2822    for member in members {
2823        ledger.mark(member.key_occurrence)?;
2824        match member.key.value.as_str() {
2825            "type" => {
2826                request_enum_string_control(&mut member.value, &["ephemeral"], ctx, ledger)?;
2827                saw_type = true;
2828            }
2829            "ttl" => request_enum_string_control(&mut member.value, &["5m", "1h"], ctx, ledger)?,
2830            _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2831        }
2832    }
2833    if !saw_type {
2834        return Err(CodecErrorCode::UnsupportedRequestSurface);
2835    }
2836    Ok(())
2837}
2838
2839fn validate_cache_control_probe(
2840    node: &JsonNode,
2841    ctx: &mut RequestTransformContext<'_>,
2842) -> Result<(), CodecErrorCode> {
2843    let JsonKind::Object(members) = &node.kind else {
2844        return Err(CodecErrorCode::SignedSurfaceMalformed);
2845    };
2846    let mut saw_type = false;
2847    for member in members {
2848        let value = string_value(&member.value)?;
2849        let valid = match member.key.value.as_str() {
2850            "type" => {
2851                saw_type = true;
2852                value == "ephemeral"
2853            }
2854            "ttl" => matches!(value, "5m" | "1h"),
2855            _ => false,
2856        };
2857        if !valid {
2858            return Err(CodecErrorCode::SignedSurfaceMalformed);
2859        }
2860        guard_request_mutable_text(value, ctx)?;
2861        ctx.validate_token_shapes(value)?;
2862        if ctx.probe_without_prefix_cache_write(value)? != value {
2863            return Err(CodecErrorCode::SignedMutationRequired);
2864        }
2865    }
2866    if saw_type {
2867        Ok(())
2868    } else {
2869        Err(CodecErrorCode::SignedSurfaceMalformed)
2870    }
2871}
2872
2873fn transform_thinking_control(
2874    node: &mut JsonNode,
2875    ctx: &mut RequestTransformContext<'_>,
2876    ledger: &mut CoverageLedger,
2877) -> Result<(), CodecErrorCode> {
2878    let thinking_type = object_string(node, "type")?.to_owned();
2879    if !matches!(thinking_type.as_str(), "enabled" | "disabled") {
2880        return Err(CodecErrorCode::UnsupportedRequestSurface);
2881    }
2882    ledger.mark(node.occurrence)?;
2883    let JsonKind::Object(members) = &mut node.kind else {
2884        return Err(CodecErrorCode::UnsupportedRequestSurface);
2885    };
2886    let mut saw_type = false;
2887    let mut saw_budget = false;
2888    for member in members {
2889        ledger.mark(member.key_occurrence)?;
2890        match member.key.value.as_str() {
2891            "type" => {
2892                request_enum_string_control(
2893                    &mut member.value,
2894                    &[thinking_type.as_str()],
2895                    ctx,
2896                    ledger,
2897                )?;
2898                saw_type = true;
2899            }
2900            "budget_tokens" if thinking_type == "enabled" => {
2901                request_integer_control(&member.value, ledger, true)?;
2902                saw_budget = true;
2903            }
2904            _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2905        }
2906    }
2907    if saw_type && (thinking_type == "disabled" || saw_budget) {
2908        Ok(())
2909    } else {
2910        Err(CodecErrorCode::UnsupportedRequestSurface)
2911    }
2912}
2913
2914fn transform_tool_choice_control(
2915    node: &mut JsonNode,
2916    ctx: &mut RequestTransformContext<'_>,
2917    ledger: &mut CoverageLedger,
2918) -> Result<(), CodecErrorCode> {
2919    let choice_type = object_string(node, "type")?.to_owned();
2920    if !matches!(choice_type.as_str(), "auto" | "any" | "tool" | "none") {
2921        return Err(CodecErrorCode::UnsupportedRequestSurface);
2922    }
2923    ledger.mark(node.occurrence)?;
2924    let JsonKind::Object(members) = &mut node.kind else {
2925        return Err(CodecErrorCode::UnsupportedRequestSurface);
2926    };
2927    let mut saw_type = false;
2928    let mut saw_name = false;
2929    for member in members {
2930        ledger.mark(member.key_occurrence)?;
2931        match member.key.value.as_str() {
2932            "type" => {
2933                request_enum_string_control(
2934                    &mut member.value,
2935                    &[choice_type.as_str()],
2936                    ctx,
2937                    ledger,
2938                )?;
2939                saw_type = true;
2940            }
2941            "name" if choice_type == "tool" => {
2942                request_nonempty_string_control(&mut member.value, ctx, ledger)?;
2943                saw_name = true;
2944            }
2945            "disable_parallel_tool_use" => request_bool_control(&member.value, ledger)?,
2946            _ => return Err(CodecErrorCode::UnsupportedRequestSurface),
2947        }
2948    }
2949    if saw_type && (choice_type != "tool" || saw_name) {
2950        Ok(())
2951    } else {
2952        Err(CodecErrorCode::UnsupportedRequestSurface)
2953    }
2954}
2955
2956fn transform_schema_type(
2957    node: &mut JsonNode,
2958    ctx: &mut RequestTransformContext<'_>,
2959    ledger: &mut CoverageLedger,
2960) -> Result<(), CodecErrorCode> {
2961    const TYPES: &[&str] = &[
2962        "object", "array", "string", "number", "integer", "boolean", "null",
2963    ];
2964    match &mut node.kind {
2965        JsonKind::String(_) => request_enum_string_control(node, TYPES, ctx, ledger),
2966        JsonKind::Array(values) => {
2967            ledger.mark(node.occurrence)?;
2968            if values.is_empty() {
2969                return Err(CodecErrorCode::UnsupportedRequestSurface);
2970            }
2971            for value in values {
2972                request_enum_string_control(value, TYPES, ctx, ledger)?;
2973            }
2974            Ok(())
2975        }
2976        _ => Err(CodecErrorCode::UnsupportedRequestSurface),
2977    }
2978}
2979
2980fn transform_additional_properties(
2981    node: &mut JsonNode,
2982    ctx: &mut RequestTransformContext<'_>,
2983    ledger: &mut CoverageLedger,
2984) -> Result<(), CodecErrorCode> {
2985    if matches!(&node.kind, JsonKind::Bool(_)) {
2986        request_bool_control(node, ledger)
2987    } else if matches!(&node.kind, JsonKind::Object(_)) {
2988        transform_request_schema(node, ctx, ledger)
2989    } else {
2990        Err(CodecErrorCode::UnsupportedRequestSurface)
2991    }
2992}
2993
2994fn transform_schema_list(
2995    node: &mut JsonNode,
2996    ctx: &mut RequestTransformContext<'_>,
2997    ledger: &mut CoverageLedger,
2998) -> Result<(), CodecErrorCode> {
2999    ledger.mark(node.occurrence)?;
3000    let JsonKind::Array(values) = &mut node.kind else {
3001        return Err(CodecErrorCode::UnsupportedRequestSurface);
3002    };
3003    if values.is_empty() {
3004        return Err(CodecErrorCode::UnsupportedRequestSurface);
3005    }
3006    for value in values {
3007        transform_request_schema(value, ctx, ledger)?;
3008    }
3009    Ok(())
3010}
3011
3012fn transform_schema_literal(
3013    node: &mut JsonNode,
3014    ctx: &mut RequestTransformContext<'_>,
3015    ledger: &mut CoverageLedger,
3016) -> Result<(), CodecErrorCode> {
3017    match &node.kind {
3018        JsonKind::String(_) => request_string_control(node, ctx, ledger),
3019        JsonKind::Number(_) => request_number_literal_control(node, ctx, ledger),
3020        JsonKind::Bool(_) | JsonKind::Null => ledger.mark(node.occurrence),
3021        JsonKind::Object(_) | JsonKind::Array(_) => Err(CodecErrorCode::UnsupportedRequestSurface),
3022    }
3023}
3024
3025fn transform_schema_enum(
3026    node: &mut JsonNode,
3027    ctx: &mut RequestTransformContext<'_>,
3028    ledger: &mut CoverageLedger,
3029) -> Result<(), CodecErrorCode> {
3030    ledger.mark(node.occurrence)?;
3031    let JsonKind::Array(values) = &mut node.kind else {
3032        return Err(CodecErrorCode::UnsupportedRequestSurface);
3033    };
3034    if values.is_empty() {
3035        return Err(CodecErrorCode::UnsupportedRequestSurface);
3036    }
3037    for value in values {
3038        transform_schema_literal(value, ctx, ledger)?;
3039    }
3040    Ok(())
3041}
3042
3043fn request_number_control(
3044    node: &JsonNode,
3045    ledger: &mut CoverageLedger,
3046) -> Result<(), CodecErrorCode> {
3047    ledger.mark(node.occurrence)?;
3048    if matches!(node.kind, JsonKind::Number(_)) {
3049        Ok(())
3050    } else {
3051        Err(CodecErrorCode::UnsupportedRequestSurface)
3052    }
3053}
3054
3055/// Numeric schema-literal control: the numeric analogue of `request_string_control`
3056/// for `const` / `enum` members / `minimum` / `maximum` inside `tools[].input_schema`.
3057///
3058/// Marks coverage and shape-checks the node via `request_number_control`, then probes
3059/// the raw digit text through detection and fails closed if it would be tokenized.
3060/// Without this, an N-only (all-digit) recognizer never sees a numeric schema literal
3061/// and a real order/customer ID reaches the provider un-tokenized (audit finding 1).
3062fn request_number_literal_control(
3063    node: &JsonNode,
3064    ctx: &mut RequestTransformContext<'_>,
3065    ledger: &mut CoverageLedger,
3066) -> Result<(), CodecErrorCode> {
3067    request_number_control(node, ledger)?;
3068    let JsonKind::Number(raw) = &node.kind else {
3069        return Err(CodecErrorCode::UnsupportedRequestSurface);
3070    };
3071    if ctx.probe_without_prefix_cache_write(raw)? == *raw {
3072        Ok(())
3073    } else {
3074        Err(CodecErrorCode::ControlWouldMutate)
3075    }
3076}
3077
3078fn request_integer_control(
3079    node: &JsonNode,
3080    ledger: &mut CoverageLedger,
3081    nonzero: bool,
3082) -> Result<(), CodecErrorCode> {
3083    ledger.mark(node.occurrence)?;
3084    let JsonKind::Number(raw) = &node.kind else {
3085        return Err(CodecErrorCode::UnsupportedRequestSurface);
3086    };
3087    if raw.starts_with('-') || raw.contains(['.', 'e', 'E']) {
3088        return Err(CodecErrorCode::UnsupportedRequestSurface);
3089    }
3090    let value = raw
3091        .parse::<u64>()
3092        .map_err(|_| CodecErrorCode::UnsupportedRequestSurface)?;
3093    if nonzero && value == 0 {
3094        return Err(CodecErrorCode::UnsupportedRequestSurface);
3095    }
3096    Ok(())
3097}
3098
3099fn request_unit_interval_control(
3100    node: &JsonNode,
3101    ledger: &mut CoverageLedger,
3102) -> Result<(), CodecErrorCode> {
3103    ledger.mark(node.occurrence)?;
3104    let JsonKind::Number(raw) = &node.kind else {
3105        return Err(CodecErrorCode::UnsupportedRequestSurface);
3106    };
3107    if raw.starts_with('-') {
3108        return Err(CodecErrorCode::UnsupportedRequestSurface);
3109    }
3110    let value = raw
3111        .parse::<f64>()
3112        .map_err(|_| CodecErrorCode::UnsupportedRequestSurface)?;
3113    if value.is_finite() && (0.0..=1.0).contains(&value) {
3114        Ok(())
3115    } else {
3116        Err(CodecErrorCode::UnsupportedRequestSurface)
3117    }
3118}
3119
3120fn request_bool_control(
3121    node: &JsonNode,
3122    ledger: &mut CoverageLedger,
3123) -> Result<(), CodecErrorCode> {
3124    ledger.mark(node.occurrence)?;
3125    if matches!(node.kind, JsonKind::Bool(_)) {
3126        Ok(())
3127    } else {
3128        Err(CodecErrorCode::UnsupportedRequestSurface)
3129    }
3130}
3131
3132fn guard_mutable_text(value: &str) -> Result<(), CodecErrorCode> {
3133    let mut inspected = value;
3134    let mut wrapper_depth = 0usize;
3135    while let Some(inner) = inspected
3136        .strip_prefix('<')
3137        .and_then(|inner| inner.strip_suffix('>'))
3138    {
3139        wrapper_depth += 1;
3140        if wrapper_depth > MAX_ANGLE_WRAPPER_DEPTH {
3141            return Err(CodecErrorCode::OpaqueMediaUninspected);
3142        }
3143        inspected = inner;
3144    }
3145    let lower = inspected.to_ascii_lowercase();
3146    if inspected.chars().any(|character| {
3147        (character.is_control() && !matches!(character, '\n' | '\r' | '\t'))
3148            || matches!(
3149                character,
3150                '\u{061c}'
3151                    | '\u{200e}'
3152                    | '\u{200f}'
3153                    | '\u{202a}'..='\u{202e}'
3154                    | '\u{2066}'..='\u{2069}'
3155            )
3156    }) || find_carrier_scheme(&lower).is_some()
3157        || inspected.as_bytes().windows(3).any(|window| {
3158            window[0] == b'%' && hex_value(window[1]).is_some() && hex_value(window[2]).is_some()
3159        })
3160        || (inspected.len() >= 64
3161            && (inspected.bytes().all(|byte| byte.is_ascii_hexdigit())
3162                || inspected.bytes().all(|byte| {
3163                    byte.is_ascii_alphanumeric() || matches!(byte, b'+' | b'/' | b'=' | b'-' | b'_')
3164                })))
3165    {
3166        return Err(CodecErrorCode::OpaqueMediaUninspected);
3167    }
3168    Ok(())
3169}
3170
3171fn guard_request_mutable_text(
3172    value: &str,
3173    ctx: &mut RequestTransformContext<'_>,
3174) -> Result<(), CodecErrorCode> {
3175    let result = guard_mutable_text(value);
3176    if result == Err(CodecErrorCode::OpaqueMediaUninspected) {
3177        let lower = value.to_ascii_lowercase();
3178        if let Some((scheme, byte_offset, byte_length)) = find_carrier_scheme(&lower) {
3179            ctx.record_opaque_carrier(scheme, byte_offset, byte_length);
3180        }
3181    }
3182    result
3183}
3184
3185fn find_carrier_scheme(value: &str) -> Option<(OpaqueCarrierScheme, usize, usize)> {
3186    value.char_indices().find_map(|(index, _)| {
3187        let candidate = &value[index..];
3188        let (scheme, matched) = [
3189            (OpaqueCarrierScheme::Data, "data:"),
3190            (OpaqueCarrierScheme::File, "file:"),
3191            (OpaqueCarrierScheme::Http, "http://"),
3192            (OpaqueCarrierScheme::Https, "https://"),
3193        ]
3194        .into_iter()
3195        .find(|(_, literal)| candidate.starts_with(literal))?;
3196        let boundary = index == 0
3197            || !value[..index].chars().next_back().is_some_and(|character| {
3198                character.is_ascii_alphanumeric() || matches!(character, '_' | '-')
3199            });
3200        boundary.then_some((scheme, index, matched.len()))
3201    })
3202}
3203
3204fn transform_response_root(
3205    node: &mut JsonNode,
3206    input: &[u8],
3207    ctx: &mut ResponseTransformContext<'_>,
3208    ledger: &mut CoverageLedger,
3209) -> Result<(), CodecErrorCode> {
3210    ledger.mark(node.occurrence)?;
3211    let JsonKind::Object(members) = &mut node.kind else {
3212        return Err(CodecErrorCode::UnsupportedResponseSurface);
3213    };
3214    let mut saw_id = false;
3215    let mut saw_type = false;
3216    let mut saw_role = false;
3217    let mut saw_model = false;
3218    let mut saw_content = false;
3219    let mut saw_stop_reason = false;
3220    let mut saw_stop_sequence = false;
3221    let mut saw_usage = false;
3222    for member in members {
3223        ledger.mark(member.key_occurrence)?;
3224        match member.key.value.as_str() {
3225            "id" => {
3226                response_nonempty_string_control(&mut member.value, ctx, ledger)?;
3227                saw_id = true;
3228            }
3229            "type" => {
3230                response_enum_string_control(&mut member.value, &["message"], ctx, ledger)?;
3231                saw_type = true;
3232            }
3233            "role" => {
3234                response_enum_string_control(&mut member.value, &["assistant"], ctx, ledger)?;
3235                saw_role = true;
3236            }
3237            "model" => {
3238                response_nonempty_string_control(&mut member.value, ctx, ledger)?;
3239                saw_model = true;
3240            }
3241            "stop_reason" => {
3242                response_enum_string_or_null(
3243                    &mut member.value,
3244                    &[
3245                        "end_turn",
3246                        "max_tokens",
3247                        "stop_sequence",
3248                        "tool_use",
3249                        "pause_turn",
3250                        "refusal",
3251                        "model_context_window_exceeded",
3252                    ],
3253                    ctx,
3254                    ledger,
3255                )?;
3256                saw_stop_reason = true;
3257            }
3258            "stop_sequence" => {
3259                response_string_or_null(&mut member.value, ctx, ledger)?;
3260                saw_stop_sequence = true;
3261            }
3262            "content" => {
3263                transform_response_content(&mut member.value, input, ctx, ledger)?;
3264                saw_content = true;
3265            }
3266            "usage" => {
3267                response_usage(&mut member.value, ledger, true)?;
3268                saw_usage = true;
3269            }
3270            _ => return Err(CodecErrorCode::UnsupportedResponseSurface),
3271        }
3272    }
3273    if saw_id
3274        && saw_type
3275        && saw_role
3276        && saw_model
3277        && saw_content
3278        && saw_stop_reason
3279        && saw_stop_sequence
3280        && saw_usage
3281    {
3282        Ok(())
3283    } else {
3284        Err(CodecErrorCode::UnsupportedResponseSurface)
3285    }
3286}
3287
3288fn transform_response_content(
3289    node: &mut JsonNode,
3290    input: &[u8],
3291    ctx: &mut ResponseTransformContext<'_>,
3292    ledger: &mut CoverageLedger,
3293) -> Result<(), CodecErrorCode> {
3294    ledger.mark(node.occurrence)?;
3295    let JsonKind::Array(blocks) = &mut node.kind else {
3296        return Err(CodecErrorCode::UnsupportedResponseSurface);
3297    };
3298    for block in blocks {
3299        transform_response_block(block, input, ctx, ledger)?;
3300    }
3301    Ok(())
3302}
3303
3304fn transform_response_block(
3305    node: &mut JsonNode,
3306    input: &[u8],
3307    ctx: &mut ResponseTransformContext<'_>,
3308    ledger: &mut CoverageLedger,
3309) -> Result<(), CodecErrorCode> {
3310    let block_type = object_string(node, "type")?.to_owned();
3311    if !matches!(
3312        block_type.as_str(),
3313        "text"
3314            | "tool_use"
3315            | "tool_result"
3316            | "search_result"
3317            | "document"
3318            | "thinking"
3319            | "redacted_thinking"
3320    ) {
3321        return Err(CodecErrorCode::UnsupportedResponseSurface);
3322    }
3323    if matches!(block_type.as_str(), "thinking" | "redacted_thinking") {
3324        validate_signed_response_block(node, input, ctx, ledger, &block_type)?;
3325        node.raw_preserve = true;
3326        return Ok(());
3327    }
3328    ledger.mark(node.occurrence)?;
3329    let JsonKind::Object(members) = &mut node.kind else {
3330        return Err(CodecErrorCode::UnsupportedResponseSurface);
3331    };
3332    let mut saw_type = false;
3333    let mut saw_text = false;
3334    let mut saw_id = false;
3335    let mut saw_name = false;
3336    let mut saw_input = false;
3337    let mut saw_tool_use_id = false;
3338    let mut saw_content = false;
3339    let mut saw_user_payload = false;
3340    for member in members {
3341        ledger.mark(member.key_occurrence)?;
3342        match (block_type.as_str(), member.key.value.as_str()) {
3343            (_, "type") => {
3344                response_enum_string_control(
3345                    &mut member.value,
3346                    &[block_type.as_str()],
3347                    ctx,
3348                    ledger,
3349                )?;
3350                saw_type = true;
3351            }
3352            ("tool_use", "id") => {
3353                response_nonempty_string_control(&mut member.value, ctx, ledger)?;
3354                saw_id = true;
3355            }
3356            ("tool_use", "name") => {
3357                response_nonempty_string_control(&mut member.value, ctx, ledger)?;
3358                saw_name = true;
3359            }
3360            ("text", "text") => {
3361                transform_response_string(&mut member.value, ctx, ledger)?;
3362                saw_text = true;
3363            }
3364            ("text", "citations") => transform_response_citations(&mut member.value, ctx, ledger)?,
3365            ("tool_use", "input") => {
3366                transform_response_mutable(&mut member.value, ctx, ledger)?;
3367                saw_input = true;
3368            }
3369            ("tool_result", "content") => {
3370                transform_response_mutable(&mut member.value, ctx, ledger)?;
3371                saw_content = true;
3372            }
3373            ("tool_result", "tool_use_id") => {
3374                response_nonempty_string_control(&mut member.value, ctx, ledger)?;
3375                saw_tool_use_id = true;
3376            }
3377            ("tool_result", "is_error") => response_bool_or_null(&member.value, ledger)?,
3378            ("search_result" | "document", "title" | "context" | "text" | "content") => {
3379                transform_response_mutable(&mut member.value, ctx, ledger)?;
3380                saw_user_payload = true;
3381            }
3382            ("search_result" | "document", "source" | "id") => {
3383                response_string_control(&mut member.value, ctx, ledger)?
3384            }
3385            _ => return Err(CodecErrorCode::UnsupportedResponseSurface),
3386        }
3387    }
3388    let valid = match block_type.as_str() {
3389        "text" => saw_text,
3390        "tool_use" => saw_id && saw_name && saw_input,
3391        "tool_result" => saw_tool_use_id && saw_content,
3392        "search_result" | "document" => saw_user_payload,
3393        _ => false,
3394    };
3395    if saw_type && valid {
3396        Ok(())
3397    } else {
3398        Err(CodecErrorCode::UnsupportedResponseSurface)
3399    }
3400}
3401
3402fn validate_signed_response_block(
3403    node: &JsonNode,
3404    input: &[u8],
3405    ctx: &mut ResponseTransformContext<'_>,
3406    ledger: &mut CoverageLedger,
3407    block_type: &str,
3408) -> Result<(), CodecErrorCode> {
3409    account_subtree(node, ledger)?;
3410    let JsonKind::Object(members) = &node.kind else {
3411        return Err(CodecErrorCode::SignedSurfaceMalformed);
3412    };
3413    let mut has_payload = false;
3414    let mut has_type = false;
3415    let mut has_signature = false;
3416    for member in members {
3417        match member.key.value.as_str() {
3418            "type" if string_value(&member.value)? == block_type => {
3419                has_type = true;
3420            }
3421            "signature" => {
3422                let _ = ctx.restore(string_value(&member.value)?)?;
3423                has_signature = true;
3424            }
3425            "thinking" if block_type == "thinking" => {
3426                let text = string_value(&member.value)?;
3427                guard_mutable_text_response(text)?;
3428                let _ = ctx.restore(text)?;
3429                ctx.validate(text, &[])?;
3430                has_payload = true;
3431            }
3432            "data" if block_type == "redacted_thinking" => {
3433                let data = string_value(&member.value)?;
3434                let _ = ctx.restore(data)?;
3435                has_payload = true;
3436            }
3437            _ => return Err(CodecErrorCode::SignedSurfaceMalformed),
3438        }
3439    }
3440    if !has_type
3441        || !has_payload
3442        || (block_type == "thinking" && !has_signature)
3443        || node.span.end > input.len()
3444    {
3445        return Err(CodecErrorCode::SignedSurfaceMalformed);
3446    }
3447    Ok(())
3448}
3449
3450fn transform_response_mutable(
3451    node: &mut JsonNode,
3452    ctx: &mut ResponseTransformContext<'_>,
3453    ledger: &mut CoverageLedger,
3454) -> Result<(), CodecErrorCode> {
3455    match &mut node.kind {
3456        JsonKind::Object(members) => {
3457            ledger.mark(node.occurrence)?;
3458            let mut transformed_keys = HashSet::new();
3459            for member in members {
3460                ledger.mark(member.key_occurrence)?;
3461                restore_json_string(&mut member.key, ctx)?;
3462                if !transformed_keys.insert(member.key.value.clone()) {
3463                    return Err(CodecErrorCode::TransformedKeyCollision);
3464                }
3465                transform_response_mutable(&mut member.value, ctx, ledger)?;
3466            }
3467            Ok(())
3468        }
3469        JsonKind::Array(values) => {
3470            ledger.mark(node.occurrence)?;
3471            for value in values.iter_mut() {
3472                transform_response_mutable(value, ctx, ledger)?;
3473            }
3474            let mut logical = String::new();
3475            let mut authorized = Vec::<Range<usize>>::new();
3476            for value in values {
3477                if let JsonKind::String(value) = &value.kind {
3478                    let base = logical.len();
3479                    logical.push_str(&value.value);
3480                    authorized.extend(
3481                        value
3482                            .authorized
3483                            .iter()
3484                            .map(|range| base + range.start..base + range.end),
3485                    );
3486                }
3487            }
3488            guard_mutable_text_response(&logical)?;
3489            ctx.validate(&logical, &authorized)?;
3490            Ok(())
3491        }
3492        JsonKind::String(_) => transform_response_string(node, ctx, ledger),
3493        JsonKind::Bool(_) | JsonKind::Null => ledger.mark(node.occurrence),
3494        JsonKind::Number(_) => {
3495            ledger.mark(node.occurrence)?;
3496            Err(CodecErrorCode::ProviderOriginNumeric)
3497        }
3498    }
3499}
3500
3501fn transform_response_string(
3502    node: &mut JsonNode,
3503    ctx: &mut ResponseTransformContext<'_>,
3504    ledger: &mut CoverageLedger,
3505) -> Result<(), CodecErrorCode> {
3506    ledger.mark(node.occurrence)?;
3507    let JsonKind::String(value) = &mut node.kind else {
3508        return Err(CodecErrorCode::UnsupportedResponseSurface);
3509    };
3510    restore_json_string(value, ctx)
3511}
3512
3513fn restore_json_string(
3514    value: &mut JsonString,
3515    ctx: &mut ResponseTransformContext<'_>,
3516) -> Result<(), CodecErrorCode> {
3517    guard_mutable_text_response(&value.value)?;
3518    let restored = ctx.restore(&value.value)?;
3519    ctx.validate(&restored.text, &restored.authorized_output_ranges)?;
3520    value.value = restored.text;
3521    value.authorized = restored.authorized_output_ranges;
3522    Ok(())
3523}
3524
3525fn guard_mutable_text_response(value: &str) -> Result<(), CodecErrorCode> {
3526    guard_mutable_text(value).map_err(|_| CodecErrorCode::ProviderOriginPii)
3527}
3528
3529fn transform_response_citations(
3530    node: &mut JsonNode,
3531    ctx: &mut ResponseTransformContext<'_>,
3532    ledger: &mut CoverageLedger,
3533) -> Result<(), CodecErrorCode> {
3534    ledger.mark(node.occurrence)?;
3535    let JsonKind::Array(citations) = &mut node.kind else {
3536        return Err(CodecErrorCode::UnsupportedResponseSurface);
3537    };
3538    for citation in citations {
3539        transform_response_citation(citation, ctx, ledger)?;
3540    }
3541    Ok(())
3542}
3543
3544fn transform_response_citation(
3545    citation: &mut JsonNode,
3546    ctx: &mut ResponseTransformContext<'_>,
3547    ledger: &mut CoverageLedger,
3548) -> Result<(), CodecErrorCode> {
3549    ledger.mark(citation.occurrence)?;
3550    let JsonKind::Object(members) = &mut citation.kind else {
3551        return Err(CodecErrorCode::UnsupportedResponseSurface);
3552    };
3553    for member in members {
3554        ledger.mark(member.key_occurrence)?;
3555        match member.key.value.as_str() {
3556            "cited_text" | "document_title" | "title" => {
3557                transform_response_string(&mut member.value, ctx, ledger)?
3558            }
3559            "type" | "url" | "source" => response_string_control(&mut member.value, ctx, ledger)?,
3560            "document_index"
3561            | "start_char_index"
3562            | "end_char_index"
3563            | "start_page_number"
3564            | "end_page_number"
3565            | "start_block_index"
3566            | "end_block_index"
3567            | "search_result_index" => response_numeric_control(&member.value, ledger)?,
3568            _ => return Err(CodecErrorCode::UnsupportedResponseSurface),
3569        }
3570    }
3571    Ok(())
3572}
3573
3574fn response_string_control(
3575    node: &mut JsonNode,
3576    ctx: &mut ResponseTransformContext<'_>,
3577    ledger: &mut CoverageLedger,
3578) -> Result<(), CodecErrorCode> {
3579    ledger.mark(node.occurrence)?;
3580    let JsonKind::String(value) = &node.kind else {
3581        return Err(CodecErrorCode::UnsupportedResponseSurface);
3582    };
3583    guard_mutable_text_response(&value.value)?;
3584    ctx.validate(&value.value, &[])
3585}
3586
3587fn response_nonempty_string_control(
3588    node: &mut JsonNode,
3589    ctx: &mut ResponseTransformContext<'_>,
3590    ledger: &mut CoverageLedger,
3591) -> Result<(), CodecErrorCode> {
3592    if string_value(node)?.is_empty() {
3593        return Err(CodecErrorCode::UnsupportedResponseSurface);
3594    }
3595    response_string_control(node, ctx, ledger)
3596}
3597
3598fn response_enum_string_control(
3599    node: &mut JsonNode,
3600    allowed: &[&str],
3601    ctx: &mut ResponseTransformContext<'_>,
3602    ledger: &mut CoverageLedger,
3603) -> Result<(), CodecErrorCode> {
3604    if !allowed.contains(&string_value(node)?) {
3605        return Err(CodecErrorCode::UnsupportedResponseSurface);
3606    }
3607    response_string_control(node, ctx, ledger)
3608}
3609
3610fn response_string_or_null(
3611    node: &mut JsonNode,
3612    ctx: &mut ResponseTransformContext<'_>,
3613    ledger: &mut CoverageLedger,
3614) -> Result<(), CodecErrorCode> {
3615    match &node.kind {
3616        JsonKind::String(_) => response_string_control(node, ctx, ledger),
3617        JsonKind::Null => ledger.mark(node.occurrence),
3618        _ => Err(CodecErrorCode::UnsupportedResponseSurface),
3619    }
3620}
3621
3622fn response_enum_string_or_null(
3623    node: &mut JsonNode,
3624    allowed: &[&str],
3625    ctx: &mut ResponseTransformContext<'_>,
3626    ledger: &mut CoverageLedger,
3627) -> Result<(), CodecErrorCode> {
3628    match &node.kind {
3629        JsonKind::String(_) => response_enum_string_control(node, allowed, ctx, ledger),
3630        JsonKind::Null => ledger.mark(node.occurrence),
3631        _ => Err(CodecErrorCode::UnsupportedResponseSurface),
3632    }
3633}
3634
3635fn response_numeric_control(
3636    node: &JsonNode,
3637    ledger: &mut CoverageLedger,
3638) -> Result<(), CodecErrorCode> {
3639    ledger.mark(node.occurrence)?;
3640    let JsonKind::Number(raw) = &node.kind else {
3641        return Err(CodecErrorCode::UnsupportedResponseSurface);
3642    };
3643    if raw.starts_with('-') || raw.contains(['.', 'e', 'E']) {
3644        return Err(CodecErrorCode::UnsupportedResponseSurface);
3645    }
3646    raw.parse::<u64>()
3647        .map(|_| ())
3648        .map_err(|_| CodecErrorCode::UnsupportedResponseSurface)
3649}
3650
3651fn response_usage(
3652    node: &mut JsonNode,
3653    ledger: &mut CoverageLedger,
3654    require_input_tokens: bool,
3655) -> Result<(), CodecErrorCode> {
3656    ledger.mark(node.occurrence)?;
3657    let JsonKind::Object(members) = &mut node.kind else {
3658        return Err(CodecErrorCode::UnsupportedResponseSurface);
3659    };
3660    let mut saw_input_tokens = false;
3661    let mut saw_output_tokens = false;
3662    for member in members {
3663        ledger.mark(member.key_occurrence)?;
3664        match member.key.value.as_str() {
3665            "input_tokens" => {
3666                response_numeric_control(&member.value, ledger)?;
3667                saw_input_tokens = true;
3668            }
3669            "output_tokens" => {
3670                response_numeric_control(&member.value, ledger)?;
3671                saw_output_tokens = true;
3672            }
3673            "cache_creation_input_tokens" | "cache_read_input_tokens" => {
3674                response_numeric_control(&member.value, ledger)?
3675            }
3676            _ => return Err(CodecErrorCode::UnsupportedResponseSurface),
3677        }
3678    }
3679    if (!require_input_tokens || saw_input_tokens) && saw_output_tokens {
3680        Ok(())
3681    } else {
3682        Err(CodecErrorCode::UnsupportedResponseSurface)
3683    }
3684}
3685
3686fn response_bool_or_null(
3687    node: &JsonNode,
3688    ledger: &mut CoverageLedger,
3689) -> Result<(), CodecErrorCode> {
3690    ledger.mark(node.occurrence)?;
3691    if matches!(&node.kind, JsonKind::Bool(_) | JsonKind::Null) {
3692        Ok(())
3693    } else {
3694        Err(CodecErrorCode::UnsupportedResponseSurface)
3695    }
3696}
3697
3698fn object_string<'a>(node: &'a JsonNode, key: &str) -> Result<&'a str, CodecErrorCode> {
3699    let JsonKind::Object(members) = &node.kind else {
3700        return Err(CodecErrorCode::InvalidJson);
3701    };
3702    let member = members
3703        .iter()
3704        .find(|member| member.key.value == key)
3705        .ok_or(CodecErrorCode::InvalidJson)?;
3706    string_value(&member.value)
3707}
3708
3709fn string_value(node: &JsonNode) -> Result<&str, CodecErrorCode> {
3710    let JsonKind::String(value) = &node.kind else {
3711        return Err(CodecErrorCode::InvalidJson);
3712    };
3713    Ok(&value.value)
3714}
3715
3716fn write_document(
3717    document: &JsonDocument,
3718    input: &[u8],
3719) -> Result<(Vec<u8>, OutputProvenance), CodecErrorCode> {
3720    let mut output = Vec::new();
3721    let mut provenance = OutputProvenance::default();
3722    write_json_node(&document.root, input, &mut output, &mut provenance)?;
3723    provenance.set_occurrence_count(document.occurrence_count);
3724    Ok((output, provenance))
3725}
3726
3727fn write_json_node(
3728    node: &JsonNode,
3729    input: &[u8],
3730    output: &mut Vec<u8>,
3731    provenance: &mut OutputProvenance,
3732) -> Result<(), CodecErrorCode> {
3733    if node.raw_preserve {
3734        let raw = input
3735            .get(node.span.clone())
3736            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
3737        let start = output.len();
3738        output.extend_from_slice(raw);
3739        provenance.record_signed(start..output.len());
3740        return Ok(());
3741    }
3742    match &node.kind {
3743        JsonKind::Object(members) => {
3744            output.push(b'{');
3745            for (index, member) in members.iter().enumerate() {
3746                if index > 0 {
3747                    output.push(b',');
3748                }
3749                write_json_string(&member.key, output, provenance);
3750                output.push(b':');
3751                write_json_node(&member.value, input, output, provenance)?;
3752            }
3753            output.push(b'}');
3754        }
3755        JsonKind::Array(values) => {
3756            output.push(b'[');
3757            for (index, value) in values.iter().enumerate() {
3758                if index > 0 {
3759                    output.push(b',');
3760                }
3761                write_json_node(value, input, output, provenance)?;
3762            }
3763            output.push(b']');
3764        }
3765        JsonKind::String(value) => write_json_string(value, output, provenance),
3766        JsonKind::Number(raw) => output.extend_from_slice(raw.as_bytes()),
3767        JsonKind::Bool(true) => output.extend_from_slice(b"true"),
3768        JsonKind::Bool(false) => output.extend_from_slice(b"false"),
3769        JsonKind::Null => output.extend_from_slice(b"null"),
3770    }
3771    Ok(())
3772}
3773
3774fn write_json_string(value: &JsonString, output: &mut Vec<u8>, provenance: &mut OutputProvenance) {
3775    output.push(b'"');
3776    for (logical_start, character) in value.value.char_indices() {
3777        let logical_end = logical_start + character.len_utf8();
3778        let authorized = value
3779            .authorized
3780            .iter()
3781            .any(|range| range.start <= logical_start && range.end >= logical_end);
3782        let wire_start = output.len();
3783        match character {
3784            '"' => output.extend_from_slice(br#"\""#),
3785            '\\' => output.extend_from_slice(br#"\\"#),
3786            '\u{0008}' => output.extend_from_slice(br"\b"),
3787            '\u{000c}' => output.extend_from_slice(br"\f"),
3788            '\n' => output.extend_from_slice(br"\n"),
3789            '\r' => output.extend_from_slice(br"\r"),
3790            '\t' => output.extend_from_slice(br"\t"),
3791            character if character <= '\u{001f}' => {
3792                output.extend_from_slice(format!("\\u{:04x}", u32::from(character)).as_bytes());
3793            }
3794            character => {
3795                let mut bytes = [0u8; 4];
3796                output.extend_from_slice(character.encode_utf8(&mut bytes).as_bytes());
3797            }
3798        }
3799        if authorized {
3800            provenance.record_authorized(wire_start..output.len());
3801        }
3802    }
3803    output.push(b'"');
3804}
3805
3806fn json_semantically_equal(left: &JsonNode, right: &JsonNode) -> bool {
3807    match (&left.kind, &right.kind) {
3808        (JsonKind::Object(left_members), JsonKind::Object(right_members)) => {
3809            left_members.len() == right_members.len()
3810                && left_members.iter().zip(right_members).all(|(left, right)| {
3811                    left.key.value == right.key.value
3812                        && json_semantically_equal(&left.value, &right.value)
3813                })
3814        }
3815        (JsonKind::Array(left_values), JsonKind::Array(right_values)) => {
3816            left_values.len() == right_values.len()
3817                && left_values
3818                    .iter()
3819                    .zip(right_values)
3820                    .all(|(left, right)| json_semantically_equal(left, right))
3821        }
3822        (JsonKind::String(left), JsonKind::String(right)) => left.value == right.value,
3823        (JsonKind::Number(left), JsonKind::Number(right)) => left == right,
3824        (JsonKind::Bool(left), JsonKind::Bool(right)) => left == right,
3825        (JsonKind::Null, JsonKind::Null) => true,
3826        _ => false,
3827    }
3828}
3829
3830fn collect_signed_slices(node: &JsonNode, input: &[u8]) -> Result<Vec<Vec<u8>>, CodecErrorCode> {
3831    let mut slices = Vec::new();
3832    collect_signed_slices_into(node, input, &mut slices)?;
3833    Ok(slices)
3834}
3835
3836fn collect_signed_slices_into(
3837    node: &JsonNode,
3838    input: &[u8],
3839    slices: &mut Vec<Vec<u8>>,
3840) -> Result<(), CodecErrorCode> {
3841    if node.raw_preserve {
3842        slices.push(
3843            input
3844                .get(node.span.clone())
3845                .ok_or(CodecErrorCode::InternalCoverageFailure)?
3846                .to_vec(),
3847        );
3848        return Ok(());
3849    }
3850    match &node.kind {
3851        JsonKind::Object(members) => {
3852            for member in members {
3853                collect_signed_slices_into(&member.value, input, slices)?;
3854            }
3855        }
3856        JsonKind::Array(values) => {
3857            for value in values {
3858                collect_signed_slices_into(value, input, slices)?;
3859            }
3860        }
3861        JsonKind::String(_) | JsonKind::Number(_) | JsonKind::Bool(_) | JsonKind::Null => {}
3862    }
3863    Ok(())
3864}
3865
3866fn collect_authorized_wire_chunks(node: &JsonNode) -> Result<Vec<Vec<u8>>, CodecErrorCode> {
3867    let mut chunks = Vec::new();
3868    collect_authorized_wire_chunks_into(node, &mut chunks)?;
3869    Ok(chunks)
3870}
3871
3872fn collect_authorized_wire_chunks_into(
3873    node: &JsonNode,
3874    chunks: &mut Vec<Vec<u8>>,
3875) -> Result<(), CodecErrorCode> {
3876    if node.raw_preserve {
3877        return Ok(());
3878    }
3879    match &node.kind {
3880        JsonKind::Object(members) => {
3881            for member in members {
3882                collect_authorized_string_chunks(&member.key, chunks)?;
3883                collect_authorized_wire_chunks_into(&member.value, chunks)?;
3884            }
3885        }
3886        JsonKind::Array(values) => {
3887            for value in values {
3888                collect_authorized_wire_chunks_into(value, chunks)?;
3889            }
3890        }
3891        JsonKind::String(value) => collect_authorized_string_chunks(value, chunks)?,
3892        JsonKind::Number(_) | JsonKind::Bool(_) | JsonKind::Null => {}
3893    }
3894    Ok(())
3895}
3896
3897fn collect_authorized_string_chunks(
3898    value: &JsonString,
3899    chunks: &mut Vec<Vec<u8>>,
3900) -> Result<(), CodecErrorCode> {
3901    for range in &value.authorized {
3902        let logical = value
3903            .value
3904            .get(range.clone())
3905            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
3906        let mut encoded = Vec::new();
3907        write_json_string(
3908            &JsonString {
3909                value: logical.to_owned(),
3910                authorized: Vec::new(),
3911            },
3912            &mut encoded,
3913            &mut OutputProvenance::default(),
3914        );
3915        let content = encoded
3916            .get(1..encoded.len().saturating_sub(1))
3917            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
3918        chunks.push(content.to_vec());
3919    }
3920    Ok(())
3921}
3922
3923fn verify_final_wire_proof(
3924    output: &[u8],
3925    provenance: &OutputProvenance,
3926    expected_authorized: &[Vec<u8>],
3927    expected_signed: &[Vec<u8>],
3928) -> Result<(), CodecErrorCode> {
3929    verify_range_chunks(
3930        output,
3931        provenance.authorized_output_ranges(),
3932        expected_authorized,
3933    )?;
3934    verify_range_chunks(output, provenance.signed_opaque_ranges(), expected_signed)?;
3935    for authorized in provenance.authorized_output_ranges() {
3936        if provenance
3937            .signed_opaque_ranges()
3938            .iter()
3939            .any(|signed| authorized.start < signed.end && signed.start < authorized.end)
3940        {
3941            return Err(CodecErrorCode::InternalCoverageFailure);
3942        }
3943    }
3944    Ok(())
3945}
3946
3947fn verify_range_chunks(
3948    output: &[u8],
3949    ranges: &[Range<usize>],
3950    expected: &[Vec<u8>],
3951) -> Result<(), CodecErrorCode> {
3952    if ranges.len() != expected.len() {
3953        return Err(CodecErrorCode::InternalCoverageFailure);
3954    }
3955    let mut previous_end = 0usize;
3956    for (range, expected) in ranges.iter().zip(expected) {
3957        if range.start < previous_end
3958            || range.start >= range.end
3959            || range.end > output.len()
3960            || output.get(range.clone()) != Some(expected.as_slice())
3961        {
3962            return Err(CodecErrorCode::InternalCoverageFailure);
3963        }
3964        previous_end = range.end;
3965    }
3966    Ok(())
3967}
3968
3969struct SseDecoder {
3970    limits: CodecLimits,
3971    bytes: Vec<u8>,
3972}
3973
3974struct SseFrame {
3975    event: Option<String>,
3976    data: Vec<u8>,
3977    raw: Vec<u8>,
3978    comment: bool,
3979    inspection_fact: Option<SseInspectionFrameFactV1>,
3980}
3981
3982struct SseInspectionFrameFactV1 {
3983    event_kind: SseEventKindV1,
3984    delta_kind: ProjectionAvailabilityV1<SseDeltaKindV1>,
3985    content_block: ProjectionAvailabilityV1<ContentBlockIndexV1>,
3986}
3987
3988impl SseDecoder {
3989    fn new(limits: CodecLimits) -> Self {
3990        Self {
3991            limits,
3992            bytes: Vec::new(),
3993        }
3994    }
3995
3996    fn push(&mut self, chunk: &[u8]) -> Result<(), CodecError> {
3997        let next =
3998            self.bytes.len().checked_add(chunk.len()).ok_or_else(|| {
3999                codec_error(CodecErrorCode::BodyLimitExceeded, CodecPhase::SseDecode)
4000            })?;
4001        if next > self.limits.max_body_bytes() {
4002            return Err(codec_error(
4003                CodecErrorCode::BodyLimitExceeded,
4004                CodecPhase::SseDecode,
4005            ));
4006        }
4007        self.bytes.extend_from_slice(chunk);
4008        Ok(())
4009    }
4010
4011    fn input_len(&self) -> usize {
4012        self.bytes.len()
4013    }
4014
4015    fn finish(self) -> Result<Vec<SseFrame>, CodecError> {
4016        if self.bytes.starts_with(&[0xef, 0xbb, 0xbf]) || self.bytes.contains(&0) {
4017            return Err(codec_error(
4018                CodecErrorCode::InvalidSseFrame,
4019                CodecPhase::SseDecode,
4020            ));
4021        }
4022        std::str::from_utf8(&self.bytes)
4023            .map_err(|_| codec_error(CodecErrorCode::InvalidUtf8, CodecPhase::SseDecode))?;
4024        let lines = split_sse_lines(&self.bytes, self.limits)?;
4025        let mut frames = Vec::new();
4026        let mut event = None;
4027        let mut data_lines = Vec::<Vec<u8>>::new();
4028        let mut raw = Vec::new();
4029        let mut comment_only = false;
4030        for line in lines {
4031            if line.content.is_empty() {
4032                if comment_only && event.is_none() && data_lines.is_empty() {
4033                    raw.extend_from_slice(line.raw);
4034                    if raw.len() > self.limits.max_sse_frame_bytes() {
4035                        return Err(codec_error(
4036                            CodecErrorCode::SseFrameLimitExceeded,
4037                            CodecPhase::SseDecode,
4038                        ));
4039                    }
4040                    frames.push(SseFrame {
4041                        event: None,
4042                        data: Vec::new(),
4043                        raw: std::mem::take(&mut raw),
4044                        comment: true,
4045                        inspection_fact: None,
4046                    });
4047                } else if event.is_some() || !data_lines.is_empty() {
4048                    raw.extend_from_slice(line.raw);
4049                    if raw.len() > self.limits.max_sse_frame_bytes() {
4050                        return Err(codec_error(
4051                            CodecErrorCode::SseFrameLimitExceeded,
4052                            CodecPhase::SseDecode,
4053                        ));
4054                    }
4055                    let data_len = data_lines.iter().map(Vec::len).sum::<usize>()
4056                        + data_lines.len().saturating_sub(1);
4057                    if data_len > self.limits.max_sse_frame_bytes() {
4058                        return Err(codec_error(
4059                            CodecErrorCode::SseFrameLimitExceeded,
4060                            CodecPhase::SseDecode,
4061                        ));
4062                    }
4063                    let mut data = Vec::with_capacity(data_len);
4064                    for (index, value) in data_lines.drain(..).enumerate() {
4065                        if index > 0 {
4066                            data.push(b'\n');
4067                        }
4068                        data.extend_from_slice(&value);
4069                    }
4070                    frames.push(SseFrame {
4071                        event: event.take(),
4072                        data,
4073                        raw: std::mem::take(&mut raw),
4074                        comment: false,
4075                        inspection_fact: None,
4076                    });
4077                } else if !raw.is_empty() {
4078                    return Err(codec_error(
4079                        CodecErrorCode::InvalidSseFrame,
4080                        CodecPhase::SseDecode,
4081                    ));
4082                }
4083                comment_only = false;
4084                if frames.len() > self.limits.max_sse_events() {
4085                    return Err(codec_error(
4086                        CodecErrorCode::SseEventLimitExceeded,
4087                        CodecPhase::SseDecode,
4088                    ));
4089                }
4090                continue;
4091            }
4092            raw.extend_from_slice(line.raw);
4093            if raw.len() > self.limits.max_sse_frame_bytes() {
4094                return Err(codec_error(
4095                    CodecErrorCode::SseFrameLimitExceeded,
4096                    CodecPhase::SseDecode,
4097                ));
4098            }
4099            if line.content.starts_with(b":") {
4100                if event.is_some() || !data_lines.is_empty() || comment_only {
4101                    return Err(codec_error(
4102                        CodecErrorCode::InvalidSseFrame,
4103                        CodecPhase::SseDecode,
4104                    ));
4105                }
4106                comment_only = true;
4107                continue;
4108            }
4109            if comment_only {
4110                return Err(codec_error(
4111                    CodecErrorCode::InvalidSseFrame,
4112                    CodecPhase::SseDecode,
4113                ));
4114            }
4115            let colon = line
4116                .content
4117                .iter()
4118                .position(|byte| *byte == b':')
4119                .ok_or_else(|| {
4120                    codec_error(CodecErrorCode::InvalidSseField, CodecPhase::SseDecode)
4121                })?;
4122            let field = &line.content[..colon];
4123            let mut value = &line.content[colon + 1..];
4124            if value.first() == Some(&b' ') {
4125                value = &value[1..];
4126            }
4127            match field {
4128                b"event" => {
4129                    if event.is_some() || !data_lines.is_empty() {
4130                        return Err(codec_error(
4131                            CodecErrorCode::InvalidSseField,
4132                            CodecPhase::SseDecode,
4133                        ));
4134                    }
4135                    event = Some(
4136                        std::str::from_utf8(value)
4137                            .map_err(|_| {
4138                                codec_error(CodecErrorCode::InvalidUtf8, CodecPhase::SseDecode)
4139                            })?
4140                            .to_owned(),
4141                    );
4142                }
4143                b"data" => data_lines.push(value.to_vec()),
4144                _ => {
4145                    return Err(codec_error(
4146                        CodecErrorCode::InvalidSseField,
4147                        CodecPhase::SseDecode,
4148                    ));
4149                }
4150            }
4151        }
4152        if event.is_some() || !data_lines.is_empty() || comment_only || !raw.is_empty() {
4153            return Err(codec_error(
4154                CodecErrorCode::IncompleteSseStream,
4155                CodecPhase::SseDecode,
4156            ));
4157        }
4158        Ok(frames)
4159    }
4160}
4161
4162struct SseLine<'a> {
4163    content: &'a [u8],
4164    raw: &'a [u8],
4165}
4166
4167fn split_sse_lines(bytes: &[u8], limits: CodecLimits) -> Result<Vec<SseLine<'_>>, CodecError> {
4168    let mut lines = Vec::new();
4169    let mut start = 0usize;
4170    let mut position = 0usize;
4171    while position < bytes.len() {
4172        if !matches!(bytes[position], b'\r' | b'\n') {
4173            position += 1;
4174            if position - start > limits.max_sse_line_bytes() {
4175                return Err(codec_error(
4176                    CodecErrorCode::SseLineLimitExceeded,
4177                    CodecPhase::SseDecode,
4178                ));
4179            }
4180            continue;
4181        }
4182        let content_end = position;
4183        if bytes[position] == b'\r' && bytes.get(position + 1) == Some(&b'\n') {
4184            position += 2;
4185        } else {
4186            position += 1;
4187        }
4188        lines.push(SseLine {
4189            content: &bytes[start..content_end],
4190            raw: &bytes[start..position],
4191        });
4192        start = position;
4193    }
4194    if start != bytes.len() {
4195        return Err(codec_error(
4196            CodecErrorCode::IncompleteSseStream,
4197            CodecPhase::SseDecode,
4198        ));
4199    }
4200    Ok(lines)
4201}
4202
4203#[derive(Clone, Copy, Eq, PartialEq)]
4204enum MessageLifecycle {
4205    AwaitingMessageStart,
4206    InMessage,
4207    MessageStopped,
4208}
4209
4210#[derive(Clone, Copy, Eq, PartialEq)]
4211enum BlockKind {
4212    Text,
4213    InputJson,
4214    Thinking,
4215    RedactedThinking,
4216}
4217
4218struct BlockAccumulator {
4219    kind: BlockKind,
4220    start_slot: usize,
4221    start_frame: Vec<u8>,
4222    delta_slots: Vec<usize>,
4223    logical: String,
4224    signature: String,
4225    signed_frames: Vec<(usize, Vec<u8>)>,
4226    passthrough_frames: Vec<(usize, Vec<u8>, OutputProvenance)>,
4227}
4228
4229#[derive(Default)]
4230struct ReplaySlot {
4231    bytes: Option<Vec<u8>>,
4232    provenance: OutputProvenance,
4233}
4234
4235fn restore_sse_frames(
4236    mut frames: Vec<SseFrame>,
4237    ctx: &mut ResponseTransformContext<'_>,
4238) -> Result<ProvedResponseBody, CodecError> {
4239    let mut lifecycle = MessageLifecycle::AwaitingMessageStart;
4240    let mut blocks = BTreeMap::<u32, BlockAccumulator>::new();
4241    let mut seen_indices = HashSet::<u32>::new();
4242    let mut slots = Vec::<ReplaySlot>::new();
4243    let mut concatenated_text = String::new();
4244    let mut concatenated_authorized = Vec::<Range<usize>>::new();
4245    let mut occurrence_count = 0usize;
4246    let mut inspection_facts_complete = true;
4247    for frame in &mut frames {
4248        if frame.comment {
4249            if matches!(lifecycle, MessageLifecycle::MessageStopped) {
4250                return Err(codec_error(
4251                    CodecErrorCode::InvalidSseLifecycle,
4252                    CodecPhase::SseLifecycle,
4253                ));
4254            }
4255            continue;
4256        }
4257        let event = frame
4258            .event
4259            .as_deref()
4260            .ok_or_else(|| codec_error(CodecErrorCode::InvalidSseFrame, CodecPhase::SseDecode))?;
4261        if matches!(lifecycle, MessageLifecycle::MessageStopped) {
4262            return Err(codec_error(
4263                CodecErrorCode::InvalidSseLifecycle,
4264                CodecPhase::SseLifecycle,
4265            ));
4266        }
4267        let mut document = parse_json(&frame.data, ctx.limits(), CodecPhase::SseDecode)?;
4268        occurrence_count = occurrence_count
4269            .checked_add(document.occurrence_count)
4270            .ok_or_else(|| {
4271                codec_error(CodecErrorCode::NodeLimitExceeded, CodecPhase::SseLifecycle)
4272            })?;
4273        let discriminator = object_string(&document.root, "type")
4274            .map_err(|code| codec_error(code, CodecPhase::SseDecode))?;
4275        if discriminator != event {
4276            return Err(codec_error(
4277                CodecErrorCode::InvalidSseEventPair,
4278                CodecPhase::SseDecode,
4279            ));
4280        }
4281        match event {
4282            "ping" => {
4283                validate_simple_event(&document, "ping")?;
4284            }
4285            "error" => {
4286                return Err(codec_error(
4287                    CodecErrorCode::ProviderErrorEvent,
4288                    CodecPhase::SseLifecycle,
4289                ));
4290            }
4291            "message_start" => {
4292                if !matches!(lifecycle, MessageLifecycle::AwaitingMessageStart) {
4293                    return Err(codec_error(
4294                        CodecErrorCode::InvalidSseLifecycle,
4295                        CodecPhase::SseLifecycle,
4296                    ));
4297                }
4298                transform_message_start(&mut document, &frame.data, ctx)?;
4299                let (bytes, provenance) = canonical_sse_frame(event, &document, &frame.data)?;
4300                slots.push(ReplaySlot {
4301                    bytes: Some(bytes),
4302                    provenance,
4303                });
4304                lifecycle = MessageLifecycle::InMessage;
4305            }
4306            "content_block_start" => {
4307                if !matches!(lifecycle, MessageLifecycle::InMessage) {
4308                    return Err(codec_error(
4309                        CodecErrorCode::InvalidSseLifecycle,
4310                        CodecPhase::SseLifecycle,
4311                    ));
4312                }
4313                if seen_indices.len() >= ctx.limits().max_sse_indices() {
4314                    return Err(codec_error(
4315                        CodecErrorCode::SseIndexLimitExceeded,
4316                        CodecPhase::SseLifecycle,
4317                    ));
4318                }
4319                let index = event_index(&document)?;
4320                if !seen_indices.insert(index) {
4321                    return Err(codec_error(
4322                        CodecErrorCode::InvalidContentBlockIndex,
4323                        CodecPhase::SseLifecycle,
4324                    ));
4325                }
4326                let slot = slots.len();
4327                slots.push(ReplaySlot::default());
4328                let accumulator =
4329                    transform_block_start(&mut document, &frame.data, &frame.raw, slot, ctx)?;
4330                blocks.insert(index, accumulator);
4331            }
4332            "content_block_delta" => {
4333                if !matches!(lifecycle, MessageLifecycle::InMessage) {
4334                    return Err(codec_error(
4335                        CodecErrorCode::InvalidSseLifecycle,
4336                        CodecPhase::SseLifecycle,
4337                    ));
4338                }
4339                let index = event_index(&document)?;
4340                let accumulator = blocks.get_mut(&index).ok_or_else(|| {
4341                    codec_error(
4342                        CodecErrorCode::InvalidContentBlockIndex,
4343                        CodecPhase::SseLifecycle,
4344                    )
4345                })?;
4346                let slot = slots.len();
4347                slots.push(ReplaySlot::default());
4348                transform_block_delta(
4349                    accumulator,
4350                    &mut document,
4351                    &frame.data,
4352                    &frame.raw,
4353                    slot,
4354                    ctx,
4355                )?;
4356            }
4357            "content_block_stop" => {
4358                if !matches!(lifecycle, MessageLifecycle::InMessage) {
4359                    return Err(codec_error(
4360                        CodecErrorCode::InvalidSseLifecycle,
4361                        CodecPhase::SseLifecycle,
4362                    ));
4363                }
4364                let index = event_index(&document)?;
4365                let accumulator = blocks.remove(&index).ok_or_else(|| {
4366                    codec_error(
4367                        CodecErrorCode::InvalidContentBlockIndex,
4368                        CodecPhase::SseLifecycle,
4369                    )
4370                })?;
4371                let stop_slot = slots.len();
4372                slots.push(ReplaySlot::default());
4373                finish_block(
4374                    index,
4375                    accumulator,
4376                    &mut slots,
4377                    StopFrame {
4378                        slot: stop_slot,
4379                        document: &mut document,
4380                        input: &frame.data,
4381                    },
4382                    ctx,
4383                    &mut concatenated_text,
4384                    &mut concatenated_authorized,
4385                )?;
4386            }
4387            "message_delta" => {
4388                if !matches!(lifecycle, MessageLifecycle::InMessage) || !blocks.is_empty() {
4389                    return Err(codec_error(
4390                        CodecErrorCode::InvalidSseLifecycle,
4391                        CodecPhase::SseLifecycle,
4392                    ));
4393                }
4394                transform_message_delta(&mut document, ctx)?;
4395                let (bytes, provenance) = canonical_sse_frame(event, &document, &frame.data)?;
4396                slots.push(ReplaySlot {
4397                    bytes: Some(bytes),
4398                    provenance,
4399                });
4400            }
4401            "message_stop" => {
4402                if !matches!(lifecycle, MessageLifecycle::InMessage) || !blocks.is_empty() {
4403                    return Err(codec_error(
4404                        CodecErrorCode::InvalidSseLifecycle,
4405                        CodecPhase::SseLifecycle,
4406                    ));
4407                }
4408                validate_simple_event(&document, "message_stop")?;
4409                let (bytes, provenance) = canonical_sse_frame(event, &document, &frame.data)?;
4410                slots.push(ReplaySlot {
4411                    bytes: Some(bytes),
4412                    provenance,
4413                });
4414                lifecycle = MessageLifecycle::MessageStopped;
4415            }
4416            _ => {
4417                validate_future_event(&document, event, ctx)?;
4418            }
4419        }
4420        if ctx.inspection_projection_requested() {
4421            frame.inspection_fact = sse_inspection_fact(&document, event);
4422            inspection_facts_complete &= frame.inspection_fact.is_some();
4423        }
4424    }
4425    if !matches!(lifecycle, MessageLifecycle::MessageStopped) || !blocks.is_empty() {
4426        return Err(codec_error(
4427            CodecErrorCode::IncompleteSseStream,
4428            CodecPhase::SseLifecycle,
4429        ));
4430    }
4431    ctx.validate(&concatenated_text, &concatenated_authorized)
4432        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
4433    let mut output = Vec::new();
4434    let mut provenance = OutputProvenance::default();
4435    let mut expected_authorized = Vec::<Vec<u8>>::new();
4436    let mut expected_signed = Vec::<Vec<u8>>::new();
4437    let mut expected_authorized_ranges = Vec::<Range<usize>>::new();
4438    let mut expected_signed_ranges = Vec::<Range<usize>>::new();
4439    for slot in slots {
4440        if let Some(bytes) = slot.bytes {
4441            let offset = output.len();
4442            for range in slot.provenance.authorized_output_ranges() {
4443                append_expected_wire_chunk(
4444                    &bytes,
4445                    range,
4446                    offset,
4447                    &mut expected_authorized_ranges,
4448                    &mut expected_authorized,
4449                )
4450                .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4451            }
4452            for range in slot.provenance.signed_opaque_ranges() {
4453                append_expected_wire_chunk(
4454                    &bytes,
4455                    range,
4456                    offset,
4457                    &mut expected_signed_ranges,
4458                    &mut expected_signed,
4459                )
4460                .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4461            }
4462            output.extend_from_slice(&bytes);
4463            for range in slot.provenance.authorized_output_ranges() {
4464                provenance.record_authorized(offset + range.start..offset + range.end);
4465            }
4466            for range in slot.provenance.signed_opaque_ranges() {
4467                provenance.record_signed(offset + range.start..offset + range.end);
4468            }
4469        }
4470    }
4471    if output.len() > ctx.limits().max_body_bytes() {
4472        return Err(codec_error(
4473            CodecErrorCode::BodyLimitExceeded,
4474            CodecPhase::SseReplay,
4475        ));
4476    }
4477    let final_occurrence_count = reprove_sse_output(&output, ctx.limits())?;
4478    provenance.set_occurrence_count(final_occurrence_count);
4479    verify_final_wire_proof(&output, &provenance, &expected_authorized, &expected_signed)
4480        .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4481    provenance.mark_final_buffer_verified();
4482    if ctx.inspection_projection_requested() && provenance.signed_opaque_ranges().is_empty() {
4483        for frame in &mut frames {
4484            frame.event = None;
4485            frame.data = Vec::new();
4486            frame.raw = Vec::new();
4487        }
4488        Ok(ProvedResponseBody::new_with_inspection_parsed_facts(
4489            output,
4490            WireFormat::Sse,
4491            provenance,
4492            InspectionParsedFactsV1::AnthropicSse(SseInspectionParsedFactsV1 {
4493                frames,
4494                complete: inspection_facts_complete,
4495            }),
4496        ))
4497    } else {
4498        Ok(ProvedResponseBody::new(output, WireFormat::Sse, provenance))
4499    }
4500}
4501
4502fn sse_inspection_fact(document: &JsonDocument, event: &str) -> Option<SseInspectionFrameFactV1> {
4503    let event_kind = match event {
4504        "message_start" => SseEventKindV1::MessageStart,
4505        "content_block_start" => SseEventKindV1::ContentBlockStart,
4506        "content_block_delta" => SseEventKindV1::ContentBlockDelta,
4507        "content_block_stop" => SseEventKindV1::ContentBlockStop,
4508        "message_delta" => SseEventKindV1::MessageDelta,
4509        "message_stop" => SseEventKindV1::MessageStop,
4510        "ping" => SseEventKindV1::Ping,
4511        "error" => SseEventKindV1::Error,
4512        _ => SseEventKindV1::UnknownFuture,
4513    };
4514    let content_block = match event {
4515        "content_block_start" | "content_block_delta" | "content_block_stop" => {
4516            ProjectionAvailabilityV1::Present(ContentBlockIndexV1::new(event_index(document).ok()?))
4517        }
4518        _ => ProjectionAvailabilityV1::Omitted(ProjectionOmissionReasonV1::NotApplicable),
4519    };
4520    let delta_kind = if event == "content_block_delta" {
4521        let delta = object_value(&document.root, "delta").ok()?;
4522        let delta_type = object_string(delta, "type").ok()?;
4523        let kind = match delta_type {
4524            "text_delta" => SseDeltaKindV1::Text,
4525            "input_json_delta" => SseDeltaKindV1::InputJson,
4526            "thinking_delta" => SseDeltaKindV1::Thinking,
4527            "signature_delta" => SseDeltaKindV1::Signature,
4528            "citations_delta" => SseDeltaKindV1::Citation,
4529            _ => SseDeltaKindV1::UnknownFuture,
4530        };
4531        ProjectionAvailabilityV1::Present(kind)
4532    } else {
4533        ProjectionAvailabilityV1::Omitted(ProjectionOmissionReasonV1::NotApplicable)
4534    };
4535    Some(SseInspectionFrameFactV1 {
4536        event_kind,
4537        delta_kind,
4538        content_block,
4539    })
4540}
4541
4542fn append_expected_wire_chunk(
4543    source: &[u8],
4544    local: &Range<usize>,
4545    offset: usize,
4546    ranges: &mut Vec<Range<usize>>,
4547    chunks: &mut Vec<Vec<u8>>,
4548) -> Result<(), CodecErrorCode> {
4549    let chunk = source
4550        .get(local.clone())
4551        .ok_or(CodecErrorCode::InternalCoverageFailure)?;
4552    let global = offset
4553        .checked_add(local.start)
4554        .ok_or(CodecErrorCode::InternalCoverageFailure)?
4555        ..offset
4556            .checked_add(local.end)
4557            .ok_or(CodecErrorCode::InternalCoverageFailure)?;
4558    if let Some(previous) = ranges.last_mut() {
4559        if global.start <= previous.end {
4560            let overlap = previous.end.saturating_sub(global.start);
4561            if overlap > chunk.len() {
4562                return Err(CodecErrorCode::InternalCoverageFailure);
4563            }
4564            let previous_chunk = chunks
4565                .last_mut()
4566                .ok_or(CodecErrorCode::InternalCoverageFailure)?;
4567            if overlap > previous_chunk.len()
4568                || previous_chunk[previous_chunk.len() - overlap..] != chunk[..overlap]
4569            {
4570                return Err(CodecErrorCode::InternalCoverageFailure);
4571            }
4572            previous_chunk.extend_from_slice(&chunk[overlap..]);
4573            previous.end = previous.end.max(global.end);
4574            return Ok(());
4575        }
4576    }
4577    ranges.push(global);
4578    chunks.push(chunk.to_vec());
4579    Ok(())
4580}
4581
4582fn reprove_sse_output(output: &[u8], limits: CodecLimits) -> Result<usize, CodecError> {
4583    let mut decoder = SseDecoder::new(limits);
4584    decoder.push(output)?;
4585    let frames = decoder.finish()?;
4586    let mut reconstructed = Vec::with_capacity(output.len());
4587    let mut lifecycle = MessageLifecycle::AwaitingMessageStart;
4588    let mut blocks = BTreeMap::<u32, BlockKind>::new();
4589    let mut seen_indices = HashSet::<u32>::new();
4590    let mut occurrence_count = 0usize;
4591    for frame in frames {
4592        if frame.comment {
4593            return Err(codec_error(
4594                CodecErrorCode::InternalCoverageFailure,
4595                CodecPhase::SseReplay,
4596            ));
4597        }
4598        reconstructed.extend_from_slice(&frame.raw);
4599        let event = frame.event.as_deref().ok_or_else(|| {
4600            codec_error(
4601                CodecErrorCode::InternalCoverageFailure,
4602                CodecPhase::SseReplay,
4603            )
4604        })?;
4605        let document = parse_json(&frame.data, limits, CodecPhase::SseReplay)?;
4606        occurrence_count = occurrence_count
4607            .checked_add(document.occurrence_count)
4608            .ok_or_else(|| codec_error(CodecErrorCode::NodeLimitExceeded, CodecPhase::SseReplay))?;
4609        validate_full_coverage(&document).map_err(|_| {
4610            codec_error(
4611                CodecErrorCode::InternalCoverageFailure,
4612                CodecPhase::SseReplay,
4613            )
4614        })?;
4615        if object_string(&document.root, "type") != Ok(event) {
4616            return Err(codec_error(
4617                CodecErrorCode::InternalCoverageFailure,
4618                CodecPhase::SseReplay,
4619            ));
4620        }
4621        match event {
4622            "message_start" => {
4623                if lifecycle != MessageLifecycle::AwaitingMessageStart {
4624                    return Err(codec_error(
4625                        CodecErrorCode::InternalCoverageFailure,
4626                        CodecPhase::SseReplay,
4627                    ));
4628                }
4629                exact_object_shape(&document.root, &["type", "message"], &["type", "message"])
4630                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4631                let message = object_value(&document.root, "message")
4632                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4633                prove_response_root_shape(message)
4634                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4635                lifecycle = MessageLifecycle::InMessage;
4636            }
4637            "content_block_start" => {
4638                if lifecycle != MessageLifecycle::InMessage {
4639                    return Err(codec_error(
4640                        CodecErrorCode::InternalCoverageFailure,
4641                        CodecPhase::SseReplay,
4642                    ));
4643                }
4644                exact_object_shape(
4645                    &document.root,
4646                    &["type", "index", "content_block"],
4647                    &["type", "index", "content_block"],
4648                )
4649                .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4650                let index = event_index(&document)?;
4651                if seen_indices.len() >= limits.max_sse_indices()
4652                    || !seen_indices.insert(index)
4653                    || blocks.contains_key(&index)
4654                {
4655                    return Err(codec_error(
4656                        CodecErrorCode::InternalCoverageFailure,
4657                        CodecPhase::SseReplay,
4658                    ));
4659                }
4660                let content_block = object_value(&document.root, "content_block")
4661                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4662                let kind = prove_sse_block_start_shape(content_block)
4663                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4664                blocks.insert(index, kind);
4665            }
4666            "content_block_delta" => {
4667                if lifecycle != MessageLifecycle::InMessage {
4668                    return Err(codec_error(
4669                        CodecErrorCode::InternalCoverageFailure,
4670                        CodecPhase::SseReplay,
4671                    ));
4672                }
4673                exact_object_shape(
4674                    &document.root,
4675                    &["type", "index", "delta"],
4676                    &["type", "index", "delta"],
4677                )
4678                .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4679                let index = event_index(&document)?;
4680                let kind = blocks.get(&index).copied().ok_or_else(|| {
4681                    codec_error(
4682                        CodecErrorCode::InternalCoverageFailure,
4683                        CodecPhase::SseReplay,
4684                    )
4685                })?;
4686                let delta = object_value(&document.root, "delta")
4687                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4688                prove_sse_delta_shape(delta, kind, limits)
4689                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4690            }
4691            "content_block_stop" => {
4692                if lifecycle != MessageLifecycle::InMessage {
4693                    return Err(codec_error(
4694                        CodecErrorCode::InternalCoverageFailure,
4695                        CodecPhase::SseReplay,
4696                    ));
4697                }
4698                exact_object_shape(&document.root, &["type", "index"], &["type", "index"])
4699                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4700                let index = event_index(&document)?;
4701                if blocks.remove(&index).is_none() {
4702                    return Err(codec_error(
4703                        CodecErrorCode::InternalCoverageFailure,
4704                        CodecPhase::SseReplay,
4705                    ));
4706                }
4707            }
4708            "message_delta" => {
4709                if lifecycle != MessageLifecycle::InMessage || !blocks.is_empty() {
4710                    return Err(codec_error(
4711                        CodecErrorCode::InternalCoverageFailure,
4712                        CodecPhase::SseReplay,
4713                    ));
4714                }
4715                prove_message_delta_shape(&document.root)
4716                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4717            }
4718            "message_stop" => {
4719                if lifecycle != MessageLifecycle::InMessage || !blocks.is_empty() {
4720                    return Err(codec_error(
4721                        CodecErrorCode::InternalCoverageFailure,
4722                        CodecPhase::SseReplay,
4723                    ));
4724                }
4725                exact_object_shape(&document.root, &["type"], &["type"])
4726                    .map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
4727                lifecycle = MessageLifecycle::MessageStopped;
4728            }
4729            _ => {
4730                return Err(codec_error(
4731                    CodecErrorCode::InternalCoverageFailure,
4732                    CodecPhase::SseReplay,
4733                ));
4734            }
4735        }
4736    }
4737    if reconstructed != output
4738        || lifecycle != MessageLifecycle::MessageStopped
4739        || !blocks.is_empty()
4740    {
4741        return Err(codec_error(
4742            CodecErrorCode::InternalCoverageFailure,
4743            CodecPhase::SseReplay,
4744        ));
4745    }
4746    Ok(occurrence_count)
4747}
4748
4749fn exact_object_shape(
4750    node: &JsonNode,
4751    allowed: &[&str],
4752    required: &[&str],
4753) -> Result<(), CodecErrorCode> {
4754    let JsonKind::Object(members) = &node.kind else {
4755        return Err(CodecErrorCode::InternalCoverageFailure);
4756    };
4757    if members
4758        .iter()
4759        .any(|member| !allowed.contains(&member.key.value.as_str()))
4760        || required
4761            .iter()
4762            .any(|required| !members.iter().any(|member| member.key.value == *required))
4763    {
4764        return Err(CodecErrorCode::InternalCoverageFailure);
4765    }
4766    Ok(())
4767}
4768
4769fn object_value<'a>(node: &'a JsonNode, key: &str) -> Result<&'a JsonNode, CodecErrorCode> {
4770    let JsonKind::Object(members) = &node.kind else {
4771        return Err(CodecErrorCode::InternalCoverageFailure);
4772    };
4773    members
4774        .iter()
4775        .find(|member| member.key.value == key)
4776        .map(|member| &member.value)
4777        .ok_or(CodecErrorCode::InternalCoverageFailure)
4778}
4779
4780fn prove_response_root_shape(node: &JsonNode) -> Result<(), CodecErrorCode> {
4781    const KEYS: &[&str] = &[
4782        "id",
4783        "type",
4784        "role",
4785        "model",
4786        "content",
4787        "stop_reason",
4788        "stop_sequence",
4789        "usage",
4790    ];
4791    exact_object_shape(node, KEYS, KEYS)?;
4792    if object_string(node, "type")? != "message"
4793        || object_string(node, "role")? != "assistant"
4794        || object_string(node, "id")?.is_empty()
4795        || object_string(node, "model")?.is_empty()
4796    {
4797        return Err(CodecErrorCode::InternalCoverageFailure);
4798    }
4799    prove_optional_enum_string(
4800        object_value(node, "stop_reason")?,
4801        &[
4802            "end_turn",
4803            "max_tokens",
4804            "stop_sequence",
4805            "tool_use",
4806            "pause_turn",
4807            "refusal",
4808            "model_context_window_exceeded",
4809        ],
4810    )?;
4811    prove_optional_string(object_value(node, "stop_sequence")?)?;
4812    let content = object_value(node, "content")?;
4813    let JsonKind::Array(blocks) = &content.kind else {
4814        return Err(CodecErrorCode::InternalCoverageFailure);
4815    };
4816    for block in blocks {
4817        prove_response_block_shape(block)?;
4818    }
4819    prove_usage_shape(object_value(node, "usage")?, true)
4820}
4821
4822fn prove_response_block_shape(node: &JsonNode) -> Result<(), CodecErrorCode> {
4823    match object_string(node, "type")? {
4824        "text" => exact_object_shape(node, &["type", "text", "citations"], &["type", "text"]),
4825        "tool_use" => exact_object_shape(
4826            node,
4827            &["type", "id", "name", "input"],
4828            &["type", "id", "name", "input"],
4829        ),
4830        "tool_result" => exact_object_shape(
4831            node,
4832            &["type", "tool_use_id", "content", "is_error"],
4833            &["type", "tool_use_id", "content"],
4834        ),
4835        "search_result" | "document" => exact_object_shape(
4836            node,
4837            &[
4838                "type", "title", "context", "text", "content", "source", "id",
4839            ],
4840            &["type"],
4841        ),
4842        "thinking" => exact_object_shape(
4843            node,
4844            &["type", "thinking", "signature"],
4845            &["type", "thinking", "signature"],
4846        ),
4847        "redacted_thinking" => exact_object_shape(node, &["type", "data"], &["type", "data"]),
4848        _ => Err(CodecErrorCode::InternalCoverageFailure),
4849    }
4850}
4851
4852fn prove_sse_block_start_shape(node: &JsonNode) -> Result<BlockKind, CodecErrorCode> {
4853    let kind = match object_string(node, "type")? {
4854        "text" => {
4855            exact_object_shape(node, &["type", "text"], &["type", "text"])?;
4856            BlockKind::Text
4857        }
4858        "tool_use" => {
4859            exact_object_shape(
4860                node,
4861                &["type", "id", "name", "input"],
4862                &["type", "id", "name", "input"],
4863            )?;
4864            BlockKind::InputJson
4865        }
4866        "thinking" => {
4867            exact_object_shape(
4868                node,
4869                &["type", "thinking", "signature"],
4870                &["type", "thinking"],
4871            )?;
4872            BlockKind::Thinking
4873        }
4874        "redacted_thinking" => {
4875            exact_object_shape(node, &["type", "data"], &["type", "data"])?;
4876            BlockKind::RedactedThinking
4877        }
4878        _ => return Err(CodecErrorCode::InternalCoverageFailure),
4879    };
4880    Ok(kind)
4881}
4882
4883fn prove_sse_delta_shape(
4884    node: &JsonNode,
4885    kind: BlockKind,
4886    limits: CodecLimits,
4887) -> Result<(), CodecErrorCode> {
4888    match (kind, object_string(node, "type")?) {
4889        (BlockKind::Text, "text_delta") => {
4890            exact_object_shape(node, &["type", "text"], &["type", "text"])
4891        }
4892        (BlockKind::Text, "citations_delta") => {
4893            exact_object_shape(node, &["type", "citation"], &["type", "citation"])
4894        }
4895        (BlockKind::InputJson, "input_json_delta") => {
4896            exact_object_shape(node, &["type", "partial_json"], &["type", "partial_json"])?;
4897            prove_rebuilt_partial_json(object_string(node, "partial_json")?, limits)
4898        }
4899        (BlockKind::Thinking, "thinking_delta") => {
4900            exact_object_shape(node, &["type", "thinking"], &["type", "thinking"])
4901        }
4902        (BlockKind::Thinking | BlockKind::RedactedThinking, "signature_delta") => {
4903            exact_object_shape(node, &["type", "signature"], &["type", "signature"])
4904        }
4905        _ => Err(CodecErrorCode::InternalCoverageFailure),
4906    }
4907}
4908
4909fn prove_rebuilt_partial_json(
4910    partial_json: &str,
4911    limits: CodecLimits,
4912) -> Result<(), CodecErrorCode> {
4913    let document = parse_json(partial_json.as_bytes(), limits, CodecPhase::SseReplay)
4914        .map_err(|error| error.code())?;
4915    let mut ledger = CoverageLedger::new(document.occurrence_count);
4916    account_subtree(&document.root, &mut ledger)?;
4917    ledger.finish()?;
4918    prove_final_mutable_shape(&document.root)?;
4919    let (reproved, _) = write_document(&document, partial_json.as_bytes())?;
4920    if reproved == partial_json.as_bytes() {
4921        Ok(())
4922    } else {
4923        Err(CodecErrorCode::InternalCoverageFailure)
4924    }
4925}
4926
4927fn prove_final_mutable_shape(node: &JsonNode) -> Result<(), CodecErrorCode> {
4928    match &node.kind {
4929        JsonKind::Object(members) => {
4930            for member in members {
4931                prove_final_mutable_shape(&member.value)?;
4932            }
4933            Ok(())
4934        }
4935        JsonKind::Array(values) => {
4936            for value in values {
4937                prove_final_mutable_shape(value)?;
4938            }
4939            Ok(())
4940        }
4941        JsonKind::String(_) | JsonKind::Bool(_) | JsonKind::Null => Ok(()),
4942        JsonKind::Number(_) => Err(CodecErrorCode::InternalCoverageFailure),
4943    }
4944}
4945
4946fn prove_message_delta_shape(node: &JsonNode) -> Result<(), CodecErrorCode> {
4947    exact_object_shape(
4948        node,
4949        &["type", "delta", "usage"],
4950        &["type", "delta", "usage"],
4951    )?;
4952    exact_object_shape(
4953        object_value(node, "delta")?,
4954        &["stop_reason", "stop_sequence"],
4955        &["stop_reason", "stop_sequence"],
4956    )?;
4957    let delta = object_value(node, "delta")?;
4958    prove_optional_enum_string(
4959        object_value(delta, "stop_reason")?,
4960        &[
4961            "end_turn",
4962            "max_tokens",
4963            "stop_sequence",
4964            "tool_use",
4965            "pause_turn",
4966            "refusal",
4967            "model_context_window_exceeded",
4968        ],
4969    )?;
4970    prove_optional_string(object_value(delta, "stop_sequence")?)?;
4971    prove_usage_shape(object_value(node, "usage")?, false)
4972}
4973
4974fn prove_optional_enum_string(node: &JsonNode, allowed: &[&str]) -> Result<(), CodecErrorCode> {
4975    match &node.kind {
4976        JsonKind::String(value) if allowed.contains(&value.value.as_str()) => Ok(()),
4977        JsonKind::Null => Ok(()),
4978        _ => Err(CodecErrorCode::InternalCoverageFailure),
4979    }
4980}
4981
4982fn prove_optional_string(node: &JsonNode) -> Result<(), CodecErrorCode> {
4983    if matches!(&node.kind, JsonKind::String(_) | JsonKind::Null) {
4984        Ok(())
4985    } else {
4986        Err(CodecErrorCode::InternalCoverageFailure)
4987    }
4988}
4989
4990fn prove_usage_shape(node: &JsonNode, require_input_tokens: bool) -> Result<(), CodecErrorCode> {
4991    const KEYS: &[&str] = &[
4992        "input_tokens",
4993        "output_tokens",
4994        "cache_creation_input_tokens",
4995        "cache_read_input_tokens",
4996    ];
4997    let required: &[&str] = if require_input_tokens {
4998        &["input_tokens", "output_tokens"]
4999    } else {
5000        &["output_tokens"]
5001    };
5002    exact_object_shape(node, KEYS, required)?;
5003    let JsonKind::Object(members) = &node.kind else {
5004        return Err(CodecErrorCode::InternalCoverageFailure);
5005    };
5006    if members.iter().any(|member| {
5007        !matches!(&member.value.kind, JsonKind::Number(raw) if !raw.starts_with('-') && !raw.contains(['.', 'e', 'E']))
5008    }) {
5009        return Err(CodecErrorCode::InternalCoverageFailure);
5010    }
5011    Ok(())
5012}
5013
5014fn validate_simple_event(document: &JsonDocument, expected: &str) -> Result<(), CodecError> {
5015    let JsonKind::Object(members) = &document.root.kind else {
5016        return Err(codec_error(
5017            CodecErrorCode::InvalidSseFrame,
5018            CodecPhase::SseDecode,
5019        ));
5020    };
5021    if members.len() != 1 || object_string(&document.root, "type") != Ok(expected) {
5022        return Err(codec_error(
5023            CodecErrorCode::InvalidSseFrame,
5024            CodecPhase::SseDecode,
5025        ));
5026    }
5027    validate_full_coverage(document)
5028}
5029
5030fn validate_full_coverage(document: &JsonDocument) -> Result<(), CodecError> {
5031    let mut ledger = CoverageLedger::new(document.occurrence_count);
5032    account_subtree(&document.root, &mut ledger)
5033        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5034    ledger
5035        .finish()
5036        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))
5037}
5038
5039fn transform_message_start(
5040    document: &mut JsonDocument,
5041    input: &[u8],
5042    ctx: &mut ResponseTransformContext<'_>,
5043) -> Result<(), CodecError> {
5044    let mut ledger = CoverageLedger::new(document.occurrence_count);
5045    ledger
5046        .mark(document.root.occurrence)
5047        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5048    let JsonKind::Object(members) = &mut document.root.kind else {
5049        return Err(codec_error(
5050            CodecErrorCode::InvalidSseFrame,
5051            CodecPhase::SseLifecycle,
5052        ));
5053    };
5054    let mut saw_message = false;
5055    for member in members {
5056        ledger
5057            .mark(member.key_occurrence)
5058            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5059        match member.key.value.as_str() {
5060            "type" => response_string_control(&mut member.value, ctx, &mut ledger),
5061            "message" => {
5062                saw_message = true;
5063                transform_response_root(&mut member.value, input, ctx, &mut ledger)
5064            }
5065            _ => Err(CodecErrorCode::UnsupportedResponseSurface),
5066        }
5067        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5068    }
5069    if !saw_message {
5070        return Err(codec_error(
5071            CodecErrorCode::InvalidSseFrame,
5072            CodecPhase::SseLifecycle,
5073        ));
5074    }
5075    ledger
5076        .finish()
5077        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))
5078}
5079
5080fn event_index(document: &JsonDocument) -> Result<u32, CodecError> {
5081    let JsonKind::Object(members) = &document.root.kind else {
5082        return Err(codec_error(
5083            CodecErrorCode::InvalidContentBlockIndex,
5084            CodecPhase::SseLifecycle,
5085        ));
5086    };
5087    let index = members
5088        .iter()
5089        .find(|member| member.key.value == "index")
5090        .ok_or_else(|| {
5091            codec_error(
5092                CodecErrorCode::InvalidContentBlockIndex,
5093                CodecPhase::SseLifecycle,
5094            )
5095        })?;
5096    let JsonKind::Number(raw) = &index.value.kind else {
5097        return Err(codec_error(
5098            CodecErrorCode::InvalidContentBlockIndex,
5099            CodecPhase::SseLifecycle,
5100        ));
5101    };
5102    if raw.starts_with('-') || raw.contains(['.', 'e', 'E']) {
5103        return Err(codec_error(
5104            CodecErrorCode::InvalidContentBlockIndex,
5105            CodecPhase::SseLifecycle,
5106        ));
5107    }
5108    raw.parse().map_err(|_| {
5109        codec_error(
5110            CodecErrorCode::InvalidContentBlockIndex,
5111            CodecPhase::SseLifecycle,
5112        )
5113    })
5114}
5115
5116fn transform_block_start(
5117    document: &mut JsonDocument,
5118    input: &[u8],
5119    raw_frame: &[u8],
5120    start_slot: usize,
5121    ctx: &mut ResponseTransformContext<'_>,
5122) -> Result<BlockAccumulator, CodecError> {
5123    let mut ledger = CoverageLedger::new(document.occurrence_count);
5124    ledger
5125        .mark(document.root.occurrence)
5126        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5127    let JsonKind::Object(members) = &mut document.root.kind else {
5128        return Err(codec_error(
5129            CodecErrorCode::InvalidSseFrame,
5130            CodecPhase::SseLifecycle,
5131        ));
5132    };
5133    let mut content_block = None;
5134    for member in members {
5135        ledger
5136            .mark(member.key_occurrence)
5137            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5138        match member.key.value.as_str() {
5139            "type" => response_string_control(&mut member.value, ctx, &mut ledger),
5140            "index" => {
5141                ledger
5142                    .mark(member.value.occurrence)
5143                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5144                if matches!(member.value.kind, JsonKind::Number(_)) {
5145                    Ok(())
5146                } else {
5147                    Err(CodecErrorCode::InvalidContentBlockIndex)
5148                }
5149            }
5150            "content_block" => {
5151                content_block = Some(&mut member.value);
5152                Ok(())
5153            }
5154            _ => Err(CodecErrorCode::InvalidSseFrame),
5155        }
5156        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5157    }
5158    let block = content_block
5159        .ok_or_else(|| codec_error(CodecErrorCode::InvalidSseFrame, CodecPhase::SseLifecycle))?;
5160    let block_type = object_string(block, "type")
5161        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?
5162        .to_owned();
5163    let mut logical = String::new();
5164    let mut signature = String::new();
5165    let kind = match block_type.as_str() {
5166        "text" => {
5167            ledger
5168                .mark(block.occurrence)
5169                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5170            let JsonKind::Object(block_members) = &mut block.kind else {
5171                return Err(codec_error(
5172                    CodecErrorCode::InvalidSseFrame,
5173                    CodecPhase::SseLifecycle,
5174                ));
5175            };
5176            let mut saw_text = false;
5177            for member in block_members {
5178                ledger
5179                    .mark(member.key_occurrence)
5180                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5181                match member.key.value.as_str() {
5182                    "type" => {
5183                        response_enum_string_control(&mut member.value, &["text"], ctx, &mut ledger)
5184                            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?
5185                    }
5186                    "text" => {
5187                        ledger
5188                            .mark(member.value.occurrence)
5189                            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5190                        let JsonKind::String(value) = &mut member.value.kind else {
5191                            return Err(codec_error(
5192                                CodecErrorCode::InvalidSseFrame,
5193                                CodecPhase::SseLifecycle,
5194                            ));
5195                        };
5196                        logical.push_str(&value.value);
5197                        value.value.clear();
5198                        saw_text = true;
5199                    }
5200                    _ => {
5201                        return Err(codec_error(
5202                            CodecErrorCode::InvalidSseFrame,
5203                            CodecPhase::SseLifecycle,
5204                        ));
5205                    }
5206                }
5207            }
5208            if !saw_text {
5209                return Err(codec_error(
5210                    CodecErrorCode::InvalidSseFrame,
5211                    CodecPhase::SseLifecycle,
5212                ));
5213            }
5214            BlockKind::Text
5215        }
5216        "tool_use" => {
5217            ledger
5218                .mark(block.occurrence)
5219                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5220            let JsonKind::Object(block_members) = &mut block.kind else {
5221                return Err(codec_error(
5222                    CodecErrorCode::InvalidSseFrame,
5223                    CodecPhase::SseLifecycle,
5224                ));
5225            };
5226            let mut saw_id = false;
5227            let mut saw_name = false;
5228            let mut saw_input = false;
5229            for member in block_members {
5230                ledger
5231                    .mark(member.key_occurrence)
5232                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5233                match member.key.value.as_str() {
5234                    "type" => response_enum_string_control(
5235                        &mut member.value,
5236                        &["tool_use"],
5237                        ctx,
5238                        &mut ledger,
5239                    )
5240                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?,
5241                    "id" => {
5242                        response_nonempty_string_control(&mut member.value, ctx, &mut ledger)
5243                            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5244                        saw_id = true;
5245                    }
5246                    "name" => {
5247                        response_nonempty_string_control(&mut member.value, ctx, &mut ledger)
5248                            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5249                        saw_name = true;
5250                    }
5251                    "input" => {
5252                        if !matches!(&member.value.kind, JsonKind::Object(values) if values.is_empty())
5253                        {
5254                            return Err(codec_error(
5255                                CodecErrorCode::InvalidContentBlockDelta,
5256                                CodecPhase::SseLifecycle,
5257                            ));
5258                        }
5259                        account_subtree(&member.value, &mut ledger)
5260                            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5261                        saw_input = true;
5262                    }
5263                    _ => {
5264                        return Err(codec_error(
5265                            CodecErrorCode::InvalidSseFrame,
5266                            CodecPhase::SseLifecycle,
5267                        ));
5268                    }
5269                }
5270            }
5271            if !saw_id || !saw_name || !saw_input {
5272                return Err(codec_error(
5273                    CodecErrorCode::InvalidSseFrame,
5274                    CodecPhase::SseLifecycle,
5275                ));
5276            }
5277            BlockKind::InputJson
5278        }
5279        "thinking" | "redacted_thinking" => {
5280            let (initial_logical, initial_signature) =
5281                validate_signed_sse_block(block, &block_type, ctx)?;
5282            logical = initial_logical;
5283            signature = initial_signature;
5284            account_subtree(block, &mut ledger)
5285                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5286            if block_type == "thinking" {
5287                BlockKind::Thinking
5288            } else {
5289                BlockKind::RedactedThinking
5290            }
5291        }
5292        _ => {
5293            return Err(codec_error(
5294                CodecErrorCode::UnsupportedResponseSurface,
5295                CodecPhase::SseLifecycle,
5296            ));
5297        }
5298    };
5299    ledger
5300        .finish()
5301        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5302    let start_frame = if matches!(kind, BlockKind::Thinking | BlockKind::RedactedThinking) {
5303        raw_frame.to_vec()
5304    } else {
5305        canonical_sse_frame("content_block_start", document, input)?.0
5306    };
5307    let mut signed_frames = Vec::new();
5308    if matches!(kind, BlockKind::Thinking | BlockKind::RedactedThinking) {
5309        signed_frames.push((start_slot, raw_frame.to_vec()));
5310    }
5311    Ok(BlockAccumulator {
5312        kind,
5313        start_slot,
5314        start_frame,
5315        delta_slots: Vec::new(),
5316        logical,
5317        signature,
5318        signed_frames,
5319        passthrough_frames: Vec::new(),
5320    })
5321}
5322
5323fn validate_signed_sse_block(
5324    block: &JsonNode,
5325    block_type: &str,
5326    ctx: &mut ResponseTransformContext<'_>,
5327) -> Result<(String, String), CodecError> {
5328    let JsonKind::Object(members) = &block.kind else {
5329        return Err(codec_error(
5330            CodecErrorCode::SignedSurfaceMalformed,
5331            CodecPhase::SseLifecycle,
5332        ));
5333    };
5334    let mut logical = String::new();
5335    let mut signature = String::new();
5336    let mut has_payload = false;
5337    let mut has_type = false;
5338    for member in members {
5339        match member.key.value.as_str() {
5340            "type" if string_value(&member.value) == Ok(block_type) => {
5341                has_type = true;
5342            }
5343            "thinking" if block_type == "thinking" => {
5344                let value = string_value(&member.value)
5345                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5346                guard_mutable_text_response(value)
5347                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5348                let _ = ctx
5349                    .restore(value)
5350                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5351                ctx.validate(value, &[])
5352                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5353                logical.push_str(value);
5354                has_payload = true;
5355            }
5356            "signature" if block_type == "thinking" => {
5357                let value = string_value(&member.value)
5358                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5359                let _ = ctx
5360                    .restore(value)
5361                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5362                signature.push_str(value);
5363            }
5364            "data" if block_type == "redacted_thinking" => {
5365                let value = string_value(&member.value)
5366                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5367                let _ = ctx
5368                    .restore(value)
5369                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5370                has_payload = true;
5371            }
5372            _ => {
5373                return Err(codec_error(
5374                    CodecErrorCode::SignedSurfaceMalformed,
5375                    CodecPhase::SseLifecycle,
5376                ));
5377            }
5378        }
5379    }
5380    if !has_type || !has_payload {
5381        return Err(codec_error(
5382            CodecErrorCode::SignedSurfaceMalformed,
5383            CodecPhase::SseLifecycle,
5384        ));
5385    }
5386    Ok((logical, signature))
5387}
5388
5389fn transform_block_delta(
5390    accumulator: &mut BlockAccumulator,
5391    document: &mut JsonDocument,
5392    input: &[u8],
5393    raw_frame: &[u8],
5394    slot: usize,
5395    ctx: &mut ResponseTransformContext<'_>,
5396) -> Result<(), CodecError> {
5397    let mut ledger = CoverageLedger::new(document.occurrence_count);
5398    ledger
5399        .mark(document.root.occurrence)
5400        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5401    let JsonKind::Object(members) = &mut document.root.kind else {
5402        return Err(codec_error(
5403            CodecErrorCode::InvalidSseFrame,
5404            CodecPhase::SseLifecycle,
5405        ));
5406    };
5407    let mut delta = None;
5408    for member in members {
5409        ledger
5410            .mark(member.key_occurrence)
5411            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5412        match member.key.value.as_str() {
5413            "type" => response_string_control(&mut member.value, ctx, &mut ledger)
5414                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?,
5415            "index" => account_subtree(&member.value, &mut ledger)
5416                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?,
5417            "delta" => delta = Some(&mut member.value),
5418            _ => {
5419                return Err(codec_error(
5420                    CodecErrorCode::InvalidSseFrame,
5421                    CodecPhase::SseLifecycle,
5422                ));
5423            }
5424        }
5425    }
5426    let delta = delta
5427        .ok_or_else(|| codec_error(CodecErrorCode::InvalidSseFrame, CodecPhase::SseLifecycle))?;
5428    let delta_type = object_string(delta, "type")
5429        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?
5430        .to_owned();
5431    if delta_type == "citations_delta" {
5432        if !matches!(accumulator.kind, BlockKind::Text) {
5433            return Err(codec_error(
5434                CodecErrorCode::InvalidContentBlockDelta,
5435                CodecPhase::SseLifecycle,
5436            ));
5437        }
5438        transform_response_citation_delta(delta, ctx, &mut ledger)
5439            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5440        ledger
5441            .finish()
5442            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5443        let (bytes, provenance) = canonical_sse_frame("content_block_delta", document, input)?;
5444        accumulator
5445            .passthrough_frames
5446            .push((slot, bytes, provenance));
5447        return Ok(());
5448    }
5449    account_subtree(delta, &mut ledger)
5450        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5451    let value = match delta_type.as_str() {
5452        "text_delta" => object_string(delta, "text"),
5453        "input_json_delta" => object_string(delta, "partial_json"),
5454        "thinking_delta" => object_string(delta, "thinking"),
5455        "signature_delta" => object_string(delta, "signature"),
5456        _ => Err(CodecErrorCode::InvalidContentBlockDelta),
5457    }
5458    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5459    match (&accumulator.kind, delta_type.as_str()) {
5460        (BlockKind::Text, "text_delta") | (BlockKind::InputJson, "input_json_delta") => {
5461            accumulator.logical.push_str(value);
5462            accumulator.delta_slots.push(slot);
5463        }
5464        (BlockKind::Thinking, "thinking_delta") => {
5465            accumulator.logical.push_str(value);
5466            accumulator.signed_frames.push((slot, raw_frame.to_vec()));
5467        }
5468        (BlockKind::Thinking, "signature_delta") => {
5469            accumulator.signature.push_str(value);
5470            accumulator.signed_frames.push((slot, raw_frame.to_vec()));
5471        }
5472        (BlockKind::RedactedThinking, "signature_delta") => {
5473            accumulator.signature.push_str(value);
5474            accumulator.signed_frames.push((slot, raw_frame.to_vec()));
5475        }
5476        _ => {
5477            return Err(codec_error(
5478                CodecErrorCode::InvalidContentBlockDelta,
5479                CodecPhase::SseLifecycle,
5480            ));
5481        }
5482    }
5483    if accumulator.logical.len() > ctx.limits().max_sse_accumulator_bytes()
5484        || accumulator.signature.len() > ctx.limits().max_sse_accumulator_bytes()
5485    {
5486        return Err(codec_error(
5487            CodecErrorCode::SseAccumulatorLimitExceeded,
5488            CodecPhase::SseLifecycle,
5489        ));
5490    }
5491    ledger
5492        .finish()
5493        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))
5494}
5495
5496fn transform_response_citation_delta(
5497    delta: &mut JsonNode,
5498    ctx: &mut ResponseTransformContext<'_>,
5499    ledger: &mut CoverageLedger,
5500) -> Result<(), CodecErrorCode> {
5501    ledger.mark(delta.occurrence)?;
5502    let JsonKind::Object(members) = &mut delta.kind else {
5503        return Err(CodecErrorCode::InvalidContentBlockDelta);
5504    };
5505    for member in members {
5506        ledger.mark(member.key_occurrence)?;
5507        match member.key.value.as_str() {
5508            "type" => response_string_control(&mut member.value, ctx, ledger)?,
5509            "citation" => transform_response_citation(&mut member.value, ctx, ledger)?,
5510            _ => return Err(CodecErrorCode::InvalidContentBlockDelta),
5511        }
5512    }
5513    Ok(())
5514}
5515
5516struct StopFrame<'document, 'input> {
5517    slot: usize,
5518    document: &'document mut JsonDocument,
5519    input: &'input [u8],
5520}
5521
5522fn finish_block(
5523    index: u32,
5524    accumulator: BlockAccumulator,
5525    slots: &mut [ReplaySlot],
5526    stop: StopFrame<'_, '_>,
5527    ctx: &mut ResponseTransformContext<'_>,
5528    concatenated_text: &mut String,
5529    concatenated_authorized: &mut Vec<Range<usize>>,
5530) -> Result<(), CodecError> {
5531    validate_stop_event(stop.document)?;
5532    let (stop_frame, stop_provenance) =
5533        canonical_sse_frame("content_block_stop", stop.document, stop.input)?;
5534    slots[stop.slot] = ReplaySlot {
5535        bytes: Some(stop_frame),
5536        provenance: stop_provenance,
5537    };
5538    match accumulator.kind {
5539        BlockKind::Text => {
5540            let restored = ctx
5541                .restore(&accumulator.logical)
5542                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5543            guard_mutable_text_response(&restored.text)
5544                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5545            ctx.validate(&restored.text, &restored.authorized_output_ranges)
5546                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5547            let base = concatenated_text.len();
5548            concatenated_text.push_str(&restored.text);
5549            concatenated_authorized.extend(
5550                restored
5551                    .authorized_output_ranges
5552                    .iter()
5553                    .map(|range| base + range.start..base + range.end),
5554            );
5555            slots[accumulator.start_slot].bytes = Some(accumulator.start_frame);
5556            if let Some(first) = accumulator.delta_slots.first().copied() {
5557                let (bytes, provenance) = built_delta_frame(
5558                    index,
5559                    "text_delta",
5560                    "text",
5561                    &restored.text,
5562                    restored.authorized_output_ranges,
5563                );
5564                slots[first] = ReplaySlot {
5565                    bytes: Some(bytes),
5566                    provenance,
5567                };
5568            } else if !restored.text.is_empty() {
5569                return Err(codec_error(
5570                    CodecErrorCode::InvalidContentBlockDelta,
5571                    CodecPhase::SseLifecycle,
5572                ));
5573            }
5574            for (slot, bytes, provenance) in accumulator.passthrough_frames {
5575                slots[slot] = ReplaySlot {
5576                    bytes: Some(bytes),
5577                    provenance,
5578                };
5579            }
5580        }
5581        BlockKind::InputJson => {
5582            let partial_input =
5583                if accumulator.delta_slots.is_empty() && accumulator.logical.is_empty() {
5584                    "{}"
5585                } else {
5586                    accumulator.logical.as_str()
5587                };
5588            let mut partial = parse_json(
5589                partial_input.as_bytes(),
5590                ctx.limits(),
5591                CodecPhase::SseLifecycle,
5592            )?;
5593            let mut ledger = CoverageLedger::new(partial.occurrence_count);
5594            transform_response_mutable(&mut partial.root, ctx, &mut ledger)
5595                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5596            ledger
5597                .finish()
5598                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5599            let (partial_bytes, partial_provenance) =
5600                write_document(&partial, partial_input.as_bytes())
5601                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5602            let partial_text = String::from_utf8(partial_bytes)
5603                .map_err(|_| codec_error(CodecErrorCode::InvalidUtf8, CodecPhase::SseLifecycle))?;
5604            slots[accumulator.start_slot].bytes = Some(accumulator.start_frame);
5605            if let Some(first) = accumulator.delta_slots.first().copied() {
5606                let (bytes, provenance) = built_delta_frame(
5607                    index,
5608                    "input_json_delta",
5609                    "partial_json",
5610                    &partial_text,
5611                    partial_provenance.authorized_output_ranges().to_vec(),
5612                );
5613                slots[first] = ReplaySlot {
5614                    bytes: Some(bytes),
5615                    provenance,
5616                };
5617            } else if partial_text != "{}" {
5618                return Err(codec_error(
5619                    CodecErrorCode::InvalidContentBlockDelta,
5620                    CodecPhase::SseLifecycle,
5621                ));
5622            }
5623        }
5624        BlockKind::Thinking => {
5625            guard_mutable_text_response(&accumulator.logical)
5626                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5627            let _ = ctx
5628                .restore(&accumulator.logical)
5629                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5630            ctx.validate(&accumulator.logical, &[])
5631                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5632            let _ = ctx
5633                .restore(&accumulator.signature)
5634                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5635            for (slot, raw) in accumulator.signed_frames {
5636                let mut provenance = OutputProvenance::default();
5637                provenance.record_signed(0..raw.len());
5638                slots[slot] = ReplaySlot {
5639                    bytes: Some(raw),
5640                    provenance,
5641                };
5642            }
5643        }
5644        BlockKind::RedactedThinking => {
5645            let _ = ctx
5646                .restore(&accumulator.signature)
5647                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5648            for (slot, raw) in accumulator.signed_frames {
5649                let mut provenance = OutputProvenance::default();
5650                provenance.record_signed(0..raw.len());
5651                slots[slot] = ReplaySlot {
5652                    bytes: Some(raw),
5653                    provenance,
5654                };
5655            }
5656        }
5657    }
5658    Ok(())
5659}
5660
5661fn validate_stop_event(document: &JsonDocument) -> Result<(), CodecError> {
5662    let JsonKind::Object(members) = &document.root.kind else {
5663        return Err(codec_error(
5664            CodecErrorCode::InvalidSseFrame,
5665            CodecPhase::SseLifecycle,
5666        ));
5667    };
5668    let valid = members.len() == 2
5669        && members.iter().any(|member| member.key.value == "type")
5670        && members.iter().any(|member| member.key.value == "index");
5671    if valid {
5672        validate_full_coverage(document)
5673    } else {
5674        Err(codec_error(
5675            CodecErrorCode::InvalidSseFrame,
5676            CodecPhase::SseLifecycle,
5677        ))
5678    }
5679}
5680
5681fn transform_message_delta(
5682    document: &mut JsonDocument,
5683    ctx: &mut ResponseTransformContext<'_>,
5684) -> Result<(), CodecError> {
5685    let mut ledger = CoverageLedger::new(document.occurrence_count);
5686    ledger
5687        .mark(document.root.occurrence)
5688        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5689    let JsonKind::Object(members) = &mut document.root.kind else {
5690        return Err(codec_error(
5691            CodecErrorCode::InvalidSseFrame,
5692            CodecPhase::SseLifecycle,
5693        ));
5694    };
5695    let mut saw_delta = false;
5696    let mut saw_usage = false;
5697    for member in members {
5698        ledger
5699            .mark(member.key_occurrence)
5700            .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5701        match member.key.value.as_str() {
5702            "type" => response_string_control(&mut member.value, ctx, &mut ledger)
5703                .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?,
5704            "delta" => {
5705                transform_message_delta_controls(&mut member.value, ctx, &mut ledger)
5706                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5707                saw_delta = true;
5708            }
5709            "usage" => {
5710                response_usage(&mut member.value, &mut ledger, false)
5711                    .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))?;
5712                saw_usage = true;
5713            }
5714            _ => {
5715                return Err(codec_error(
5716                    CodecErrorCode::InvalidSseFrame,
5717                    CodecPhase::SseLifecycle,
5718                ));
5719            }
5720        }
5721    }
5722    if !saw_delta || !saw_usage {
5723        return Err(codec_error(
5724            CodecErrorCode::InvalidSseFrame,
5725            CodecPhase::SseLifecycle,
5726        ));
5727    }
5728    ledger
5729        .finish()
5730        .map_err(|code| codec_error(code, CodecPhase::SseLifecycle))
5731}
5732
5733fn transform_message_delta_controls(
5734    delta: &mut JsonNode,
5735    ctx: &mut ResponseTransformContext<'_>,
5736    ledger: &mut CoverageLedger,
5737) -> Result<(), CodecErrorCode> {
5738    ledger.mark(delta.occurrence)?;
5739    let JsonKind::Object(members) = &mut delta.kind else {
5740        return Err(CodecErrorCode::InvalidSseFrame);
5741    };
5742    let mut saw_reason = false;
5743    let mut saw_sequence = false;
5744    for member in members {
5745        ledger.mark(member.key_occurrence)?;
5746        match member.key.value.as_str() {
5747            "stop_reason" => {
5748                response_enum_string_or_null(
5749                    &mut member.value,
5750                    &[
5751                        "end_turn",
5752                        "max_tokens",
5753                        "stop_sequence",
5754                        "tool_use",
5755                        "pause_turn",
5756                        "refusal",
5757                        "model_context_window_exceeded",
5758                    ],
5759                    ctx,
5760                    ledger,
5761                )?;
5762                saw_reason = true;
5763            }
5764            "stop_sequence" => {
5765                response_string_or_null(&mut member.value, ctx, ledger)?;
5766                saw_sequence = true;
5767            }
5768            _ => return Err(CodecErrorCode::InvalidSseFrame),
5769        }
5770    }
5771    if saw_reason && saw_sequence {
5772        Ok(())
5773    } else {
5774        Err(CodecErrorCode::InvalidSseFrame)
5775    }
5776}
5777
5778fn validate_future_event(
5779    document: &JsonDocument,
5780    event: &str,
5781    ctx: &mut ResponseTransformContext<'_>,
5782) -> Result<(), CodecError> {
5783    let JsonKind::Object(members) = &document.root.kind else {
5784        return Err(codec_error(
5785            CodecErrorCode::UnsafeFutureEvent,
5786            CodecPhase::SseLifecycle,
5787        ));
5788    };
5789    validate_future_atom(event, ctx)?;
5790    for member in members {
5791        validate_future_atom(&member.key.value, ctx)?;
5792        match (&*member.key.value, &member.value.kind) {
5793            ("type", JsonKind::String(value)) if value.value == event => {}
5794            (_, JsonKind::Bool(_) | JsonKind::Null) => {}
5795            _ => {
5796                return Err(codec_error(
5797                    CodecErrorCode::UnsafeFutureEvent,
5798                    CodecPhase::SseLifecycle,
5799                ));
5800            }
5801        }
5802    }
5803    validate_full_coverage(document)
5804}
5805
5806fn validate_future_atom(
5807    value: &str,
5808    ctx: &mut ResponseTransformContext<'_>,
5809) -> Result<(), CodecError> {
5810    let unsafe_event = || codec_error(CodecErrorCode::UnsafeFutureEvent, CodecPhase::SseLifecycle);
5811    guard_mutable_text_response(value).map_err(|_| unsafe_event())?;
5812    let restored = ctx.restore(value).map_err(|_| unsafe_event())?;
5813    if restored.text != value || !restored.authorized_output_ranges.is_empty() {
5814        return Err(unsafe_event());
5815    }
5816    ctx.validate(value, &[]).map_err(|_| unsafe_event())
5817}
5818
5819fn canonical_sse_frame(
5820    event: &str,
5821    document: &JsonDocument,
5822    input: &[u8],
5823) -> Result<(Vec<u8>, OutputProvenance), CodecError> {
5824    let (json, json_provenance) =
5825        write_document(document, input).map_err(|code| codec_error(code, CodecPhase::SseReplay))?;
5826    let mut output = Vec::with_capacity(event.len() + json.len() + 16);
5827    output.extend_from_slice(b"event: ");
5828    output.extend_from_slice(event.as_bytes());
5829    output.extend_from_slice(b"\ndata: ");
5830    let offset = output.len();
5831    output.extend_from_slice(&json);
5832    output.extend_from_slice(b"\n\n");
5833    let mut provenance = OutputProvenance::default();
5834    for range in json_provenance.authorized_output_ranges() {
5835        provenance.record_authorized(offset + range.start..offset + range.end);
5836    }
5837    for range in json_provenance.signed_opaque_ranges() {
5838        provenance.record_signed(offset + range.start..offset + range.end);
5839    }
5840    Ok((output, provenance))
5841}
5842
5843fn built_delta_frame(
5844    index: u32,
5845    delta_type: &str,
5846    field: &str,
5847    value: &str,
5848    authorized: Vec<Range<usize>>,
5849) -> (Vec<u8>, OutputProvenance) {
5850    let mut output = format!(
5851        "event: content_block_delta\ndata: {{\"type\":\"content_block_delta\",\"index\":{index},\"delta\":{{\"type\":\"{delta_type}\",\"{field}\":"
5852    )
5853    .into_bytes();
5854    let mut provenance = OutputProvenance::default();
5855    write_json_string(
5856        &JsonString {
5857            value: value.to_owned(),
5858            authorized,
5859        },
5860        &mut output,
5861        &mut provenance,
5862    );
5863    output.extend_from_slice(b"}}\n\n");
5864    (output, provenance)
5865}
5866
5867#[cfg(test)]
5868mod inspection_parity_tests {
5869    use gaze::{Scope, Session};
5870
5871    use super::*;
5872    use crate::codec::ResponseResidualValidator;
5873
5874    struct CleanResidual;
5875
5876    impl ResponseResidualValidator for CleanResidual {
5877        fn validate(
5878            &mut self,
5879            _value: &str,
5880            _authorized_output_ranges: &[Range<usize>],
5881        ) -> Result<(), CodecErrorCode> {
5882            Ok(())
5883        }
5884    }
5885
5886    fn malformed_sse_error(inspection_configured: bool) -> CodecError {
5887        let session = Session::new(Scope::Ephemeral).unwrap();
5888        let snapshot = session.begin_transaction().commit().unwrap();
5889        let mut residual = CleanResidual;
5890        let mut context = ResponseTransformContext::new(
5891            &snapshot,
5892            &mut residual,
5893            WireFormat::Sse,
5894            CodecLimits::default(),
5895        );
5896        if inspection_configured {
5897            context.request_inspection_projection();
5898        }
5899        AnthropicMessagesCodec
5900            .restore_response(
5901                b"event: content_block_start\ndata: {\"type\":\"content_block_start\",\"content_block\":{\"type\":\"text\",\"text\":\"\"}}\n\n",
5902                &mut context,
5903            )
5904            .unwrap_err()
5905    }
5906
5907    #[test]
5908    fn malformed_sse_error_is_identical_with_and_without_inspection() {
5909        let without = malformed_sse_error(false);
5910        let with = malformed_sse_error(true);
5911        assert_eq!(with.code(), without.code());
5912        assert_eq!(with.phase(), without.phase());
5913    }
5914}