имя файла отправителя убрано из журнала приёма

- расширение приводится к перечню известных форматов прежде метки метрики:
  страница метрик открыта, и хвост имени уезжал на неё дословно
- проверки приёма перехватывают все три потока журнала и читают реестр метрик,
  каждая падает при снятии того, что сторожит
This commit is contained in:
av
2026-08-11 16:37:58 +03:00
parent ffa36e96c7
commit bd6001cd8d
18 changed files with 1797 additions and 20 deletions
@@ -0,0 +1,89 @@
## 1. Правка журнала приёма
- [x] 1.1 Убрать поле с именем, данным отправителем, из журнальной строки общего
шага заведения задачи (`internal/service/transcribe.go`,
`createTranscribeJob`). Идентификатор файла и путь к нему в хранилище остаются,
уровень строки остаётся `INFO`.
- [x] 1.2 Проверить остаток поиском по **значению**: прогон приёма с маркером в
имени, поиск маркера по всему выводу прогона — ничего не найдено. Поиск по
имени поля `file_name` остатком не считается.
## 2. Проверка
- [x] 2.1 Окружение проверок приёма по HTTP отдаёт журнал в буфер вместо
`io.Discard`. Буфер свой на каждый случай, а цепочка журнала воспроизводит
боевую: окружение зовёт `slog.SetDefault` и собирает роутер тем же набором
middleware, что `main.go`, — иначе два потока из трёх остаются вне оракула.
Вывод прогона от этого не меняется.
- [x] 2.7 У каждого из трёх потоков журнала своё удерживающее утверждение:
снятие потока из окружения роняет проверку, а не проходит молча.
- [x] 2.2 Проверка успешного приёма: имя записи несёт маркер — уникальную
ASCII-строку, которой нет в остальном выводе, — при обычном расширении `.mp3`.
В перехваченном журнале маркера нет.
- [x] 2.3 Проверка отказного приёма: источник метаданных не читает запись, имя
несёт тот же маркер. В перехваченном журнале, включая запись об ошибке,
маркера нет.
- [x] 2.4 Проверка прослеживаемости: в журнале есть идентификатор заведённого
файла, расширение принятой записи и её размер в байтах. Утверждение отбирается
по идентификатору **этого** прогона.
- [x] 2.5 Мутация: вернуть имя в журнальную строку под **другим** ключом —
проверки 2.2 и 2.3 краснеют; снять мутацию — зеленеют.
- [x] 2.6 `go test -race -count=5 ./internal/controller/http/` зелёный.
## 2а. Метка метрики (добавлено чекпоинтом после ревью кода)
- [x] 2а.1 Расширение приводится к закрытому перечню известных форматов прежде,
чем уйти меткой метрики; всё прочее — `other`. Имя файла на диске не трогается.
- [x] 2а.2 Обе метки, несущие расширение, идут через приведение: размер принятой
записи и длительность конвертации. Сырой точки употребления гистограммы в
сервисе не остаётся — приведение живёт внутри обёрток пакета метрик, и обойти
его можно только заведя новую точку.
- [x] 2а.4 Обе обёртки судятся по реестру метрик, а не по чистой функции:
снятие приведения в любой из них роняет проверку.
- [x] 2а.3 Проверка приведения: известное расширение с точкой и без, смена
регистра, умолчание сервиса, хвост имени отправителя, часть даты, пустое.
## 3. Гейт и документы
- [x] 3.1 `task gate` зелёный сверх объявленного долга (4 замечания
`golangci-lint` в существующем коде).
- [x] 3.2 `docs/security.md`: строка «Имя файла, данное отправителем, пишется»
переписана остатком — имя из журнала приёма убрано, хвост после последней
точки продолжает попадать в журнал внутри пути файла в хранилище.
- [x] 3.3 Решить, нужна ли строка в `docs/conventions/logging.md` о том, чем
заменено имя, и либо дописать её, либо назвать причину отказа.
## Критерии приёмки
### Из записи задачи `no-user-filename-in-log`, дословно
- Имени, данного отправителем, нет ни в одной журнальной строке приёма. Оракул —
прогон приёма с записью, чьё имя содержит опознаваемую строку, и `grep` этой
строки по перехваченному журналу: ничего не найдено.
- Идентификатор файла, его расширение и длина в журнале остаются: по ним путь
записи прослеживается. Оракул — тот же перехваченный журнал, `file_id` и
`size` на месте.
### Рубрика ревью дизайна
- Запрещённое значение не появляется ни в одном поле и ни в одном `msg` записи о
приёме, включая ветку отказа. Оракул — прогон успеха и прогон отказа с
маркером в имени, поиск маркера по перехваченному журналу пуст в обоих.
- Оракул перехватывает весь журнальный поток приёма, а не один обработчик.
Оракул — мутация: вернуть имя в обход `slog`, проверка краснеет.
- Проверка способна упасть. Оракул — мутация с **другим** ключом поля роняет
проверку; проверка ищет значение, а не имя ключа.
- Маркер уникален и записан ASCII, поиск идёт по сырому тексту буфера. Оракул —
при возвращённом поле утечка находится, несмотря на экранирование обработчиком.
- Буфер журнала свой на случай, утверждение о полях отбирается по идентификатору
этого прогона. Оракул — `go test -race -count=5 ./internal/controller/http/`
зелёный.
- Запись о приёме не исчезает и не меняет адресата: уровень остаётся `INFO`,
категория `msg` прежняя. Оракул — в буфере ровно одна запись приёма на
принятую запись, её уровень `INFO`.
- Прослеживаемость названа полями поимённо, с единицей у числового: размер — в
байтах. Оракул — критерий приёмки называет те же ключи, что и требование.
- Косвенные носители имени названы поимённо и каждый закрыт либо назван
остатком: текст ошибки — закрыт проверкой 2.3, путь на диске и ключ объекта
строятся из идентификатора и расширения, расширение — остаток строкой в
`docs/security.md`.