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