feat(video): redact transcript text from logs and durable memory (#12150 P1) (#12427)

P1 of #12150: transcript text no longer reaches call logs or durable memory in the clear.

Reconciled on merge — the two persisted-requestBody assertions were failing, and the failure signature was misleading enough to be worth recording. They reported "expected: true, actual: false", which reads like the redaction not applying. It was not: pollForCallLog waited at most 120 tries x 20ms = 2.4s for the asynchronous SQLite write, then returned null, so assert.ok(row) failed before any redaction assertion ran. The observed durations were 5253ms and 4467ms against that 2.4s ceiling — a starved runner, not a leak. The control test failing alongside the positive one was the tell: a real redaction defect would break one direction, not both.

Replaced the fixed try count with a 30s wall-clock deadline: far past any healthy write, still bounded, and a fast machine still returns on the first pass. A privacy test should not depend on how busy the box is.

Verified: 4/4 three consecutive times under synthetic load, and 3/3 unloaded beforehand. Note the synthetic load reached ~7, below the ~38 where the original failure appeared, but the budget is now 12.5x larger and deadline-based rather than count-based.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-09-02 10:19:56 -03:00
committed by GitHub
parent 53b037051b
commit 5ab1e9fe5c
15 changed files with 1150 additions and 67 deletions

View File

@@ -476,6 +476,24 @@ fusion counters. The default Video Bridge path does not invoke speech-to-text
or download a second media copy; without that explicit track, it remains
video-only.
**Transcript retention (opt-in feature, #12150 P1).** When a request renders any
transcript cue (a caller-declared `transcript` or a fused `audioTranscript`), the
guardrail marks it `videoBridgeObserved` and produces a redacted shadow of the
video description — an identical rendering in which every cue's free-text body is
replaced by `[redacted-video-transcript]`, built by substituting the structured
cue field before the string is assembled (never by parsing the flattened text, so
no cue content — adversarial or ordinary, including bodies containing `]` such as
`[inaudible]`/`[music]` — can survive). The persisted call-log request body swaps
each video-derived text part for that redacted shadow, matched by content
equality (so it stays correct even after system-prompt/handoff/memory injection
reshapes the message array); the body sent upstream to the model is unchanged.
An observed request also populates no durable Memory (both request- and
response-derived extraction are skipped), so the model's own reply cannot echo
transcript text into Memory. Two further retention surfaces — the raw
pre-guardrail client-request snapshot in the detailed-log artifact and
`previous_response_id` continuation fail-closed — are tracked for a follow-up
(P2) and are not yet closed.
The internal `/api/modality-bridge/video/drilldown` lifecycle is a separate,
loopback/token-authenticated cache substrate. Every operation also requires a
canonical opaque principal ID. Before a production caller is enabled, it must