docs(media): record voice duration boundary defect and fix plan

This commit is contained in:
evgeny committed 2026-10-24 17:26:11 +02:00
1 parent 80558f6686
commit 4177ab3536
2 files changed
+68 -2

No files matched your search

+55 -2
View File
@@ -1,6 +1,7 @@
Аудит media_async / media_delivery — 2026-10-24
Статус: подтверждённый дефект исправлен; полный аудит двух каталогов ещё не завершён.
Ниже сохранены исходное воспроизведение и согласованный проект; результаты исправления — в конце.
Статус: encrypted_file исправлен; продолжение аудита подтвердило отдельный дефект границы voice_file.
Полный аудит двух каталогов ещё не завершён. Новый дефект и проект исправления — в конце.
Ниже сохранены исходное воспроизведение, согласованный проект и результаты исправления encrypted_file.
Подтверждённый дефект: исходник уничтожается через другое имя того же файла
@@ -209,3 +210,55 @@ media_delivery_chat, dm_media, dm_worker, services.
Проверка реализации не выявила противоречий владения в перечисленных сценариях.
Частичные отметки остальных файлов аудита сохраняются; этот фикс не означает полного
завершения проверки media_async/media_delivery или закрытия старых нестабильных тестов.
Продолжение аудита — 2026-10-24: граница длительности voice_file
voice_file.h обещает максимум24ч; attachment_validate (attachment.c:35) отвергает
duration_ms >86400000. Однако voice_file.c:16 проверяет samples/channels/rate >86400:
целочисленное деление отбрасывает долю секунды. Записи с полными кадрами на24ч+20..980мс
проходят проверку аргументов. Затем voice_file.c:37 вычисляет точную длительность
в миллисекундах по числу20мс кадров, уже выходящую за предел метаданных.
attachment_send.c вызывает voice_file_encode в worker, а attachment_validate —
при публикации результата. При успешном полном кодировании такой результат будет
отклонён после подготовки файла. Это дефект границы записей длиннее суток;
сбой обычных коротких записей или потеря данных этим опытом не установлены.
Диагностическое воспроизведение на настоящем voice_file_encode из src/libutun.a:
- /tmp/media-voice-duration-repro.c и .mk; сборка через tests/Makefile и его библиотеки/флаги.
- Linux64: виртуальный read-only PCM достаточного размера, без чтения или заполнения.
Linker wrapper opus_codec_encoder_create фиксирует достижение кодировщика
и возвращает NULL до чтения PCM/открытия output. Реальная проверка аргументов не подменена.
- Частоты8000/12000/16000/24000/48000, mono/stereo; для каждой пары проверены
24ч-20мс, ровно24ч, +19мс хвоста, +20мс, +980мс и +1000мс: всего60 случаев.
- Ровно24ч и +19мс хвоста проходят, так как хвост короче полного кадра отбрасывается;
+1000мс отвергается до encoder. На +20/+980мс во всех10 сочетаниях codec достигнут,
тогда как attachment_validate соответствующей длительности возвращает-1:
duration_guard_mismatches=20, confirmed=1.
- Все60 вызовов возвращают-1: для допустивших encoder это намеренная инъекция отказа,
для +1000мс — штатная валидация. Опыт доказывает ошибку допуска к encoder,
но не является24-часовым кодированием или сквозной проверкой отправки такого файла.
- Полный журнал с media=info/debug=info: /tmp/media-voice-duration-repro.log;
сборка: /tmp/media-voice-duration-build.log. Проектные .c/.h не менялись.
Проект простого исправления:
1. Задать один ATTACHMENT_DURATION_MAX_MS=86400000 в attachment.h; использовать
в валидаторе voice/video и проверке video completion вместо отдельных литералов.
2. После проверки rate/channels считать frame_samples=(rate/50)*channels,
frames=count/frame_samples. До создания encoder/открытия файла отклонять
frames<25 либо frames>ATTACHMENT_DURATION_MAX_MS/20 (4320000).
Проверяется длительность записываемых полных кадров, хвост <20мс по-прежнему отбрасывается.
3. Только после ограничения frames считать samples=frames*frame_samples
и duration_ms=frames*20. Размер samples не превосходит count, длительность
помещается в uint32_t; большие count не требуют потенциально переполняющего умножения на20.
4. Сообщение раннего отказа различает неверные параметры и недопустимую длительность;
для длительности выводит count/rate/channels/frames и разрешённые границы.
Дополнительный helper/API или изменение pipeline/формата не нужны.
5. В test_attachment добавить проверку границ500мс/24ч, хвоста <20мс,
превышения на полный кадр, разных rate/channels и раннего отказа без изменения файла/метаданных.
Верхние границы проверять диагностической точкой до encoder без реального кодирования суток;
сохранить существующий настоящий Opus roundtrip короткой записи.
Аудит остановлен по AGENTS.md:10 после подтверждения и подготовки проекта исправления.
Рабочий код не исправлялся. voice_file.h и attachment.h остаются [~]; оставшаяся
повторная проверка media_delivery не выполнялась. Новый общий тестовый/sanitizer-прогон
не запускался: в этом продолжении изменены только записи аудита, диагностика находится в /tmp.
+13
View File
@@ -4,6 +4,19 @@
## Текущие задачи
[ ] **media_async voice_file: согласовать верхнюю границу длительности с метаданными** — подтверждено 24.10.2026.
Проверка samples/channels/rate >86400 пропускает полные кадры 24ч+20..980мс,
хотя attachment_validate отклоняет duration_ms >86400000. В штатном pipeline это означает
лишнюю подготовку файла перед отказом публикации; дефект относится к граничным записям длиннее суток.
Диагностический вызов реального voice_file_encode с остановкой на создании Opus:
60 случаев, все пять частот и 1/2 канала; 20 подтверждённых расхождений проверки.
/tmp/media-voice-duration-repro.c, /tmp/media-voice-duration-repro.mk, /tmp/media-voice-duration-repro.log.
План: общий предел миллисекунд в attachment.h; в voice_file проверять 25..4320000 полных кадров
до создания encoder/открытия output. Валидатор и video completion используют тот же предел.
Регрессии: границы 500мс/24ч, отбрасывание хвоста <20мс и ранний отказ при превышении на полный кадр.
Подробности и ограничения воспроизведения: [media_async_audit_findings.txt](media_async_audit_findings.txt).
Рабочий код не изменён: аудит остановлен по AGENTS.md:10; полный аудит media_delivery ещё не завершён.
[+] **media_async encrypted_file: не уничтожать source через alias назначения** — исправлено 24.10.2026.
write/read отвергают только одинаковые строки; /./ и hardlink обходят проверку одного файла.
write возвращает0, заменяя исходные30 байт контейнером пустого файла; read возвращает0,