117 lines
18 KiB
Markdown
117 lines
18 KiB
Markdown
# План устранения регрессий — 10 сентября 2026
|
||
|
||
> **Архивный документ.** Пакет A01–A13 завершён и повторно принят 11 сентября 2026. Итоги находятся в [RECOVERY_FIXES_REPORT.md](RECOVERY_FIXES_REPORT.md), а единственная текущая очередь — в [ROADMAP.md](ROADMAP.md). Чекбоксы ниже сохранены как исходные критерии аудита и не обозначают незавершённую работу.
|
||
|
||
База проверки: `4f68d6b`. Приоритет выше прежних R/T/D/U/S-пакетов. Они сохраняют контекст требований, но не образуют параллельную очередь. Промпт исполнителю: [RECOVERY_PROMPT.md](RECOVERY_PROMPT.md).
|
||
|
||
## Исходное состояние
|
||
|
||
Проверено: 107 Python-тестов проходят, 1 пропущен; Astro check/build, web unit и Caddy adapt проходят. Это не полная приёмка: проверки не покрывают обнаруженные ниже сценарии. Несовместимость activity envelope исправлена у четырёх потребителей по коду; история site cooldown теперь включает disabled endpoint. Не повторять эти изменения без нового воспроизведения.
|
||
|
||
Ниже сохранён исходный снимок критериев до исправлений; формулировки «не выполнено» и секция «основание» описывают состояние базы `4f68d6b`, а не текущую ветку. По повторной приёмке 11 сентября A01–A13 закрыты в [RECOVERY_FIXES_REPORT.md](RECOVERY_FIXES_REPORT.md). 15 сентября пагинация A04 дополнительно переведена с вводящей в заблуждение кнопки «Показать ещё» на серверные страницы previous/next для activity, records и каталогов; фильтры сохраняются, избыточный offset нормализуется на последнюю страницу, сценарий 45 элементов закреплён unit-тестом. Источники в сеть для этой проверки не опрашивались.
|
||
|
||
| Исторический пакет | Текущий статус | Актуальное подтверждение |
|
||
|---|---|---|
|
||
| A01–A03 | закрыт | `RECOVERY_FIXES_REPORT.md`, тесты readiness/cooldown/redirect |
|
||
| A04 | закрыт, повторно усилен 15.09 | серверные previous/next, диапазон и unit-тест 45 элементов |
|
||
| A05–A12 | закрыт | `RECOVERY_FIXES_REPORT.md`, адресные regression-тесты |
|
||
| A13 | закрыт | итоговый отчёт и единственная активная очередь в `ROADMAP.md` |
|
||
|
||
## Порядок и критерии приёмки
|
||
|
||
### A01 · P0 · Убрать зависимость восстановления импорта от его свежести (R12)
|
||
|
||
- [ ] Разделить готовность API обслуживать запросы и здоровье импорта. Старые/failed/running импорты не должны мешать запуску scheduler, способного восстановить сбор.
|
||
- [ ] Сохранить отдельную тревогу по каждому enabled источнику/площадке с учётом ротации, backoff, последнего успеха и зависших попыток. Разбирать JSON мониторинга, а не искать любое `status:ready`.
|
||
- [ ] Приёмка: запуск на пустой БД, перезапуск после простоя более часа, failed/stalled источники и исправные DB/MinIO; scheduler стартует, деградация сбора заметна. Не обходить проблему безусловно зелёным `/ready`.
|
||
|
||
Основание: `readiness.py` возвращает false для stale импорта, а production scheduler зависит от `api: service_healthy`. Stale-сценарий воспроизведён на SQLite; запуск стека после простоя ещё проверить.
|
||
|
||
### A02 · P1 · Гарантировать общий интервал парсинга (R03/R04)
|
||
|
||
- [ ] Атомарная операция check-and-reserve: один lock на чтение/проверку/запись; не обнулять файл до блокировки, flush до unlock. Безопасное поведение при повреждении/недоступности state и миграция старых ключей.
|
||
- [ ] Один ключ площадки для её доменов/endpoint; отключение источника не удаляет историю cooldown. Production CLI, scheduler и исследовательские команды не должны обходить общий лимит: выбрать общий authority либо запретить независимый сетевой research-путь для production.
|
||
- [ ] Приёмка: два конкурентных процесса — максимум одна разрешённая попытка; неудачный HTTP расходует интервал; disabled/re-enabled, старый state, повреждение, перезапуск. Все тесты без внешних запросов.
|
||
|
||
Основание: `_write_state` открывает `w` до flock, check/reserve разделены, ошибки чтения превращаются в пустую историю.
|
||
|
||
### A03 · P1 · Проверять каждый сетевой переход до I/O (R11)
|
||
|
||
- [ ] Валидировать scheme/host/port исходного URL и каждого redirect до обращения; ограничить переходы, время и размер ответа. Согласовать нормализацию с A02.
|
||
- [ ] Приёмка: запрещённые initial/redirect URL не вызывают transport; цепочки redirect и ответы больше лимита проверены на fixtures. Не считать проверку конечного response.url защитой до запроса.
|
||
|
||
### A04 · P1 · Восстановить фильтры и пагинацию (R08/R09/R02)
|
||
|
||
- [ ] Связные label/select в сетке; period/sort доступны mobile с JS и без JS, selected корректен для 6/12/24/72.
|
||
- [ ] Выбрать понятную модель: серверные страницы с next/previous либо настоящее накопление. Не изображать накопление пустым массивом нового SSR-запроса. Заменять offset через set, не добавлять дубли.
|
||
- [ ] Завершить навигацию records/catalogs, сохранение фильтров, честные счётчики и поведение недопустимого/слишком большого offset.
|
||
- [ ] Приёмка: 45+ записей — достижимы все три страницы без цикла, повторов и потерь; назад/вперёд и смена фильтра. Desktop/mobile/no-JS/keyboard, пустая выдача и длинные названия; SSR всех четырёх activity detail-потребителей.
|
||
|
||
Основание: `offset=20&offset=20` остаётся второй страницей; mobile CSS скрывает поля внутри нового details; selected исправлен не для всех периодов.
|
||
|
||
### A05 · P1 · Сохранить заявку при отказах формы (R10)
|
||
|
||
- [ ] Восстанавливать черновик и фокус для create_error/rate_limited/server_error/timeout; выдерживать недоступность sessionStorage. Не заявлять о восстановлении file input.
|
||
- [ ] Завершить обработку multipart/413/429/timeout и безопасный повтор после неизвестного результата создания; отдельный retry изображения не создаёт второй улов.
|
||
- [ ] Приёмка: ошибки до создания и после сохранения, double submit, timeout, повторная загрузка; данные не теряются, дубли не создаются. Уже добавленную обработку TimeoutError сохранить.
|
||
|
||
### A06 · P1 · Правильно определить клиента через production proxy (R13)
|
||
|
||
- [ ] Определить доверенные peer/цепочку Caddy → Astro → API, согласовать настройки Uvicorn и CIDR окружения. Не доверять всем Docker-сетям или любому XFF без обоснования; валидировать получаемый адрес.
|
||
- [ ] Приёмка: два клиента имеют независимые лимиты через реальную proxy-цепочку; поддельный XFF недоверенного входа не меняет bucket; прямой доступ и отсутствующие заголовки имеют явную политику.
|
||
|
||
Основание: production defaults доверяют только loopback, тогда как peer Astro находится в Docker-сети. Проверка helper на loopback не заменяет проверку цепочки.
|
||
|
||
### A07 · P1 · Согласовать фильтры сигналов, время и оценки (R06/R15)
|
||
|
||
- [ ] Убрать раннее исключение рыбы без external ID там, где допустим подтверждённый fallback; единые правила alias/name и точная review_note. Не вводить нечёткое автоматическое сопоставление.
|
||
- [ ] Определить поведение mapped/unmapped неполных сигналов при slug-фильтрах. Источник и пометки неполноты обязательны.
|
||
- [ ] Адресная оценка точки/рыбы вместо top-100; явное поведение для нескольких видов на точке. Проверить confidence для 0/1/2 игроков и убрать недоказуемые обещания защиты от накрутки.
|
||
- [ ] Сохранить различие неизвестного времени улова и публикации/получения. Приёмка: fixtures с отсутствующим ID, неизвестным временем, анонимными игроками и несколькими рыбами одной точки.
|
||
|
||
### A08 · P1 · Завершить HTTP/SEO-контракт ошибок (R07/S03)
|
||
|
||
- [ ] Согласовать status/noindex/Cache-Control/Retry-After/JSON-LD для главной и detail-страниц. Успешный справочник плюс сбой activity не должен оставлять индексируемую страницу ошибки.
|
||
- [ ] Проверить единый origin, canonical, trailing slash и пагинацию; не считать одно `trailingSlash: never` выполнением всего S03.
|
||
- [ ] Приёмка: 200 populated/empty, 404, 422, 503; на ошибке нет вводящего в заблуждение Dataset/CollectionPage, URL соответствуют выбранной политике.
|
||
|
||
### A09 · P2 · Вернуть автономность CLI (R14)
|
||
|
||
- [ ] Использовать статический registry при argparse, enabled выбирать в рабочем пути команды через переданную сессию.
|
||
- [ ] Приёмка: `python -m app.cli --help` и help подкоманд работают без БД; реальные команды сохраняют проверки enabled и общего cooldown.
|
||
|
||
Основание: CLI всё ещё вызывает `configured_sources()` для choices; падение help без БД воспроизведено.
|
||
|
||
### A10 · P1 · Починить bootstrap и приёмку миграций (R05)
|
||
|
||
- [ ] Заменить устаревшее ожидание `0013` проверкой актуального Alembic head; проверить upgrade с прежней ревизии и чистую БД.
|
||
- [ ] Изолированные loopback-порты/локальные домены, fixture-источники и запрет внешнего egress. Вернуть проверку Caddy/scheduler безопасно, не просто добавить сервисы production.
|
||
- [ ] Приёмка: Caddy adapt, реальные 413 и маршруты; форма → модерация → публикация через proxy, Basic/Bearer, старый импорт после рестарта. Не трогать рабочие volumes.
|
||
|
||
Основание: head теперь `48094a7d1b92`, bootstrap ожидает `0013`. Опасный запуск реальных источников убран, но сквозная приёмка исключённых сервисов отсутствует.
|
||
|
||
### A11 · P2 · Сделать CI и зависимости воспроизводимыми (T08)
|
||
|
||
- [ ] Использовать реальный инструмент аудита зависимостей с явной политикой отказов, без `pip audit ... || true`.
|
||
- [ ] Согласовать Python-версию генерации locks, CI и Docker; образы тоже устанавливают закреплённые зависимости. Проверить, что последующий `pip install -e .` не нарушает pins.
|
||
- [ ] Приёмка: clean install/build; audit действительно запускается и не скрывает технические ошибки; web unit и новые адресные regression tests запускаются в CI. Не выполнять несвязанный массовый upgrade.
|
||
|
||
### A12 · P2 · Завершить историю изменений импорта (D09)
|
||
|
||
- [ ] Хранить значимые версии/изменённые значения с provenance, а не только тип события. Неизменённый повтор не создаёт ложную редакцию. Определить срок хранения, удаление и права доступа.
|
||
- [ ] Приёмка: create → unchanged → changed, частичный сбой/rollback и повтор; прежняя версия восстанавливается из истории, источники не смешиваются. Проверить FK/индексы/миграцию.
|
||
|
||
### A13 · Приёмка и документация
|
||
|
||
- [ ] Актуализировать REGRESSION_FIXES_REPORT: по одному статусу на ID, никаких pending-коммитов и взаимоисключающих разделов; связать R с A. README и ROADMAP отражают факты.
|
||
- [ ] Полный Python suite и web check/build/unit; объяснить каждый skip. Одна общая наполненная SSR/браузерная матрица и один изолированный production acceptance после адресных проверок.
|
||
- [ ] Для каждого A — коммит, команды/результаты, остаточные риски. Только выполненные критерии дают `[x]`. Зелёные старые тесты не заменяют новый regression case.
|
||
|
||
## Организация работы
|
||
|
||
Порядок: A01 → A02 → A03 → A04 → A05 → A06 → A07 → A08 → A09 → A10 → A11 → A12 → A13. Адресные unit/fixture-проверки выполнять по ходу, Docker объединять по инфраструктурным пакетам. Если обнаружена новая опасная регрессия, сначала воспроизвести и добавить в этот план с приоритетом.
|
||
|
||
Ограничения: сохранять Astro/FastAPI/PostgreSQL; не удалять чужие изменения, данные и volumes; не менять стек и не ослаблять тесты ради зелёного результата. Сетевой парсинг не чаще раза за 30 минут на площадку по всем путям запуска, включая неудачные попытки. Для данного пакета реальные источники не нужны.
|
||
|
||
После A13: сверка старого backlog по доказательствам, затем каталог/detail-очередь D05/S02, визуальная идентичность и компоненты V/U, постоянный SEO-контент и performance S, эксплуатационные T. Реальный деплой и внешние интеграции — отдельная стадия, не подразумеваемое разрешение этого плана.
|