Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions crates/aisix-proxy/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,25 @@ unscannable sites as the full set: the places that scan a mangled copy
unconditionally, with no failure policy involved. `jobs::scan_output_blob`
and the binary-purpose arm of `scan_input_blob` scan
`String::from_utf8_lossy` and relay the original bytes whatever the row
says; `audio.rs` and `images_edits.rs` drop non-UTF-8 multipart prompt
parts with `filter_map`; `passthrough_route` scans the lossy body. None of
these consults `refuses_unevaluable_*`, so a fail-CLOSED row does not
refuse there either — that asymmetry is #1022's open product decision, not
something telemetry can paper over, and making them refuse is a behaviour
change rather than an observability one. Tagging them instead would fire
the field on every binary upload and download, which destroys the negative
answer just as thoroughly. Note that `record_unevaluable_*` is the wrong
helper at such a site: its predicate assumes the fail-closed case was
already refused, so at a site that never refuses it would silently drop
exactly the case worth reporting.
says; `passthrough_route` scans the lossy body; `audio.rs`'s
`transcription_output_text` falls back to the lossy body for the plain-text
transcript formats (`text` / `srt` / `vtt`). None of these consults
`refuses_unevaluable_*`, so a fail-CLOSED row does not refuse there either —
not something telemetry can paper over, and making them refuse is a behaviour
change rather than an observability one. Tagging them instead would fire the
field on every binary upload and download, which destroys the negative answer
just as thoroughly. Note that `record_unevaluable_*` is the wrong helper at
such a site: its predicate assumes the fail-closed case was already refused,
so at a site that never refuses it would silently drop exactly the case worth
reporting.

What is no longer in that set is the multipart `prompt` on `audio.rs` and
`images_edits.rs`: since #1016 both call
`dispatch::require_utf8_prompt_fields` after model resolution and before the
chain runs, so an undecodable `prompt` part is answered 400 and the
`filter_map` in their scan builders can no longer be reached by one. Do not
describe those surfaces as silently dropping non-UTF-8 prompt parts — audio's
transcript OUTPUT scan, listed above, is a separate site and still lossy.

Values come from the guardrail kind's own `bypass_tag()` — the same bounded
vocabulary `GuardrailVerdict::block_unavailable` carries, so one outage reads
Expand Down