textmachine/platform/docs/DEFECT_REGISTER.md

29 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Регистр дефектов и уязвимостей платформы
> Заведён по решению владельца 04.08 («отдельно ведётся колонка багов и уязвимостей — тут опасно всё»).
> Правила: каждая находка любой сессии/приёмки/аудита — строкой сюда ДО закрытия; ID стабилен навсегда;
> закрытие — только с коммитом фикса и тестом, пинящим свойство (урок PD-1: свойство без пинящего теста
> считается НЕ закрытым). Класс: `vuln` — эксплуатируемо или ослабляет защиту · `bug` — неверное поведение ·
> `hardening` — защита в глубину / латентное. Статус: `open` · `fixed(<commit>)` · `accepted-risk(<кем, когда>)`.
| ID | Класс | Серьёзность | Где | Суть | Статус | Источник |
|---|---|---|---|---|---|---|
| PD-1 | hardening | minor | `internal/pgstore/pg_test.go:89` | Свойство «в БД только SHA-256, не токен» НЕ запинено тестом: посадка «`Digest` возвращает плейнтекст» выживает — тест сверяет хранимое через тот же `auth.Digest` (self-consistent). Нужен тест с НЕЗАВИСИМО вычисленным хешом либо ассерт «плейнтекст в БД не находится» | open | приёмка P0 (посадка №1) |
| PD-2 | vuln | **major, ЖИВАЯ (не латентная)** | `cmd/tmplatformd/main.go:73-82` | Нет `ReadTimeout` ⇒ соединения пиннятся уже СЕГОДНЯ, без единой body-принимающей ручки: `net/http` дренирует непрочитанное тело <256 КБ ВНУТРИ `chunkWriter.writeHeader` до отправки заголовка ответа (`net/http/server.go:1389-1435`), и этот чтение-шаг наследует отсутствующий дедлайн. **Репродуцировано оркестратором на собранном бинаре:** 50 полу-кормленных POST на охраняемый `/v0/*` сервер отработал и залогировал 50×401 `ms:0`, клиенты получили НОЛЬ байт, fd 757 и держались, пока не закрыл КЛИЕНТ (агент-скептик независимо пинил 500 соединений). Ограничителя соединений и документированного edge-прокси в зоне нет. Фикс одна строка (`ReadTimeout`; для будущего SSE per-conn дедлайны через `ResponseController`). Вторая половина (`MaxBytesReader`) сегодня не эксплуатируема (ни один хендлер не читает body) гейт P1: закрыть ДО первого POST-хендлера | open | приёмка P0 (security-линза + скептик + собственная репродукция) |
| PD-3 | bug | minor | `internal/httpapi/middleware.go:57` | `Recover` логирует сырой `r.URL.Path` на ERROR id книг/прогонов утекают в лог, против собственной дисциплины AccessLog (route-pattern, не путь) | open | приёмка P0 (security-линза) |
| PD-4 | hardening | minor | `internal/pgstore/sessions.go:41` | WHERE у `Touch` слабее, чем у `Lookup` (нет `idle_expires_at > now`): прямой вызов воскресил бы idle-истёкшую сессию. Через `Require` недостижимо (Touch только после успешного Lookup) одна строка защиты в глубину | open | приёмка P0 (security-линза) |
| PD-5 | bug | minor | `internal/auth/middleware.go:36,45` | Ошибки стора невидимы: сбойный `Lookup` 401 без единой строки лога (аутентификационный DB-outage выглядит как шторм 401), `Touch` глотается `_ =`. На проводе различать нельзя (оракул) но лог обязан различать | open | приёмка P0 (security+blind линзы) |
| PD-6 | hardening | info | `internal/auth/csrf.go:51` | GET освобождён от CSRF (верно), но SSE-хендшейк GET с амбиентной кукой: origin-чек хендшейка потока (STACK §5) не покрыт ничем. Закрыть при постройке SSE (P1) | open | приёмка P0 (security-линза) |
| PD-7 | bug | info | `internal/pgstore/sessions.go:78` | `DeleteExpiredSessions` никем не вызывается свип запланировать в P1 (периодическая джоба воркера) | open | приёмка P0 |
| PD-8 | hardening | info | `internal/auth/session.go:18` | Писателя куки ещё нет; `__Host-` требует Secure локальный dev по HTTP куку не поставит. Решить формой в P1 (dev-профиль), префикс не ослаблять в проде | open | приёмка P0 |
| PD-9 | bug | minor | `cmd/tmplatformd/main.go:81` | `BaseContext` возвращает signal-контекст SIGTERM мгновенно рубит контексты ВСЕХ in-flight запросов, и 15-секундный дренаж `Shutdown` мёртв для ctx-aware хендлеров. Fix: BaseContext без signal-ctx; сигнал ведёт только Shutdown | open | приёмка P0 (faults-линза) |
| PD-10 | bug | minor | `internal/ingest/decoder.go:42,61,67` | Три ужесточения декодера: (а) `hello` с пустым `engine_run_id` принимается а это половина ключа идемпотентности; (б) seq самого hello не пинится к 1 потеря пре-хендшейковых строк недетектируема; (в) mid-stream `hello` (любой версии, вкл. мажор 9.9) уходит в Sink как обычное событие version-гейт держит только строку 1 | open | приёмка P0 (faults-линза) |
| PD-11 | bug | minor | `internal/pgstore/migrations/00002_readmodel.sql:137,177` | Неиндексированные FK-каскады: `notes.chapter_id` и `bank_decisions.term_id` каскадное удаление сканирует таблицы | open | приёмка P0 (faults-линза) |
| PD-12 | bug | info | `internal/ingest/supervisor.go:82-84` | Сбой Sink в начале прогона платформа дренирует ВЕСЬ оставшийся поток в `io.Discard` часами: ceiling/bank_stop-события выбрасываются, никто не оповещён. Нужна политика «БД платформы упала посреди прогона» (ретраи синка / деградация с алармом) дизайн-вопрос P1 | open | приёмка P0 (faults-линза) |
| PD-13 | bug | info | `internal/ingest/supervisor.go:64` | Краш платформы осиротляет процесс движка: ни process-group, ни pidfile, ни пути реаттача (поток невосстановим, повторный спавн упрётся в EXCLUSIVE-лок). Дизайн супервизии P1 | open | приёмка P0 (faults-линза) |
| PD-14 | hardening | info | `internal/httpapi/server.go:79` | `readyz`: ping без собственного таймаута (WriteTimeout нет намеренно SSE), эндпоинт неаутентифицирован и без rate-limit задушить дешёво; таймаут на ping + прикрыть на ops-слое | open | приёмка P0 |
| PD-15 | bug | info | `internal/ingest/resync.go:32` | Деньги в ре-синке float64, а `usage_windows` хранит micro-USD именно против дрейфа: дрейф входит шагом раньше (JSON-парс + суммирование дельт). Принять осознанно или считать в целых | open | приёмка P0 (faults-линза) |
| PD-16 | bug | minor | `internal/httpapi/server.go:81` | `readyz` глотает ошибку ping вопреки собственному комменту «the reason stays in the log» лога нет | open | приёмка P0 (blind-линза) |
| PD-17 | bug | minor | `Makefile:41-42` | Баннер «did NOT run (no database печатается и при ПРОГНАННЫХ БД-тестах (безусловный); батарея гоняет сьют дважды ради имён скипов (второй прогон без -race) | open | приёмка P0 (blind-линза) |
| PD-18 | bug | info | `internal/pgstore/migrations/00002_readmodel.sql:9,139` | Коммент шапки «engine vocabulary never crosses this seam» противоречит `notes.reason` (движковая причина хранится, не проецируется); коммент переписать честно | open | приёмка P0 (canon-линза) |
| PD-19 | bug | info | `internal/ingest/resync.go:44` | `WorstFlagReason` задокументирован «stored», а колонки в `chapters` нет доккоммент или схема, одно из двух | open | приёмка P0 (canon-линза) |