fix(media): gate inbound audio on structured media facts#111315
Conversation
hasInboundAudio previously accepted <media:audio> placeholder bodies, [Audio transcript headers, and filename sniffing alongside MediaTypes. It now consumes only the structured facts channels already carry (MediaType/MediaTypes, kind audio or audio/*), removing the string reverse-engineering ahead of the placeholder-elimination program. Discord — the one channel with a coverage hole — now carries its native audio classification (MIME, voice fields, constrained filename fallback) as structured kind: "audio", with definitive fetched/declared MIME precedence so generic container types cannot erase declared audio and filename hints cannot override definitive non-audio MIME.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6c6160ba9f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const mime = normalizeMimeType(contentType); | ||
| const kind = | ||
| mime?.startsWith("audio/") || | ||
| hasDiscordVoiceAttachmentFields(params.attachment) || |
There was a problem hiding this comment.
Honor definitive MIME before native voice fields
When an attachment has duration_secs or waveform but the downloaded bytes resolve to a definitive non-audio MIME such as image/png, this unconditional branch still sets kind to audio; line 123 then discards the authoritative fetched MIME, causing the image/document to be projected as audio and routed to transcription. This also contradicts resolveEffectiveMediaType, which explicitly gives definitive fetched MIME highest precedence. Apply native voice classification only when the effective MIME is absent or non-definitive, as the filename fallback already does.
Useful? React with 👍 / 👎.
|
Merged via squash.
|
…1315) hasInboundAudio previously accepted <media:audio> placeholder bodies, [Audio transcript headers, and filename sniffing alongside MediaTypes. It now consumes only the structured facts channels already carry (MediaType/MediaTypes, kind audio or audio/*), removing the string reverse-engineering ahead of the placeholder-elimination program. Discord — the one channel with a coverage hole — now carries its native audio classification (MIME, voice fields, constrained filename fallback) as structured kind: "audio", with definitive fetched/declared MIME precedence so generic container types cannot erase declared audio and filename hints cannot override definitive non-audio MIME.
What Problem This Solves
hasInboundAudio— the gate that decides whether an inbound message carries audio for transcription/voice handling — reverse-engineered presentation text: it matched<media:audio>placeholder bodies,[Audiotranscript headers, and audio-looking filenames in addition to the structuredMediaType/MediaTypesfields. This is PR1 of the<media:kind>placeholder-elimination program: before channels stop minting placeholder bodies, nothing in core may depend on them for behavior.Why This Change Was Made
hasInboundAudionow consumes only structured facts: normalizedMediaType/MediaTypesaccepting the structured kindaudiooraudio/*MIME (case-insensitive, parameters stripped). The placeholder regex, header regex, and filename inference are deleted (net −10 prod LOC in core).<media:strings; table with file:line cites in the audit summary below) proved every audio-capable channel populates structured media types — except one hole: Discord, when a download fails, could leave a voice-classified attachment with a usable remote URL but no MIME. Discord now carries its native audio classification as structuredkind: "audio"with deliberate precedence: definitive fetched MIME > definitive declared MIME > generic container types (application/octet-stream,binary/octet-stream,application/ogg); filename inference applies only when the effective MIME is absent/non-definitive; definitive non-audio MIME is never dropped or overridden. The rendered placeholder now derives from the same classification, so text and structured facts cannot diverge.User Impact
Voice-message transcription now triggers on the same prepared facts channel ingress already carries, for every bundled channel. Discord voice messages with failed downloads or generic container MIME are now correctly classified as audio (previously possible false negative), and documents misnamed
*.oggare no longer routed into audio-only understanding (previously possible false positive).Evidence
node scripts/run-vitest.mjs: newinbound-media.test.ts6/6 (structured detection, placeholder/filename non-inference),get-reply.message-hooks.test.ts18/18 (filename-inference contract flip), Discordmessage-utils.test.ts59/59 (MIME-conflict, generic-container, native-voice, fetched-override, pdf-named-.ogg cases); reran post-rebase onto origin/main.