* feat(docs): mirror every docs/ page in all 65 locales Extends the documentation mirrors from the 22-page core set (#13940) to every Markdown page under docs/: 152 sources x 65 locales = 9,880 mirrors (6,208 new), language bars rewritten for the full locale list, state adopted so the blocking drift gate now covers all 152 pages. run-translation.mjs: an oversized block made only of table rows or list items (PROVIDER_REFERENCE.md 244-row table, FREE_TIERS.md 71-item list) is cut at item boundaries and rejoined without a blank line — the single 16-40 KB request outlived the backend socket for verbose scripts. 48 older mirrors whose tables had lost rows were retranslated with --force. * docs(i18n): refresh mirrors for the sources the base changed since the branch cut Section-level retranslation of the 29 docs (and README.md) whose source or mirrors moved on release/v3.8.51 during the run, then state adoption; the drift gate is green again on the merged tree.
69 KiB
Guardrails (Filipino)
🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇸 es · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇰🇭 km · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW
Pinagmumulan ng katotohanan:
src/lib/guardrails/Huling na-update: 2026-08-29 — v3.8.51 (ang pinagmulan ng transcript ng Video Bridge ay idinedeklara ng tumatawag, hindi pa bineberipika ng server — nilinaw alinsunod sa #11661)
Ipinapatupad ng mga guardrail ang kaligtasan, patakaran, at mga pagbabago sa content sa hangganan
sa pagitan ng OmniRoute at mga upstream provider. Maaaring suriin ng bawat guardrail (at
opsyonal na tanggihan, baguhin, o lagyan ng anotasyon) ang mga request payload (preCall) at
mga upstream response (postCall).
Ang system ay fail-open: kung mag-throw ang isang guardrail habang isinasagawa, itinatala ng registry
ang error at nagpapatuloy sa susunod na guardrail sa halip na mabigo ang
request. Ang pag-block ay isang tahasang desisyon (block: true), at hindi kailanman aksidente.
Mga Built-in na Guardrail
Awtomatikong nilo-load ng registry ang anim na guardrail ayon sa pagkakasunod-sunod ng priyoridad sa pag-import
(tingnan ang registry.ts → registerDefaultGuardrails()):
| Priyoridad | Pangalan | (Mga) Yugto | File |
|---|---|---|---|
5 |
vision-bridge |
preCall |
visionBridge.ts |
6 |
audio-bridge |
preCall |
audioBridge.ts |
7 |
video-bridge |
preCall |
videoBridge.ts |
10 |
pii-masker |
pre + post |
piiMasker.ts |
20 |
prompt-injection |
preCall |
promptInjection.ts |
95 |
credential-masker |
pre + post |
credentialMasker.ts |
Ang mas mababang numero ng priyoridad ang unang pinapatakbo.
Vision Bridge (visionBridge.ts) — Modality Bridge PR-1
Hinaharang nito ang mga request na may image na nakatuon sa mga model na walang vision at alinman sa iniruruta muli ang buong request sa isang model na may kakayahang vision o pinapalitan ang mga bahagi ng image ng mga tekstuwal na paglalarawang ginawa ng isang nako-configure na vision model bago ang upstream call. Nagbibigay-daan ito sa mga text-only provider na malinaw na pangasiwaan ang mga multimodal payload.
Daloy:
- Laktawan kung sinusuportahan na ng target na model ang vision (maliban kung kasama ito sa
listahan ng sapilitang bridge na
isVisionBridgeForcedModel). - I-extract ang mga bahagi ng image sa pamamagitan ng
extractImageParts(messages)(visionBridgeHelpers.ts), na ipinapasa ang gawain sa pinag-isang media detector nadetectMediaParts()saopen-sse/utils/mediaParts.ts— ang nag-iisang pinagmumulan ng katotohanan na ibinabahagi sa combo compatibility filter. Ang extraction ay limitado sa allowlist ng mga top-level na bahagi na may mga hugis na maaaring muling isingit ngreplaceImageParts(ang extract↔replace contract): OpenAIimage_url, Anthropic base64source.type:"base64", Anthropic URLsource.type:"url", at Responses APIinput_image. Ang mga nested hit at hugis na indicator-only ay materyal para sa combo filter at hindi kailanman ine-extract. Laktawan kung walang nahanap. - I-resolve ang runtime config sa pamamagitan ng
resolveVisionBridgeRuntimeSettings()(src/shared/constants/modalityBridgeDefaults.ts): nananaig ang mga bagong setting key namodalityBridge*; nananatili ang mga legacy key navisionBridge*bilang one-cycle fallback (rollback window). Laktawan bago ang anumang media traversal kapag naka-disable ang bridge. - Tinutukoy ng mode selector (
modalityBridgeVisionMode, tingnan ang talahanayan sa ibaba) kung reroute o describe. Nagbabalik ang reroute ngmodifiedPayloadkung saanmodellamang ang pinalitan, kasama ang meta na{ rerouted, fromModel, toModel, imagesKept }. - Describe path: limitahan ang mga image sa
maxImages, buuin ang task-aware na prompt, konsultahin ang describe cache, tawagan ang vision model nang parallel (Promise.allSettled), at ipalit ang mga text part na[Image N]: <description>sa kinalalagyan ng mga ito. Ang nabigong describe ay nagbubunga ngnullat ang orihinal na bahagi ng image ay pinapanatili (#4012) — maliban sa combo describe path kapag nabigo ang bawat describe, kung saan ang isang kumpirmadong non-vision upstream ay tumatanggap na lang ng(hindi available — walang nakakonektang provider na may kakayahang vision)na stub (#8430). - Ibalik ang
modifiedPayload+ meta (imagesProcessed,descriptions,processingTimeMs,visionModel).
Mode selector (modalityBridgeVisionMode)
| Mode | Default | Gawi |
|---|---|---|
auto |
✔ | Legacy na heuristic, hindi binago (#6640/#7204): ang mga non-combo/auto/ model ay nire-reroute sa pinakamahusay na vision model maliban kung mayroon nang magagamit na credential ang orihinal na model (kung gayon ay magde-describe); palaging nagde-describe ang mga combo target. |
describe |
Palaging mag-describe — ganap na nilalaktawan ang reroute block; ang piniling model ng user ang palaging sumasagot. | |
reroute |
Sapilitang reroute: nilalampasan ang guard na nagpapanatili sa model na may credential. Nalalapat pa rin ang credential guard ng reroute-target — kapag walang magagamit na vision target, tutuloy ang request sa describe upang hindi makarating ang mga raw image sa isang text-only na backend (#8430). |
Nagso-short-circuit ang mga sapilitang mode bago tumakbo ang auto heuristic; ang gawi ng auto
ay byte-identical sa guardrail bago ang PR-1.
Task-aware na describe prompt (modalityBridgeVisionTaskAware)
True bilang default. Idinaragdag ng composeVisionPrompt() (visionBridgeHelpers.ts)
ang text ng huling mensahe ng user (pinaikli sa 500 character) sa base
describe prompt, upang ituon ang paglalarawan sa aktuwal na itinanong ng user
(pattern ng codex-vision-proxy) at hilingin sa vision model na i-transcribe ang nakikitang
text. Kapag naka-off ang flag — o walang text mula sa user — ginagamit ang base prompt nang walang pagbabago.
Ang sariling OpenAI-compatible na request ng describe self-loop (callVisionModelSingle()
sa visionBridgeHelpers.ts) ay palaging humihiling ng image_url.detail: "high" —
nang walang kondisyon, para sa bawat caller/provider, at hindi nakadepende sa anumang signal ng client.
Pinapababa ng low-detail sampling ang katumpakan ng OCR para mismo sa gawain ng
pag-transcribe ng teksto na hinihingi ng prompt na ito, kaya palaging humihiling ang
describe call ng high detail anuman ang antas ng detalye na ginamit ng orihinal na
papasok na request. Nakaaapekto lamang ito sa internal na request body ng describe;
hindi nito binabago kung paano ipinapasa ng OmniRoute ang sariling
image_url.detail ng caller sa pangunahing request — hiwalay na inilalapat ang
default na iyon, at para lamang sa mga natukoy na OpenCode client, sa
defaultImageDetail() (open-sse/handlers/chatCore/upstreamBody.ts). Walang
detail field ang Anthropic wire-format branch ng describe self-loop at hindi ito
naaapektuhan ng alinmang default.
Limitasyon ng output ng describe (modalityBridgeVisionMaxChars)
| Key | Default | Saklaw |
|---|---|---|
modalityBridgeVisionMaxChars |
0 |
0 o 100–50000 |
Ang 0 (default) ay nangangahulugang walang limitasyon — ang paglalarawang
ibinabalik ng callVisionModel() ay ipinapasa nang walang pagbabago, kaya
napapanatili ang kasalukuyang gawi. Pinuputol ng anumang value sa saklaw na
100–50000 ang paglalarawan na may … suffix bago ito muling isingit bilang
[Image N]: <description> (VisionBridgeGuardrail.preCall() sa
src/lib/guardrails/visionBridge.ts). Taasan ito para sa mga gawaing OCR na
nangangailangan ng maraming detalye kung saan kailangan ng downstream model ang
buong transcription; babaan ito upang limitahan ang paggamit ng token sa mga
madaldal na vision model. Matatagpuan ang dashboard field sa Advanced panel ng
Vision tab (modality-bridge-max-chars sa ModalityBridgeVisionTab.tsx) at
itinataas nito ang anumang value sa pagitan ng 1 at 99 sa minimum na 100 habang
hindi binabago ang tahasang 0 — ang 0 ay isang valid na Zod value mismo
(z.union([z.literal(0), z.number().int().min(100).max(50000)])), at hindi lamang
ang "hindi nakatakda" na default.
Cache ng describe (modalityBridge/bridgeCache.ts)
In-memory na LRU + TTL cache para sa mga output ng describe, na pinagsasaluhan sa
buong process. Key = sha256(imageRef + composedPrompt + configuredBridgeModel)
na may length-prefix framing (walang mga banggaan sa hangganan ng field). Ang
bahagi ng model ay ang naka-configure na bridge model, hindi ang model na
aktuwal na sumagot — maaaring internal na gumamit ng fallback ang
callVisionModel, at paghahati-hatiin ng pag-key sa bawat attempt ang cache.
Hindi kailanman naka-cache ang mga nabigong describe. Mga setting:
| Key | Default | Saklaw |
|---|---|---|
modalityBridgeCacheEnabled |
true |
— |
modalityBridgeCacheTtlMinutes |
60 |
1–1440 |
modalityBridgeCacheMaxEntries |
200 |
10–5000 |
Normalisasyon ng remote image (self-loop describe/base64 fetch)
Kapag ang bridge mismo ang kumukuha ng isang remote na image — ang Anthropic
describe self-call at ang claude-wire-format base64 conversion
(ensureBase64ImagesForClaudeWire), na parehong dumaraan sa
fetchRemoteImageAsDataUri() sa visionBridgeHelpers.ts — ipinadaraan ang
resultang data URI sa normalizeDataUri()
(open-sse/utils/imageNormalize.ts) bago ito i-embed sa request ng vision model.
Ang mga sobrang laking image ay pinaliliit sa 2048px na mahabang gilid
(katulad ng resize cap na inilalapat na ng OpenAI/Anthropic sa server-side), na
nagpapababa sa upload bytes/latency nang hindi binabago ang nakikita ng vision
model. Gumagamit ang resizing ng sharp, na nilo-load sa pamamagitan ng dynamic
import: sa isang platform kung saan hindi ma-load ang native binary nito,
hindi kailanman nagta-throw ang normalizeDataUri() — bumabalik ito sa
passthrough ng orihinal na bytes, kaya patuloy na gumagana ang
describe/base64-conversion path. Ang mga byte na hindi image (isang fetch na
hindi nagbalik ng nade-decode na image) ay ipinapasa rin nang walang pagbabago.
Saklaw lamang ng normalisasyong ito ang mga image na kinukuha ng bridge para sa
sarili nitong self-call — hindi ito kailanman inilalapat sa raw passthrough
payload ng caller, alinsunod sa prinsipyo ng mutation na opt-in lamang
(Hard Rule #20).
Schema ng mga setting + migration
Ang mga bagong modalityBridge* key ay bina-validate ng Zod sa
updateSettingsSchema (src/shared/validation/settingsSchemas.ts):
modalityBridgeVisionEnabled, modalityBridgeVisionMode,
modalityBridgeVisionModel, modalityBridgeVisionTaskAware,
modalityBridgeVisionPrompt, modalityBridgeVisionTimeout,
modalityBridgeVisionMaxImages, modalityBridgeVisionMaxChars, ang
modalityBridgeCache* trio, at ang grupong modalityBridgeAudio* na ginagamit
ng Audio Bridge. Kinokopya ng migration na 141_modality_bridge_settings.sql
ang mga kasalukuyang legacy na visionBridge* value sa katumbas na mga bagong
key (idempotent, hindi kailanman ino-overwrite ang isang modalityBridge* value
na itinakda ng operator); patuloy na tinatanggap ang mga legacy key bilang read
fallback sa loob ng isang release cycle.
Transparency header + stats
Ang mga response na binago ng describe ay may
x-omniroute-modality-bridge: image->text;model=<visionModel>;parts=<n>
(na binubuo ng buildModalityBridgeHeader() sa
modalityBridge/bridgeStats.ts, at inilalagay ng
withModalityBridgeHeader() sa src/sse/handlers/chatHelpers.ts).
Walang header ang mga request na ni-reroute — hindi binago ang payload at
makikita na ang pagpapalit ng model sa model field ng response body.
Ang GET /api/modality-bridge/stats (management auth, kaparehong tier ng
GET /api/settings) ay nagbabalik ng mga in-memory per-modality counter na
{ attempts, successes, bridged, cacheHits, failures, totalLatencyMs, latencySamples, averageLatencyMs, lastUsedAt } para sa vision, audio, at
video. Ginagamit ng averageLatencyMs ang latencySamples, hindi ang lahat ng
attempt, bilang denominator nito; ang isang operation na walang timing ay hindi
gumagawa ng pekeng zero-millisecond sample. Nananatili ang bridged bilang
backward-compatible na alias para sa mga matagumpay na conversion; hindi ito
dinadagdagan ng mga nabigong attempt.
Sadyang nire-reset ang mga counter kapag nag-restart ang process
(telemetry, hindi accounting).
Configuration ng dashboard
Ang nakalaang pahina ng dashboard ay
/dashboard/settings/modality-bridge. Pinapanatili ng mga tab nitong Vision, Audio,
at Video na direktang naa-access sa pamamagitan ng URL ang mga query parameter habang
binabago ang value ng tab. Inilalantad ng tab na Vision ang pagpapagana, mode, pagpili
ng modelo (kabilang ang awtomatikong default), pag-prompt na isinasaalang-alang ang gawain,
mga advanced na limitasyon sa timeout/image/haba-ng-paglalarawan/cache, mga runtime
counter, at isang protektadong halimbawang request. Aktibo rin ang tab na Audio:
inilalantad nito ang pagpapagana, isang model picker na STT-only na may Auto, mga limitasyon
sa timeout/max-clip, mga audio counter, at isang halimbawang pagsubok na input_audio.
Gumagana ang tab na Video: iniuulat nito ang runtime state ng FFmpeg/ffprobe — isa sa
apat na tahasang UI state (unknown habang isinasagawa ang probe o hindi ito makumpleto,
restricted sa isang non-loopback dashboard host kung saan nilalaktawan ang probe sa
client-side, unavailable kapag naisagawa na ang probe at nakumpirmang wala ito, o
available kasama ang mga bersyon ng FFmpeg/ffprobe) — pini-persist nito ang mga limitasyon
sa enable/model/frame/video/timeout, fina-filter ang model picker para sa mga modelong may
kakayahang vision, at inilalantad ang mga video counter.
Ang dating Vision Bridge card sa ilalim ng mga setting ng AI ay isa na ngayong compatibility link patungo sa bagong pahina; hindi na ito nagmamay-ari ng pangalawang kopya ng form. Ini-link din ng Media Providers ang mga workflow na Image-to-Text at Speech-to-Text sa mga kaukulang tab ng Modality Bridge nang hindi inaalis ang kasalukuyang Speech-to-Text playground.
Pag-bypass sa admission para sa self-loop: kapag dumaraan ang describe call sa sariling
/v1 self-loop ng OmniRoute (non-standard na modelo ng provider), ipinapadala ng sub-request
ang x-omniroute-admission-bypass: internal at ina-authenticate ito gamit ang na-resolve na
credential ng self-loop — ang lokal na sk_omniroute sentinel sa local mode, o ang
env key na OMNIROUTE_API_KEY / ROUTER_API_KEY na na-configure ng operator (#1350) upang
mapatakbo pa rin ng mga deployment na REQUIRE_API_KEY=true ang describe call. Iginagalang
lamang ang bypass para sa eksaktong mga credential na iyon, kaya hindi magagamit ng mga
external client ang header upang laktawan ang admission.
Nasa src/shared/constants/visionBridgeDefaults.ts ang mga legacy default; nasa
src/shared/constants/modalityBridgeDefaults.ts naman ang mga bagong default para sa
mode/task-aware/cache at ang settings resolver. Naglalantad ang guardrail ng isang
constructor option na deps upang makapag-inject ang mga test ng mga pekeng
implementasyon ng getSettings at callVisionModel.
Audio Bridge (audioBridge.ts) — Modality Bridge PR-3
Hinaharang ang mga chat request na may audio bago makarating ang mga ito sa isang target na hindi kilalang tumatanggap ng audio input. Hindi nito kailanman nire-reroute ang chat request: tina-transcribe ang mga bahagi ng audio sa pamamagitan ng kasalukuyang OpenAI-compatible multipart endpoint at nagpapatuloy ang napiling chat model gamit ang mga text transcript.
Daloy:
- I-resolve ang
supportsAudiosa pamamagitan nggetResolvedModelCapabilities(). Nauuna ang tahasang provider-registry metadata, kasunod ang static model metadata, at pagkatapos ay ang naka-sync namodalities_input. Ang isang idineklarang listahan ng input na walangaudioayfalse; kung walang ebidensya ng kakayahan, nananatili itongnull. Kapwa ina-activate ngfalseatnullang konserbatibong bridge, samantalang nilalampasan ito ngtrue. - I-resolve ang mga setting na
modalityBridgeAudio*at kunin ang mga top-level na bahagi ng audio na maaaring i-splice mula sa bawat mensahe sa pamamagitan ng nakabahaging detector nadetectMediaParts(). Ang mga sinusuportahang wire shape ay OpenAIinput_audio,audio_url, atsource.media_type: "audio/*". Natutukoy ang nested audio para sa routing ngunit hindi ito inaalis ng splice path. Nililimitahan ngmodalityBridgeAudioMaxClipsang gawain; nananatiling hindi nababago ang mga kasunod na bahagi. - Sundin ang isang na-configure na
provider/model, o hayaang siyasatin ngselectAudioBridgeModel()angAUDIO_TRANSCRIPTION_PROVIDERSayon sa matatag na pagkakasunod-sunod ng catalog at piliin ang unang modelo na may magagamit na aktibong provider credential. - Kino-convert ng
callAudioTranscription()ang base64/data-URI audio sa isang multipartfile, o dina-download ang isang remote naaudio_urlsa pamamagitan ng public-only outbound guard na may DNS pinning at limitasyong 25 MB. Pagkatapos, ipinapadala nito sa pamamagitan ng POST ang file at napiling modelo sa lokal na/v1/audio/transcriptionsself-loop, na ina-authenticate gamit angresolveSelfLoopBearer(). Isinasagawa ng kasalukuyang transcription route ang normal na paghahanap ng credential, pangangasiwa sa cooldown/rate-limit, at dispatch sa provider. - Pinapalitan ng mga matagumpay na call ang kanilang mga bahagi ng
[Audio N]: <transcript>. Tumatakbo ang mga call gamit angPromise.allSettled: pinapanatili ng isang indibidwal na failure ang orihinal na bahagi ng audio na iyon (#4012 contract). Kung mabigo ang lahat ng call at napatunayangsupportsAudio === falseang target, magiging[Audio N]: (unavailable — no STT provider connected)ang mga bahagi (#8430 contract). Para sa isang hindi kilalang target (null), nananatiling hindi nababago ang resulta kapag nabigo ang lahat. Ang isang napatunayang text-only na target na walang magagamit na STT credential ay makakatanggap ng parehong tahasang stub nang hindi nagsasagawa ng network call.
Ginagamit ng mga matagumpay na transcript ang process-wide na LRU/TTL cache ng Modality
Bridge. Pinagsasama ng key ang audio reference, ang matatag na operation label na
audio-transcription, at ang napiling STT model; hindi kailanman kina-cache ang mga
failure. Ina-update ng mga pagtatangkang audio ang mga nakabahaging counter na bridged,
cacheHits, failures, at lastUsedAt. Taglay ng mga na-transform na response ang
x-omniroute-modality-bridge: audio->text;model=<sttModel>;parts=<n>; hindi
nakakatanggap ng segment ng Audio Bridge ang mga request na hindi nabago.
DB-backed at Zod-validated ang mga runtime setting:
| Key | Default | Saklaw |
|---|---|---|
modalityBridgeAudioEnabled |
true |
— |
modalityBridgeAudioModel |
"" |
Auto o STT ID |
modalityBridgeAudioTimeout |
60000 |
1000–300000 |
modalityBridgeAudioMaxClips |
3 |
1–10 |
Patuloy na kinokontrol ang nakabahaging cache ng modalityBridgeCacheEnabled,
modalityBridgeCacheTtlMinutes, at modalityBridgeCacheMaxEntries.
Video Bridge (videoBridge.ts, videoBridgePipeline.ts)
Hinaharang ang mga top-level na bahagi ng video sa Chat Completions messages at Responses
API input bago tawagin ang isang target na walang kilalang native na suporta sa video.
Ang mga sinusuportahang anyo ay input_video, video_url, video_source, mga HTTPS URL,
at data:video/*;base64,... na mga data URI. Ang mga simpleng filename sa text ay hindi
itinuturing na video.
Ang VideoBridgeGuardrail.preCall (videoBridge.ts) ang namamahala sa traversal ng request,
pagsusuri ng capability/policy, pagsasama-sama sa bawat request, at response payload.
Ang gawain sa bawat video — pagkuha, cache ng buong resulta, paglalarawan ng isang frame
sequence (na pinagsasama ang anumang audio transcript na idineklara ng caller), at mga
metric/abort/cleanup sa bawat pagtatangka — ay nakatago sa likod ng processVideoPart sa
videoBridgePipeline.ts, na tinatawag nang isang beses para sa bawat bahagi ng video sa loob
ng loop ng preCall. Tinutukoy rin ng module na iyon ang mga tahasang hangganan ng port na
VideoMediaBrokerPort (pagkuha ng mga byte at pag-extract ng mga na-sample na frame),
VideoAudioTranscriptionPort (pagsasama ng audio transcript na idineklara ng caller sa mga
na-sample na caption), at VideoDrilldownPort (ang hangganan ng persistence para sa frame
drill-down; hindi pa nakakabit sa processVideoPart — tanging ang hiwalay na route na
/api/modality-bridge/video/drilldown ang nagsusulat ng mga drill-down entry sa kasalukuyan).
Ang pampublikong /v1 request path ay hindi kailanman nag-i-import o tumatawag ng subprocess.
Dina-download ang mga remote na video sa ilalim ng limitasyong 50 MiB; ang mga inline na
base64 video ay may konserbatibong decoded cap na 36 MiB bawat video upang manatili ang
model/messages/framing envelope sa loob ng pampublikong limitasyong 50 MiB para sa pagtanggap
ng JSON request. Sinusuri ang inline na haba at mga pagtataya sa decoded size bago ang
allocation. Kinakailangan ang HTTPS sa paunang remote URL at sa bawat redirect, gamit ang
umiiral na public-only outbound guard na may DNS pinning. Pagkatapos, tatawid ang mga byte sa
eksaktong internal na broker boundary na POST /api/modality-bridge/video/extract. Ang route
na iyon ay parehong LOCAL_ONLY at SPAWN_CAPABLE, tumatanggap lamang ng authenticated na
request na para sa bawat proseso at mula sa pinagkakatiwalaang loopback, at hindi kailanman
tumatanggap ng URL, filesystem path, executable, o listahan ng mga argument. Magkahiwalay na
ipinapatupad ng API body-size pipeline at incremental body reader ng handler ang 50 MiB na
broker input cap. Ang bounded queue nito ay nagpapatakbo ng isang extraction sa bawat
pagkakataon, nagpapahintulot ng apat na pending job, at naglilimita sa pending input sa
100 MiB.
Sa loob ng broker, binabasa ng ffprobe ang isang pribadong local file; hindi kasama sa
nakapirming format allowlist ang mga format ng playlist at manifest. Para sa mga pinapayagang
MOV-family container, nananatiling naka-disable bilang default ang mga external MOV data
reference, at hindi ino-opt in ng nakapirming command ang mga ito. Parehong ginagamit ng
ffprobe at ffmpeg ang protocol whitelist na file lamang, isang thread, mga nakapirming
array ng argument, walang shell, at mga executable na niri-resolve mula sa PATH. Ang mga
attached-picture cover stream ay hindi maaaring maging mga playable candidate. Dapat
matugunan ng lahat ng playable stream ang mga limitasyon, at inuuna ang isang tahasang default
stream bago ang deterministic na fallback sa pinakamababang index. Nililimitahan ang mga video
sa 600 segundo, 8,192 pixel bawat dimensyon, at 33,554,432 source pixel. Nag-i-sample ang
FFmpeg ng 1–16 midpoint JPEG frame, nagpapaliit sa mahabang gilid hanggang sa hindi hihigit sa
1,024 pixel nang hindi nag-a-upscale ng mas maliliit na input, at hindi kailanman tumatanggap
ng URL. uniform ang sampling bilang default. Ang opsyonal na scene_aware at eksperimental
na segment_aware na mga policy ay nagsasagawa ng isa pang nakapirming FFmpeg pass sa
na-validate nang local stream, pumipili ng mga bounded na showinfo scene timestamp, at
deterministikong bumabalik sa parehong mga uniform midpoint kapag nabigo o nag-timeout ang
detector, malformed ang output, o walang laman ang candidate set. Naglalaan ang segment-aware
mode ng mga midpoint sample nang proporsyonal sa mga na-validate na scene interval; inilalarawan
nang detalyado sa ibaba ang segment-aware na ebidensya at fallback behavior. Inilalapat ang
mahigpit na 16-frame cap pagkatapos ng pagpili sa bawat policy. Kapag ang isang scene-aware na
request ay may one-frame budget lamang, ginagamit nito ang uniform midpoint ng aktibong
full-video o focus window at nag-uulat ng policyEffective: uniform: hindi mapapanatili ng
iisang napiling scene frame ang parehong temporal na dulo. Maaaring opsyonal na magbigay ang
caller ng finite na focus window (start/end na mga segundo); iki-clamp ang mga bound sa
tagal ng media, tatanggihan ang reversed o non-finite na mga window, at isasagawa lamang ang
lahat ng sampling policy sa loob ng normalized na interval. Isinasama ang nagresultang window
sa sampling metadata at sa untrusted description prefix upang matukoy ng mga downstream model
ang pagkakaiba ng isang nakatuong excerpt mula sa buong timeline.
Ang semantic caption focus ay isang hiwalay at tahasang setting. Pinananatili ng default na
full analysis mode ang umiiral na frame prompt at hindi kailanman ipinapasa ang request text
sa caption model. Sa focused mode, binabasa lamang ng bridge ang pinakabagong hindi bakanteng
text/input_text na isinulat ng user mula sa parehong Chat o Responses container, ginagawa
itong normalized sa NFC, kino-collapse ang mga control character at whitespace, at nililimitahan
ito sa 500 Unicode code point. Kapag walang laman ang resulta, babalik ito sa eksaktong full
na prompt. Ang isang magagamit na hint ay ise-serialize bilang JSON sa isang nakalaang
untrusted-user-context block at maaari lamang magbigay-priyoridad sa mga napagmamasdang detalye;
hindi nito maaaring i-override ang hiwalay na babala laban sa pagsunod sa mga instruction na
nakikita o naririnig sa media. Ang textual focus ay hindi kailanman nag-i-infer ng start/end
o nagbabago sa temporal sampler.
FU-07 na istruktural na ebidensya ng segment
Gumagamit ang segment_aware ng isang bounded na pre-analysis pass sa na-validate nang local
video stream. Ang nakapirming filter chain ay nagpapaliit muna sa hindi hihigit sa 320 pixel
ang lapad, tumutukoy ng mga pagbabago ng scene at mga frozen interval, at pagkatapos ay
nagsa-sample sa bilis na 1 frame bawat segundo para sa blur, average luma, at
spatial/temporal information. Nililimitahan ang pass sa 600 structural sample, isang
FFmpeg/filter thread, parehong protocol na file lamang at mga container allowlist, isang
1 MiB process-output bound, at hindi hihigit sa 30 segundo sa loob ng pinagsasaluhang
abort/deadline ng broker. Hindi ito kailanman tumatanggap ng command, filter, path, o URL mula
sa request.
Ang mga structural value ay deterministic sampling evidence, hindi semantic video understanding. Hindi nila tinutukoy ang mga subject, action, caption, speech, o layunin ng user. Bumubuo ng mga segment ang mga scene at freeze boundary; ang freeze coverage, blur, exposure, spatial detail, at temporal change ay nakaaapekto lamang sa kung paano inilalaan ang umiiral na budget na 1–16 frame. Ang ganap na frozen na segment ay nililimitahan sa isang frame, habang nakikipagkumpitensya ang mga non-frozen segment para sa natitirang budget. Kapag mas marami ang mga boundary kaysa sa mga frame, pinananatili ang pantay na coverage ng timeline upang hindi maitago ng mabilis na mga cut sa simula ang isang mahabang segment sa hulihan. Pinagsasama ang mga scene boundary na nasa loob ng 1-second analysis resolution ng isang freeze boundary.
Kapag may mga nawawalang filter, malformed/walang-lamang evidence, detector error,
o bounded pre-analysis timeout, nagfa-fail open ito sa eksaktong uniform midpoint
policy. Hindi nagfa-fail open ang pag-abort ng caller o deadline ng broker:
tinitigil nito ang kasalukuyang subprocess, pinipigilan ang kasunod na frame
extraction, at inaalis ang pribadong temporary tree sa finally.
Gumagawa ang scripts/perf/video-bridge-fu07-eval.ts ng mga deterministic at tunay
na FFmpeg fixture para sa post-dedup caption-call savings, dense-motion budget
allocation, blur/exposure/SI-TI evidence, mabilis na mga cut na may mahabang hulihan,
at mga false positive mula sa gradual fade. Itinatala nito ang pre-analysis wall
time at, kung available ang /usr/bin/time, ang child CPU at peak RSS. Mga
structural oracle lamang ang mga quality check nito. Nananatiling HOLD ang kalidad
ng tunay na caption model dahil walang awtorisadong endpoint o frozen judge ang
harness na ito. Nananatili ring HOLD ang monetary savings maliban kung nagbibigay
ang --caption-cost-per-call-usd ng tahasang positibong pagtataya ng gastos sa bawat
call; hindi kailanman gumagawa-gawa ang script ng alinman sa mga resultang ito.
Nililimitahan ang bawat frame sa 4 MiB, ang pinagsamang lahat ng raw frame sa 23 MiB,
at ang serialized broker response sa 32 MiB. Inaalis ang isang pribadong temporary
directory sa finally. Hindi kasama sa OmniRoute ang FFmpeg at hindi ito tumatanggap
ng custom executable path. Bago ang captioning, nagpapatupad ang bridge ng
conservative visual deduplication pass: binabawasan ang bawat JPEG sa isang 16×16
grayscale buffer at inihahambing lamang ito sa huling frame na pinanatili. Para sa
hiniling na caption budget na higit sa isang frame, nagbibigay ang extraction ng
bounded candidate pool na hanggang dalawang beses ng budget na iyon at hindi
kailanman lalampas sa 16 frame. Inilalapat lamang ang hiniling na cap pagkatapos ng
deduplication, habang pinananatili ang una at huling napiling candidate sa final
thinning kapag hindi bababa sa dalawa ang budget. Ginagamit ng versioned na
grayscale-16x16-mean-cells-v2 policy ang mas mataas sa mean luma delta at sa ratio
ng mga thumbnail cell na may normalized delta na hindi bababa sa 0.05. Ang duplicate
threshold ay ang constant na 0.04, na pinili para sa predictability sa halip na
ilantad bilang runtime setting. Pinananatili ng secondary high-contrast signal na
ito ang maliliit na motion at mga pagbabago sa nakikitang text na maaaring maitago
ng mean-only comparison. Kapag may comparator o decoder error, nagfa-fail open ito
at pinananatili ang coverage. Pinaghihiwalay ng output metadata ang mga na-extract
na candidate, mga frame na matagumpay na nagamit, at mga visual duplicate na
inalis.
Maaaring humiling ang isang tahasang minarkahang video part ng timestamped contact
sheet. Bumubuo ang bridge ng JPEG grid na may hindi hihigit sa 4 column at 16 frame.
Iniimprenta ng bawat 512-pixel cell ang source timestamp nito sa isang high-contrast
band sa ibaba, habang nananatili rin ang parehong mga timestamp sa textual metadata
para sa downstream association at audit. Nananatiling limitado sa 32 MiB ang buong
JPEG. Kung hindi ma-decode o mabuo ng sharp ang grid, bumabalik ang bridge sa mga
indibidwal na JPEG frame; patuloy pa ring ipinapasa ang client abort sa buong sheet
operation.
Sadyang nakahiwalay ang promotion evidence sa synthetic composition
microbenchmark. Tinutukoy ng scripts/perf/video-bridge-contact-sheet-eval.ts ang
isang schema-versioned A/B harness para sa mga tunay na OpenAI-compatible vision
model. Sinusukat nito ang mga token na iniulat ng provider, end-to-end wall latency
(kabilang ang sheet composition), bilang ng model call, at manifest-defined fact
retention. Hindi isinusulat sa report ang mga raw model response; mga SHA-256 digest
at matched fact ID lamang ang pinananatili. Hindi gumagawa ang harness ng network o
paid model call maliban kung ipinasa ang --execute-real at naka-configure ang
--model, OMNIROUTE_BASE_URL, at OMNIROUTE_API_KEY. Kung wala ang tahasang real
run na iyon, nananatiling HOLD ang machine-readable verdict nito; hindi sapat na
promotion evidence ang synthetic payload/call-count measurements lamang.
Maaaring mag-attach ang mga caller ng opsyonal na transcript.cues array sa isang
sinusuportahang video part kapag mayroon na silang aligned text. Kailangang taglay
ng bawat cue ang text, isang finite na start/end interval sa loob ng na-probe
na duration, at isang whitelisted na source (client, embedded, o
audio-bridge); nagde-default ang confidence sa 1 at dapat manatili sa pagitan
ng 0 at 1. Pinagsasama ang mga cue na eksaktong duplicate. Hindi kailanman
nagsisimula ang OmniRoute ng transcription mula sa metadata na ito: kinokopya ang
mga validated cue sa inilarawang resulta kasama ang source, confidence, at interval,
at nire-render bilang mga hindi pinagkakatiwalaang observation kasama ng mga frame
caption. Tinatanggihan ang invalid, out-of-range, o provenance-free na text sa halip
na ihalo ito sa caption stream. Sa kasalukuyan, ang source field ay idinedeklara
ng caller at hindi vine-verify ng server: ipinapatupad ng OmniRoute na dapat isa ang
value sa tatlong pinapayagang string, ngunit hindi pa nito cryptographically
kinukumpirma na ang isang embedded o audio-bridge label ay talagang nagmula sa
extraction na pagmamay-ari ng server. Ituring ang source bilang isang hindi
pinagkakatiwalaang hint hanggang maipatupad ang verification na iyon; huwag
ibabatay rito ang mga authorization decision.
Ang isang advanced na caller ay maaaring magbigay ng awtorisado nang audioTranscript track
para sa parehong video. Pinapatakbo ng fusion seam ang mga obserbasyong biswal at audio sa
ilalim ng iisang deadline at abort signal, inaayos ang mga ito sa iisang timeline, pinagsasama
ang eksaktong magkakaparehong entry, at nag-uulat ng bahagyang resulta kapag isang panig
lamang ang nagtagumpay. Ang isang invalid na audioTranscript ay humahantong sa bahagyang
resultang iyon — pinananatili ang biswal na paglalarawan at nagtatala ang sangay ng audio ng
na-sanitize na failure code — sa halip na mabigo ang buong video. Ang availability ng bawat
sangay, ang partial flag, at ang mga na-sanitize na failure code ay pinananatili sa inilalarawang
resulta, sa guardrail metadata (audioFusionRuns/audioFusionPartials/
audioFusionFailureCodes), sa result-cache metadata, at sa mga fusion counter ng bridge.
Hindi gumagamit ang default na Video Bridge path ng speech-to-text o nagda-download ng
pangalawang kopya ng media; kung wala ang tahasang track na iyon, nananatili itong
video-only.
Pagpapanatili ng transcript (#12150 P1). Awtomatiko itong nalalapat sa tuwing
nagre-render ang Video Bridge (na opt-in mismo) ng transcript cue — walang hiwalay na
retention flag. Kapag nag-render ang isang request ng anumang transcript cue (isang
transcript na idineklara ng caller o isang fused na audioTranscript), minamarkahan ito
ng guardrail bilang videoBridgeObserved at gumagawa ng na-redact na shadow ng paglalarawan
ng video — isang kaparehong rendering kung saan ang free-text body ng bawat cue ay pinapalitan
ng [redacted-video-transcript], na binubuo sa pamamagitan ng pagpapalit sa structured cue field
bago buuin ang string (hindi kailanman sa pamamagitan ng pag-parse sa flattened text, kaya walang
nilalaman ng cue — adversarial man o karaniwan, kabilang ang mga body na naglalaman ng ] gaya ng
[inaudible]/[music] — ang maaaring manatili). Pinapalitan ng naka-persist na request body ng
call log ang bawat text part na nagmula sa video ng na-redact na shadow na iyon, na itinutugma
ayon sa pagkakapareho ng nilalaman; muling binabasa ang fullText anchor mula sa natapos na
pre-call guardrail payload, kaya nagtatagumpay pa rin ang pagtutugma matapos baguhin nang direkta
ng mga susunod na chain guardrail (ang mga PII at credential masker, na may priority na 10/95)
ang teksto ng paglalarawan at matapos baguhin ng system-prompt/handoff/memory injection ang ayos
ng message array. Hindi binabago ang body na ipinapadala upstream sa model. Hindi rin naglalagay
ang isang naobserbahang request ng anumang durable Memory (nilalaktawan ang extraction mula sa
request at response), kaya hindi maaaring i-echo ng sariling sagot ng model ang teksto ng
transcript papunta sa Memory.
May mga retention surface na nananatiling bukas at sinusubaybayan para sa follow-up (P2, #12430):
ang raw na pre-guardrail client-request snapshot sa detailed-log artifact;
ang fail-closed na pagpapatuloy ng previous_response_id; ang mga internal dispatch ng
derived prompt na nag-e-embed sa transcript sa loob ng synthesized string prompt
(mga pipeline stage, context-handoff); at ang response body / semantic-cache copy
ng tugon ng model na sumisipi sa transcript. Ang mga ito ay mga raw/response-class o
opt-in na surface na nasa labas ng saklaw ng persisted-request-body + Memory ng P1.
Ang internal na lifecycle ng /api/modality-bridge/video/drilldown ay isang hiwalay at
loopback/token-authenticated na cache substrate. Nangangailangan din ang bawat operasyon ng
canonical opaque principal ID. Bago i-enable ang isang production caller, dapat nitong
i-derive ang ID na iyon mula sa authenticated tenant at hindi ito dapat kailanman mag-forward
ng value na pinili ng client. Ibinibigkis ng mga cache key ang principal na iyon sa mga
canonical session at video-reference ID, iniimbak lamang ang kanilang mga key na hango sa
SHA-256, at nililimitahan ang saklaw ng mga read at deletion sa parehong principal. Nag-iimbak
ang cache ng hindi hihigit sa 16 na derived JPEG frame sa bawat entry, ine-expire ang mga ito
pagkalipas ng sampung minuto, at sumusuporta sa bounded na start/end read o tahasang
pag-delete ng session.
Ang bawat principal ay limitado sa 16 na entry at 64 MiB ng canonical JPEG data. Hiwalay ang mga limitasyong iyon sa global na ceiling na 64 na entry/256 MiB: ang pressure mula sa principal quota ay nag-e-evict lamang ng least-recently-used na mga entry ng principal na iyon bago isaalang-alang ang global LRU eviction. Inaalis ang mga expired na entry mula sa principal at global accounting kapag may aktibidad sa cache, samantalang ang cancellation at validation failure ay hindi nagko-commit ng bahagyang replacement.
Tinatanggihan ng cache ang non-canonical Base64, sobrang padding, non-JPEG media, malformed o
truncated na mga JPEG, at mga JPEG na naglalabas ng warning sa panahon ng bounded full-image sharp
decode. Muli nitong ine-encode ang bawat tinanggap na image bilang canonical JPEG, kinukuha ang width
at height mula sa decoded bytes sa halip na pagkatiwalaan ang mga field ng caller, at itinatapon ang
anumang trailing polyglot bytes sa halip na panatilihin ang mga ito. Ang bounded canonical compressed
buffer lamang ang ibinibilang sa parehong quota. Kabilang sa JSON wire limit ang Base64 overhead para
sa 32 MiB na decoded-input ceiling. Ang bawat
nakaimbak na derivation ay nagtatala ng validated nitong JPEG format/resolution, sampling policy,
derivation version, creation time, content hash na kinompyut ng server, at hashed parent
reference kasama ang parent-content hash ng pinagkakatiwalaang caller. Sinusuri ang cancellation
sa pagitan ng mga asynchronous decode/hash phase bago ang atomic cache commit.
Hindi pa ikinokonekta ng tranche na ito ang isang production producer sa route at hindi ito nagbibigay ng multi-resolution variant selection. Samakatuwid, walang idinaragdag na trabaho ang transparent na Video Bridge request path, habang ang tenant-bound principal derivation at ang buong FU-08 multi-resolution lifecycle ay nananatiling tahasang follow-up na gawain sa halip na maidokumento bilang kumpletong behavior.
Ang mga frame ay nilalagyan ng caption nang sunod-sunod gamit ang naka-configure na Video model. Ang walang lamang
Video override ay nagmamana sa setting ng Vision; kung parehong walang laman, pipiliin ng Vision
auto-router ang aktuwal na model na may kakayahang pang-vision. Pinapalitan ng matagumpay na mga caption
ang orihinal na bahagi gamit ang isang matatag na prefix na [Video description: na
nagmamarka rin sa text bilang hindi pinagkakatiwalaang obserbasyong nagmula sa media at nagsasabi sa mga downstream
model na huwag sundin ang mga tagubiling matatagpuan sa media. Kasama sa mga frame-caption cache key
ang mga JPEG byte, prompt, timestamp, at aktuwal na model; ang matagumpay na
mga caption lamang ang kina-cache. Pinapanatili ng mga cache entry ang aktuwal na matagumpay na producer model,
kabilang ang isang fallback model; nag-uulat ang bridge ng mixed kapag ginawa ang magkakaibang frame
ng magkakaibang model. Muling ginagamit ng isang cache hit ang pagkakakilanlan ng producer na iyon
sa halip na muling lagyan ito ng label bilang hiniling na routing plan. Ang whole-video result
cache ay may key batay sa bawat input na nagbabago sa output — prompt, aktuwal na
model, sampling policy, bilang ng frame, semantic analysis mode, SHA-256
fingerprint ng normalized focus hint, focus window, transcript,
audioTranscript, at contact-sheet flag — kaya ang pagbabago sa alinman sa mga
dimensyong iyon ay isang cache miss, at hindi kailanman muling paggamit ng lipas na data. Ang bersyon,
threshold, at may hangganang bilang ng candidate frame ng visual dedup policy ay tahasan ding kasama sa
result-cache key at metadata; samakatuwid, hindi maaaring muling gumamit ang pagbabago sa policy ng lipas na
whole-video description. Pinapanatili ng result-cache v4 metadata ang mode at
fingerprint, ngunit hindi kailanman ang raw na gawain ng user. Iniuulat ng guardrail metadata ang parehong
hiniling at aktuwal na analysis mode; ang hiniling na focused mode na walang
magagamit na text ng user ay iniuulat bilang aktuwal na full.
Kinukuha ng guardrail ang bawat sinusuportahang bahagi ng video ngunit naglalarawan ng hindi hihigit sa
modalityBridgeVideoMaxVideos. Para sa isang target na napatunayang may
supportsVideo === false, ang mga nabigo at lumampas-sa-limitasyong video ay nagiging tahasang ligtas na
mga text marker upang walang raw na video ang manatili. Kapag hindi alam ang capability, ang mga bahaging iyon
ay nananatiling hindi binabago. Nilalampasan ng mga target na may supportsVideo === true ang bridge.
Ang abort signal ng client request ay ipinapasa sa pag-download, broker queue,
mga subprocess, at mga caption call; humihinto ang mga abort sa pagitan ng mga video at hindi kailanman
nagfa-fail open tungo sa raw media.
Ang mga runtime setting ay DB-backed at vina-validate ng Zod:
| Key | Default | Saklaw / gawi |
|---|---|---|
modalityBridgeVideoEnabled |
false |
Opsyonal na runtime, kailangang tahasang i-enable |
modalityBridgeVideoAnalysisMode |
"full" |
Pinapanatili ng full ang mga generic na caption; gumagamit ang focused ng limitado at hindi pinagkakatiwalaang pinakabagong konteksto ng user |
modalityBridgeVideoModel |
"" |
Minamana ang Vision Bridge model |
modalityBridgeVideoFrameCount |
8 |
1–16 |
modalityBridgeVideoSamplingPolicy |
"uniform" |
uniform, scene_aware, o proporsyonal na segment_aware; bumabalik sa uniform kapag nabigo ang detector |
modalityBridgeVideoMaxVideos |
1 |
1–4 |
modalityBridgeVideoTimeout |
120000 |
1000–120000 ms |
Ang mga legacy na naka-persist na Video timeout value na lampas sa 120 segundo ay nililimitahan sa
broker deadline; tinatanggihan ang mga bagong pagsusulat ng setting na lampas sa limitasyong iyon.
Nangangailangan ang GET /api/modality-bridge/video/runtime ng pinagkakatiwalaang stamped loopback
locality bago ang authentication o runtime probing, at pagkatapos ay nangangailangan ng management
auth. Ibinabalik lamang nito ang available, mga nalinis na bersyon ng FFmpeg/ffprobe, at isang nakapirming
dahilan kapag hindi available ang runtime. Ang internal extraction endpoint ay hindi
isang pampublikong upload API: nagbabalik ang queue saturation ng 503 kasama ang Retry-After, ang pagdiskonekta ng caller
ay nagbabalik ng 499, at ang nakapirming broker deadline ay nagbabalik ng 504. Idinaragdag ng mga na-convert na response ang
video->text;model=<visionModel>;parts=<videos> sa sentral na
x-omniroute-modality-bridge header nang hindi inaalis ang mga segment ng Vision o Audio.
PII Masker (piiMasker.ts)
Tumatakbo sa parehong stage.
preCallay nagko-clone ng payload, binabagtas angsystem,messages,input, atprompt(kabilang ang mga plain string item), at inilalapat angprocessPII()(mula sa@/shared/utils/inputSanitizer) sa mga string nacontent/textfield. KapagPII_REDACTION_ENABLED=true, nire-redact ang natukoy na PII sa outbound payload. Hindi ito nakadepende saINPUT_SANITIZER_MODE(na kumokontrol lamang sa prompt-injection policy). Kapag naka-off ang redaction, itinatala ng call ang bilang ng mga detection nang hindi muling isinusulat ang content.postCallay gumagawa ng deep clone ng response, pinapatakbo angsanitizePIIResponse()kasama ang Responses-API-shape masker (maskResponsesOutput— sinasaklaw angoutput_textatoutput[].content[].text). Kung may anumang redaction na mangyari, papalitan ng binagong response ang orihinal.
Hindi kailanman nagba-block ang guardrail; naglalagay lamang ito ng annotation (meta.detections,
meta.redacted) o nagsusulat muli.
Prompt Injection (promptInjection.ts)
Tinutukoy ang mga adversarial na istruktura sa content na ibinigay ng user at ipinapatupad ang naka-configure na policy. Ang gawi ay pinamamahalaan ng mga environment variable at constructor option:
| Setting | Env var | Default | Epekto |
|---|---|---|---|
| Naka-enable | INPUT_SANITIZER_ENABLED |
true |
Kapag false, agad na lalaktawan ng guardrail ang pagproseso. |
| Mode | INJECTION_GUARD_MODE / INPUT_SANITIZER_MODE |
warn |
Patakaran sa injection: block, warn, o log. (Tinatanggap ang redact para sa backward compatibility ngunit hindi nito inaalis ang injection text; kinokontrol ng PII_REDACTION_ENABLED ang muling pagsulat ng PII sa request.) |
| Threshold ng pag-block | blockThreshold option / INPUT_SANITIZER_BLOCK_THRESHOLD (alias INJECTION_GUARD_BLOCK_THRESHOLD) |
high |
Pinakamababang severity na kinakailangan upang mag-block. Observe-only ang Medium sa default. |
Precedence ng mode (getMode): options.mode ng caller →
INJECTION_GUARD_MODE DB feature-flag override (Dashboard → Settings →
Feature Flags) → INJECTION_GUARD_MODE env → INPUT_SANITIZER_MODE env →
warn. Samakatuwid, nangingibabaw ang dashboard override sa mga env var, kaya
live na kinokontrol ng Feature Flags UI ang tumatakbong guard (hindi kailangan
ng restart). Fail-safe ang pagbasa sa DB: kung magka-error ito, babalik ang guard
sa behavior na nakabatay sa env, at kapag walang nakatakdang override, kapareho
ang behavior ng env-only resolution.
Mga pinagmumulan ng detection:
sanitizeRequest()mula sa@/shared/utils/inputSanitizer(nakabahaging detector set na ginagamit sa ibang bahagi ng pipeline).- Built-in na
DEFAULT_GUARD_PATTERNS(kasalukuyangsystem_override_inlineatmarkdown_system_block, na parehong mayhighseverity). - Opsyonal na
customPatternsna ipinapasa sa pamamagitan ng constructor options (mga string, regex, o{ name, pattern, severity }record).
Kapag mode === "block" at may kahit isang detection na umabot sa severity
threshold, ibinabalik ng preCall ang { block: true, message: "Request rejected: suspicious content detected" }. Sa mga mode na warn/log, nagla-log ang
guardrail ngunit pinapayagan ang call. Ini-export din ang nakabahaging helper na
evaluatePromptInjection() para sa mga caller na kailangang magsuri ng mga
prompt nang hindi dumaraan sa registry.
Hangganan ng scan (v3.8.20): sinusuri lamang ng detector ang unang 16 KB
ng pinagsamang prompt text — MAX_INJECTION_SCAN_BYTES = 16 * 1024 (16 384 bytes)
sa src/shared/utils/inputSanitizer.ts. Parehong nagsasagawa ang
detectInjection() at evaluatePromptInjection() ng
slice(0, MAX_INJECTION_SCAN_BYTES) bago patakbuhin ang pattern loop. Karaniwang
nasa itaas na bahagi ng input ang mga injection directive, kaya nililimitahan
nito ang paggamit ng regex sa CPU/GC para sa mga payload na daan-daang KB ang
laki nang hindi pinapahina ang detection (tingnan ang #3932, #4041).
Credential Masker (credentialMasker.ts)
Tumatakbo sa parehong stage at huli sa default chain (priority 95).
Nagre-redact ito ng mga kilalang pattern ng API key / secret token mula sa
outbound payload (content ng message, mga argument ng tool call, mga resulta ng
tool) at sa response ng provider, upang hindi mai-leak sa upstream provider
o pabalik sa client ang credential na na-paste sa prompt (o ibinalik ng isang
tool result).
- Opt-in lamang, kaparehong convention ng PII redaction (malapit sa Hard Rule
#20): naka-disable maliban kung
settings.credentialRedactionEnabled === trueoCREDENTIAL_REDACTION_ENABLED=true. Kapag naka-off ito, no-op ang guardrail — hindi ito kailanman nagba-block o muling nagsusulat. - Nilalakad ng
redactCredentials()ang buong payload/response tree (walkValue(), ligtas laban sa prototype pollution, ligtas laban sa cycle sa pamamagitan ngWeakSet) at pinapalitan ang mga match ng placeholder na[REDACTED:<type>], habang kino-clone lamang ang mga branch na aktuwal na nagbago. - Saklaw ng
CREDENTIAL_PATTERNSang mga key ng LLM provider (OpenAI, OpenAI-proj, Anthropic, Google, Hugging Face, Replicate), mga VCS/SaaS token (GitHub, Slack, Linear, Notion, npm, Postman, Discord), mga payment key (Stripe, Square), mga cloud key (AWS access key, Twilio, SendGrid, Mailgun), mga private key / JWT, mga connection string na may credential (mongodb://user:pass@..., atbp.), at generic na pattern para sa header-value naAuthorization/x-api-key/api-key/apikey. Ang mga key na hugis-header (authorization,x-api-key,api-key,apikey) ay nire-redact sa estruktural na paraan (value lamang, habang pinapanatili ang scheme prefix tulad ngBearer/Basic) sa halip na sa pamamagitan ng generic na text regex. - Hindi kailanman nagba-block ang guardrail; nagsusulat lamang itong muli
(
modifiedPayload/modifiedResponse) at naglalagay ng annotation (meta.credentialsRedacted,meta.count).
Regression guard: tests/unit/credential-masker-guardrail.test.ts.
Batayang Kontrata (base.ts)
class BaseGuardrail {
enabled: boolean;
name: string;
priority: number;
constructor(name: string, options?: { enabled?: boolean; priority?: number });
async preCall(payload: unknown, context: GuardrailContext): Promise<GuardrailResult | void>;
async postCall(response: unknown, context: GuardrailContext): Promise<GuardrailResult | void>;
}
interface GuardrailResult<TValue = unknown> {
block?: boolean; // kapag true, agad na itinitigil ang chain
message?: string; // ipinapakita kapag bina-block
meta?: Record<string, unknown> | null;
modifiedPayload?: TValue; // ibinabalik ng preCall upang baguhin ang request
modifiedResponse?: TValue; // ibinabalik ng postCall upang baguhin ang response
}
interface GuardrailContext {
apiKeyInfo?: Record<string, unknown> | null;
disabledGuardrails?: string[] | null;
endpoint?: string | null;
headers?: Headers | Record<string, unknown> | null;
log?: GuardrailLog | Console | null;
method?: string | null;
model?: string | null;
provider?: string | null;
signal?: AbortSignal;
sourceFormat?: string | null;
stream?: boolean;
targetFormat?: string | null;
}
Ipinahihiwatig ng isang guardrail na "walang pagbabago" sa pamamagitan ng pagbabalik ng void, {}, o
{ block: false }. Kapag nagbalik ng modifiedPayload/modifiedResponse, papalitan nito
ang value na dumadaloy sa chain para sa mga kasunod na guardrail.
Dinadala ng signal?: AbortSignal ang lifecycle ng caller papunta sa mga guardrail. Ang pag-abort ng request ang sinasadyang fail-open exception: itinitigil ng mga media bridge ang trabaho at nagsasagawa ng cleanup nang hindi ibinabalik ang raw media sa isang target na alam nang hindi sumusuporta rito.
Registry (registry.ts)
Inilalantad ng singleton na guardrailRegistry ang:
register(guardrail)— nagdaragdag ng guardrail (o pinapalitan ito ayon sa normalized na pangalan) at muling inaayos ayon sa pataas napriority.clear()/list()— mga administratibong helper.runPreCallHooks(payload, context)— inuulit ang bawat aktibong guardrail, ipinapasa ang payload sa pamamagitan ngmodifiedPayload, at humihinto sa unangblock: true.runPostCallHooks(response, context)— kaparehong daloy sa panig ng response.resetGuardrailsForTests({ registerDefaults })— nililinis ang state at opsyonal na muling nirerehistro ang mga default para sa malinis na test isolation.
Ang parehong runner ay nagbabalik ng { blocked, payload|response, results, guardrail?, message? }
kung saan ang results ay isang array ng mga record na GuardrailExecutionResult na may
mga field na blocked, skipped, modified, error, at meta para sa bawat guardrail,
na kapaki-pakinabang para sa tracing.
Pag-disable ng Mga Guardrail sa Bawat Request
Pinagsasama-sama ng resolveDisabledGuardrails({ apiKeyInfo, body, headers }) ang isang
de-duplicated na listahan ng mga pangalan ng guardrail na dapat laktawan para sa kasalukuyang
request. Mga source (lahat ay opsyonal, lahat ay pinagsasama):
apiKeyInfo.disabledGuardrailsdisabledGuardrailssa request body (top-level)metadata.disabledGuardrailssa request body- Header na
x-omniroute-disabled-guardrails(o ang legacy nax-disabled-guardrails)
Maaaring mga array ng string o comma-separated string ang mga value; ang mga pangalan ay
ino-normalize sa lowercase kebab-case (pii_masker → pii-masker). Ipinapasa
ang resulta sa registry sa pamamagitan ng context.disabledGuardrails, na lumalaktaw sa
mga tumutugmang guardrail (skipped: true sa results).
Pagkakasunod-sunod ng Pagpapatupad
Para sa bawat request na dumadaan sa src/sse/handlers/chat.ts at
open-sse/handlers/chatCore.ts:
- Binubuo ng
resolveDisabledGuardrails(...)ang listahan ng lalaktawan mula sa API key, body, at mga header. - Pinapatakbo ng
guardrailRegistry.runPreCallHooks(body, ctx)ang mga guardrail ayon sa pataas na pagkakasunod-sunod ng priority:- Itinatala bilang
skippedang mga naka-disable na guardrail. - Maaaring baguhin ng
preCallng bawat guardrail ang payload sa pamamagitan ngmodifiedPayload. - Ang unang
block: trueay agad na nagpapatigil sa chain at nagbabalik ang handler ng tugon ng pagtanggi mula sa guardrail.
- Itinatala bilang
- Ang payload na maaaring nabago ay ipinapasa sa combo routing at upstream dispatch.
- Pagkatapos mabuo ang tugon, pinapatakbo ng
guardrailRegistry.runPostCallHooks(...)ang parehong chain sa tugon. Kapagblock: truedito, hindi ipinapasa ang upstream na tugon.
Ang mga guardrail na nag-throw ay itinatala gamit ang error: <message> at nila-log sa pamamagitan ng
logger.warn, ngunit nagpapatuloy ang chain — sadyang fail-open ang disenyo.
Configuration
Mga environment variable na binabasa ng mga built-in na guardrail:
| Variable | Ginagamit ng | Epekto |
|---|---|---|
INPUT_SANITIZER_ENABLED |
prompt-injection |
Itakda sa false upang ganap na i-disable ang pagtukoy. |
INPUT_SANITIZER_MODE |
prompt-injection |
Patakaran sa injection: warn, block, o log. Hindi binabago ng legacy na value na redact ang teksto ng injection. |
INJECTION_GUARD_MODE |
prompt-injection |
Mode para sa injection guard; isa ring DB feature flag na nangingibabaw sa mga env var (DB > ENV). |
INPUT_SANITIZER_BLOCK_THRESHOLD |
prompt-injection |
Pinakamababang severity na tinatanggihan ng MODE=block: high (default), medium, o low. |
INJECTION_GUARD_BLOCK_THRESHOLD |
prompt-injection |
Legacy na alias para sa INPUT_SANITIZER_BLOCK_THRESHOLD. |
PII_REDACTION_ENABLED |
pii-masker |
Kapag true, nire-redact ang PII ng request (hiwalay sa injection mode). |
PII_RESPONSE_SANITIZATION / _MODE |
pii-masker (downstream) |
Kinokontrol ang gawi ng masker sa panig ng tugon. |
Binabasa ng mga guardrail ng Modality Bridge ang runtime config mula sa DB-backed na settings
store (getSettings()), hindi mula sa mga env var. Ang mga pangunahing key ng Vision ay
modalityBridgeVisionEnabled, modalityBridgeVisionMode,
modalityBridgeVisionModel, modalityBridgeVisionTaskAware,
modalityBridgeVisionPrompt, modalityBridgeVisionTimeout,
modalityBridgeVisionMaxImages, modalityBridgeVisionMaxChars,
modalityBridgeCacheEnabled, modalityBridgeCacheTtlMinutes, at
modalityBridgeCacheMaxEntries. Tinatanggap lamang ang mga legacy na
visionBridge* key bilang dokumentadong one-cycle read
fallback; ginagamit ng mga write mula sa dashboard ang mga pangunahing key. Ang mga default at fallback
resolver ay nasa src/shared/constants/modalityBridgeDefaults.ts, habang pinananatili ang mga legacy
constant sa src/shared/constants/visionBridgeDefaults.ts.
Ginagamit ng Audio ang modalityBridgeAudioEnabled, modalityBridgeAudioModel,
modalityBridgeAudioTimeout, at modalityBridgeAudioMaxClips, kasama ang mga shared na
setting na modalityBridgeCache*. Walang fallback para sa legacy key ang Audio dahil ipinakilala ang mga
key na ito kasama ng schema ng Modality Bridge.
Ginagamit ng Video ang modalityBridgeVideoEnabled, modalityBridgeVideoAnalysisMode,
modalityBridgeVideoModel,
modalityBridgeVideoFrameCount, modalityBridgeVideoSamplingPolicy,
modalityBridgeVideoMaxVideos, at
modalityBridgeVideoTimeout, kasama ang mga shared na setting na modalityBridgeCache*.
Naka-disable ito bilang default dahil opsyonal na operational
dependency ang FFmpeg/ffprobe at nagdaragdag ng latency at gastos sa model ang paglalagay ng caption sa mga frame.
Mga Custom na Guardrail
import { BaseGuardrail, guardrailRegistry } from "@/lib/guardrails";
class BudgetGuardrail extends BaseGuardrail {
constructor() {
super("budget", { priority: 50 });
}
async preCall(payload, ctx) {
if (ctx.apiKeyInfo?.budgetExceeded) {
return { block: true, message: "Daily budget exceeded" };
}
return { block: false };
}
}
guardrailRegistry.register(new BudgetGuardrail());
Mga hakbang:
- Gumawa ng
src/lib/guardrails/myGuardrail.tsna nag-e-extend saBaseGuardrail. - Ipatupad ang
preCallat/opostCall. - Magrehistro sa oras ng pag-import (i-push mula sa
registerDefaultGuardrails) o tawagin angguardrailRegistry.register(...)sa runtime — pinapalitan ng registry ang anumang naunang guardrail na may parehong normalized na pangalan. - Magdagdag ng mga test sa ilalim ng
tests/unit/(mga kasalukuyang halimbawa:tests/unit/guardrails-registry.test.ts,tests/unit/prompt-injection-guard.test.ts,tests/unit/guardrails/visionBridge.test.ts).
Pagsubok
Gamitin ang resetGuardrailsForTests() sa pagitan ng mga test upang magsimula mula sa isang tiyak na state.
Ipasa ang { registerDefaults: false } upang magsimula sa isang walang-lamang registry at
irehistro lamang ang mga guardrail na sinusubok. Tumatanggap ang Vision Bridge ng dependency
injection (deps.getSettings, deps.callVisionModel); inilalantad ng Audio Bridge ang
mga katumbas na seam para sa mga setting, capability, pagpili ng STT model, pagsusuri ng
credential, at transcription. Dahil dito, maaaring subukan ng mga test ang parehong flow nang walang
access sa DB o network.
Tingnan Din
src/lib/guardrails/— implementasyonsrc/shared/utils/inputSanitizer.ts— nakabahaging detector na nagpapatakbo sa prompt-injection at PII maskingsrc/shared/constants/visionBridgeDefaults.ts— mga default ng Vision Bridge at listahan ng mga model na sapilitang gumagamit ng bridgesrc/shared/constants/modalityBridgeDefaults.ts— mga nakabahaging runtime default ng Vision/Audiodocs/architecture/RESILIENCE_GUIDE.md— orthogonal na layer (circuit breaker, mga cooldown)docs/reference/ENVIRONMENT.md— kumpletong sanggunian ng env var
Saklaw ng route at red-team para sa injection-guard (Phase 8 · Block D)
Saklaw ng injection-guard (createInjectionGuard / withInjectionGuard) ang lahat ng route
na tumatanggap ng mga prompt ng user. Sinusunod nito ang INJECTION_GUARD_MODE (default na warn = pag-log lamang;
block = nagbabalik ng HTTP 400 SECURITY_001).
| Uri | Mga Route | Default na mode |
|---|---|---|
| Text (kasalukuyan) | /v1/chat/completions, /v1/completions, /v1/relay/chat/completions |
warn |
| Generative | /v1/messages, /v1/responses, /v1/images/generations, /v1/images/edits, /v1/videos/generations, /v1/music/generations, /v1/audio/speech |
warn |
| Data | /v1/embeddings, /v1/rerank, /v1/search, /v1/moderations |
warn |
Saklaw ng pagkuha ng text (extractMessageContents) ang messages/input/prompt/query+documents/instructions/system.
Red-team (gabi-gabi, nightly-llm-security.yml): bine-validate ng promptfoo na bina-block ng bawat route
ang OWASP-LLM corpus kapag INJECTION_GUARD_MODE=block; nagpapatakbo ang garak ng mga probe (nilalaktawan kapag walang secret).
Kasama ang moderations para sa consistency — maaari itong i-exempt ng mga operator sa block-mode sa pamamagitan ng
resolveDisabledGuardrails.
May dalawang job ang nightly workflow (.github/workflows/nightly-llm-security.yml, cron + manual
dispatch):
promptfoo-guard(blocking) — pinapatakbo angpromptfoo eval -c promptfooconfig.yamlgamit angINJECTION_GUARD_MODE=block. Tinitiyak ng bawat adversarial na kaso (hal. "ignore all previous instructions…", mga DAN-style jailbreak) na may taglay naerror.code === "SECURITY_001"ang response, ibig sabihin, talagang tinanggihan ng guard ang request.garak(advisory) — pinapatakbo ang garak--probes promptinject,dan,leakreplaylaban sa isang lokal na instance ng OmniRoute (http://localhost:20128/v1). Nakadepende ito sa isang provider secret (PROMPTFOO_PROVIDER_KEY); maayos itong lumalaktaw at nilalagyan ng suffix na|| true, kaya nag-uulat ito nang hindi pinapabagsak ang CI.
Saklaw ng guard helper (createInjectionGuard / withInjectionGuard)
ang bawat /v1 route na may prompt; kinukuha ang text ng prompt mula sa
messages/input/prompt/query+documents/instructions/system ng
extractMessageContents() sa src/shared/utils/inputSanitizer.ts.