From 45b73ec54ac2f73342b675c438a2107604e3de63 Mon Sep 17 00:00:00 2001 From: IK Date: Fri, 11 Sep 2026 08:06:40 +0700 Subject: [PATCH] docs: refresh roadmap after recovery acceptance --- README.md | 14 +- docs/RECOVERY_FIXES_REPORT.md | 16 +- docs/RECOVERY_PLAN_2026-09-10.md | 2 + docs/RECOVERY_PROMPT.md | 2 + docs/REGRESSION_FIXES_REPORT.md | 2 + docs/ROADMAP.md | 291 +++++-------------------------- 6 files changed, 67 insertions(+), 260 deletions(-) diff --git a/README.md b/README.md index 5d2bc9a..532d14b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ RF4 Spotter — неофициальный сервис свежих точек ## Статус разработки -**Проверка 10 сентября 2026 (`4f68d6b`): к деплою пока не готов.** Python: **107 passed, 1 skipped**; Astro check/build, web unit и Caddy adapt проходят. Исправлены синтаксис Caddy и потребители activity envelope, но остаются цикл readiness/scheduler, неатомарный cooldown, ошибки пагинации/фильтров и другие недоработки. [Актуальный план A01–A13](docs/RECOVERY_PLAN_2026-09-10.md), [промпт исполнителю](docs/RECOVERY_PROMPT.md). Начинать с A01, затем A02. Bootstrap больше не запускает реальные парсеры, но требует обновления проверки миграции и изолированной proxy/scheduler-приёмки. Ниже описаны реализованные возможности, а не гарантия приёмки текущей ревизии. +**Проверка 11 сентября 2026 (`907ad53`): локальный контур готов к развёртыванию открытой альфы, внешний запуск ждёт сервер и его настройки.** Пакет восстановления A01–A13 закрыт. Python: **130 passed, 1 skipped**; Astro check/build и API-тесты проходят. Чистый production bootstrap подтвердил Caddy, scheduler validation, миграцию `20260910_recovery` и браузерный сценарий отправки/модерации. Реальные источники во время приёмки не опрашивались. + +Актуальные следующие задачи находятся только в [ROADMAP](docs/ROADMAP.md). Старые планы и аудиты сохранены как история и больше не задают порядок работ. До внешнего запуска нужны сервер, DNS/TLS, production-секреты, публичные контакты, внешний backup и канал уведомлений. Web Docker-образ устанавливает зависимости через `npm ci` по lock-файлу и удаляет devDependencies после сборки. Локальные `.env` исключены из web build context. @@ -18,9 +20,9 @@ Web Docker-образ устанавливает зависимости чере Повторный импорт изменённой опубликованной записи переводит её на ручную проверку и снимает прежний улов с активности (с учётом TTL кэша). После сопоставления и подтверждения обновляется тот же улов; дубликат не создаётся. Автоматическое обнаружение удалённых оригиналов пока не реализовано. -Идёт исправление аудита: актуальные изменения и ограничения перечислены в [AUDIT_FIXES.md](docs/AUDIT_FIXES.md). Production Compose включает community scheduler; страницы rules/privacy реализованы. Для запуска остаются сервер, DNS/TLS, секреты, внешний backup и контакты. Шкала 72 часов использует полную выборку по времени поступления; одинаковые поля разных источников больше не считаются доказательством одного события. Фоновая публикация обновляет кэш API в пределах TTL, не мгновенно. +История исправлений аудита сохранена в [AUDIT_FIXES.md](docs/AUDIT_FIXES.md) и [RECOVERY_FIXES_REPORT.md](docs/RECOVERY_FIXES_REPORT.md). Production Compose включает community scheduler; страницы rules/privacy реализованы. Для запуска остаются сервер, DNS/TLS, секреты, внешний backup и контакты. Шкала 72 часов использует полную выборку по времени поступления; одинаковые поля разных источников больше не считаются доказательством одного события. Фоновая публикация обновляет кэш API в пределах TTL, не мгновенно. -Предыдущий полный аудит 8 сентября: [отчёт](docs/PROJECT_AUDIT_2026-09-08.md). T01/T02 исправили маршруты формы и конфликт admin-аутентификации; `sh deploy/test-proxy-routing.sh` проверял Astro redirects, API, Basic/Bearer и отказы на прежней ревизии. Синтаксис Caddy теперь исправен. Подключение scheduler к исходящей сети добавлено; актуальная интеграционная приёмка входит в [план A01–A13](docs/RECOVERY_PLAN_2026-09-10.md). +Предыдущие аудиты и план восстановления доступны в `docs/` как исторические материалы. Их незакрытые на момент составления чекбоксы не являются текущим backlog; статусы сведены в [итоговый отчёт](docs/RECOVERY_FIXES_REPORT.md). На ширинах 320, 390, 768 и 1280 px ранее проверено отсутствие горизонтального переполнения основных страниц. Это не полная визуальная приёмка: аудит обнаружил неверную desktop-компоновку фильтров; наполненные карточки, длинные названия, клавиатура и zoom остаются отдельной задачей. @@ -65,7 +67,7 @@ FastAPI ─ PostgreSQL 17 Gitea Actions workflow `.gitea/workflows/ci.yml` на каждый push и pull request проверяет Python, миграции на чистой PostgreSQL, Astro build и полный Compose/Playwright-сценарий. При падении E2E сохраняются логи контейнеров и Playwright-артефакты. -Актуальная инвентаризация источников и правила подключения адаптеров находятся в [`docs/data-source-audit.md`](docs/data-source-audit.md). Разрешённый технический пилот RF4DB/RF4-STAT описан в [`docs/community-source-pilot.md`](docs/community-source-pilot.md), а статус разрешений и лимитов — в [`docs/data-permissions.md`](docs/data-permissions.md). Данные сохраняются только в промежуточный staging и не влияют на индекс без явной проверки и публикации администратором. +Актуальная инвентаризация источников и правила подключения адаптеров находятся в [`docs/data-source-audit.md`](docs/data-source-audit.md). Разрешённый технический пилот RF4DB/RF4-STAT описан в [`docs/community-source-pilot.md`](docs/community-source-pilot.md), а статус разрешений и лимитов — в [`docs/data-permissions.md`](docs/data-permissions.md). Все наблюдения сначала попадают в staging. Полные записи с уже подтверждёнными алиасами могут публиковаться автоматически; новые соответствия требуют модерации, а неполные записи показываются отдельно и не влияют на индекс. Один ограниченный снимок публичных карточек можно получить исследовательским CLI: @@ -86,7 +88,7 @@ python -m rf4_research.community_cli rf4db --limit 25 \ | docker compose exec -T api python -m app.cli stage-community-json --input - ``` -Staging проверяет происхождение URL и диапазоны значений. Источники по умолчанию выключены; автоматического преобразования в одобренные уловы нет. Ручная очередь доступна по адресу . Публикация разрешена только после сопоставления канонических рыбы и водоёма и при наличии координат и веса. +Staging проверяет происхождение URL и диапазоны значений. Источники локально включаются явно; production-профиль запускает разрешённый scheduler. Ручная очередь доступна по адресу . Автопубликация разрешена только для полных наблюдений с ранее подтверждёнными каноническими соответствиями рыбы и водоёма; остальные записи не обходят модерацию. ## Запуск через Docker @@ -140,7 +142,7 @@ docker compose up --build ## Что реализовано - FastAPI и SQLAlchemy 2; -- PostgreSQL 17 и миграции Alembic до `0013`; +- PostgreSQL 17 и миграции Alembic до `20260910_recovery`; - идемпотентный seed с двумя точками и свежими демо-уловами; - `GET /api/v1/activity` с фильтрами периода, водоёма, рыбы, способа и сортировки; - `GET /api/v1/spots/{id}` и `/catches`; diff --git a/docs/RECOVERY_FIXES_REPORT.md b/docs/RECOVERY_FIXES_REPORT.md index 67cea33..5927718 100644 --- a/docs/RECOVERY_FIXES_REPORT.md +++ b/docs/RECOVERY_FIXES_REPORT.md @@ -1,5 +1,7 @@ # Отчёт по регрессионному аудиту — 10 сентября 2026 (Final Verified) +> **Закрыто повторной приёмкой 11 сентября 2026.** После исправлений, перечисленных ниже, дополнительно проверены: полный Python suite — `130 passed, 1 skipped`; Astro check — `0 errors / 0 warnings / 0 hints`; API suite — `20 passed`; чистый production bootstrap — успешно, включая Caddy, scheduler validation, Alembic `20260910_recovery` и Playwright-сценарий. Актуальная очередь перенесена в [ROADMAP.md](ROADMAP.md). Более низкие числа тестов, старый head и перечни «остатков» ниже описывают промежуточный снимок, а не текущее состояние. + База: `9ae05ef`. План восстановления: [RECOVERY_PLAN_2026-09-10.md](RECOVERY_PLAN_2026-09-10.md). --- @@ -165,7 +167,7 @@ --- -## Итоговый статус тестов +## Исторический статус тестов на момент исходного отчёта | Проверка | Результат | |----------|-----------| @@ -182,7 +184,7 @@ --- -## Остаточные риски +## Исторический список рисков до повторных исправлений 1. **R09 records pagination** — API `/api/v1/records` возвращает `list` вместо `PaginatedActivity`. Добавление пагинации требует изменения API контракта. 2. **D05/S02** — каталог/detail-очередь не начаты (требуют новых миграций и UI). @@ -223,7 +225,7 @@ d0d208e A03: Manual redirect control with per-hop validation --- -## Итоговый статус +## Исторический итог исходного отчёта ✅ **Основные A01-A13 выполнены и верифицированы** @@ -232,7 +234,7 @@ d0d208e A03: Manual redirect control with per-hop validation - A09-A11: CLI autonomy, Docker bootstrap, CI audit - A12: Import history (D09 migration at head) -**Остаток (требует дальнейшей работы):** +**Остаток на момент исходного отчёта (впоследствии закрыт):** - A02/A03: State validation, common key for domains, unified limit - A05: Server-side idempotency - A10: Bootstrap multiple heads, Caddy/scheduler checks @@ -240,8 +242,8 @@ d0d208e A03: Manual redirect control with per-hop validation - A12: Meaningful versions with provenance - A13: Final documentation update -**Next steps:** +**Исторические next steps (выполнены локально, кроме реального staging):** 1. Deploy to staging environment -2. Run full bootstrap test (`deploy/test-production-bootstrap.sh`) +2. Run full bootstrap test (`deploy/test-production-bootstrap.sh`) — выполнено 11 сентября 3. Monitor production for 24 hours -4. Close recovery plan +4. Close recovery plan — выполнено 11 сентября diff --git a/docs/RECOVERY_PLAN_2026-09-10.md b/docs/RECOVERY_PLAN_2026-09-10.md index 9205aaf..480cdf5 100644 --- a/docs/RECOVERY_PLAN_2026-09-10.md +++ b/docs/RECOVERY_PLAN_2026-09-10.md @@ -1,5 +1,7 @@ # План устранения регрессий — 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). ## Исходное состояние diff --git a/docs/RECOVERY_PROMPT.md b/docs/RECOVERY_PROMPT.md index 5f18075..2acfaca 100644 --- a/docs/RECOVERY_PROMPT.md +++ b/docs/RECOVERY_PROMPT.md @@ -1,5 +1,7 @@ # Промпт исполнителю плана исправлений +> **Архивный документ.** Этот промпт уже выполнен. Не запускайте его повторно: актуальные задачи находятся в [ROADMAP.md](ROADMAP.md), результаты — в [RECOVERY_FIXES_REPORT.md](RECOVERY_FIXES_REPORT.md). + Скопируйте текст ниже в задачу нейросети, имеющей доступ к репозиторию. ```text diff --git a/docs/REGRESSION_FIXES_REPORT.md b/docs/REGRESSION_FIXES_REPORT.md index 4ee5ca8..17fa38e 100644 --- a/docs/REGRESSION_FIXES_REPORT.md +++ b/docs/REGRESSION_FIXES_REPORT.md @@ -1,5 +1,7 @@ # Отчёт по регрессионному аудиту — 9 сентября 2026 +> **Архивный промежуточный отчёт.** Его раздел «оставшиеся регрессии» закрыт последующим пакетом восстановления. Актуальный итог находится в [RECOVERY_FIXES_REPORT.md](RECOVERY_FIXES_REPORT.md), текущие задачи — в [ROADMAP.md](ROADMAP.md). + База: `9ae05ef` (после трёх коммитов исправлений предыдущего аудита). Исходный отчёт: [REGRESSION_AUDIT_2026-09-09.md](REGRESSION_AUDIT_2026-09-09.md). diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 125e881..b91a79c 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,261 +1,58 @@ # План работ RF4 Spotter -Приоритет: [план восстановления A01–A13 от 10 сентября](RECOVERY_PLAN_2026-09-10.md), [промпт исполнителю](RECOVERY_PROMPT.md). Он заменяет очередь R01–R15 после повторной проверки исправлений. Предыдущие аудиты и [AUDIT_FIXES.md](AUDIT_FIXES.md) сохраняют контекст и историю. +Этот файл — единственный актуальный список задач. Завершённые аудиты сохранены как история в [PROJECT_AUDIT_2026-09-08.md](PROJECT_AUDIT_2026-09-08.md), [REGRESSION_AUDIT_2026-09-09.md](REGRESSION_AUDIT_2026-09-09.md) и [RECOVERY_PLAN_2026-09-10.md](RECOVERY_PLAN_2026-09-10.md); их старые чекбоксы не являются текущей очередью. -Этот файл — рабочий источник правды по развитию проекта. После завершения задачи её чекбокс меняется с `[ ]` на `[x]`, рядом добавляется ссылка на коммит или короткое подтверждение проверки. Новые задачи добавляются в соответствующий этап, а не хранятся только в переписке. +Последняя сверка: **11 сентября 2026**, ревизия `907ad53`. -Последняя сверка: 10 сентября 2026 (`4f68d6b`). Python: 107 passed / 1 skipped; Astro check/build, web unit и Caddy adapt проходят. При этом остаются функциональные регрессии; зелёные проверки не означают готовность к деплою. Полная визуальная/production-приёмка ещё не выполнена. +Подтверждено: -Обозначения: +- [x] пакет восстановления A01–A13 завершён; итог и доказательства собраны в [RECOVERY_FIXES_REPORT.md](RECOVERY_FIXES_REPORT.md); +- [x] полный Python suite: **130 passed, 1 skipped**; skip относится к интеграционной проверке PostgreSQL и покрывается Docker-приёмкой; +- [x] Astro check: 40 файлов, **0 errors / 0 warnings / 0 hints**; production build проходит; +- [x] API после миграции healthy; `apps/api/tests/test_api.py`: **20 passed**; +- [x] локальная БД и чистый bootstrap достигают Alembic head `20260910_recovery`; +- [x] изолированный production bootstrap проходит Caddy adapt, scheduler validation и Playwright-сценарий отправки/модерации без обращения к внешним источникам; +- [x] Astro + FastAPI + PostgreSQL остаются целевым стеком; Next.js и Vinext не используются. -- `[x]` — выполнено и проверено; -- `[ ]` — ещё не выполнено; -- пункты выполняются сверху вниз, если явно не зафиксирована другая зависимость. +## Ближайший пакет — без сервера -## Текущее состояние +Пункты выполняются сверху вниз, небольшими связанными коммитами. -- [x] Этап 0: исследован официальный источник, добавлены парсер, фикстуры и `docs/data-sources.md` (`a6f91a1`). -- [x] Этап 1: создан Docker-каркас Astro + FastAPI + PostgreSQL, миграции, seed, публичный API и базовый E2E (`d3a4524`). -- [x] Основная часть этапа 2: адаптер официальных рекордов, нормализация, дедупликация, журнал импорта и страница рекордов (`d3a4524`). -- [x] Основная часть этапа 3: форма пользовательского улова, модерация, rate limit, MinIO и безопасная обработка скриншотов (`6d536d0`, `c524272`). -- [x] Визуальный референс перенесён в Astro без Next.js, Vinext и React (`c524272`). +- [ ] **Q01 · Документы источников.** Приложить или дать устойчивые ссылки на первичные разрешения RF4DB, RF4-STAT, RF4MAP и RF4 Posts; для каждого зафиксировать атрибуцию, точный production-лимит, срок хранения и процедуру удаления. +- [ ] **Q02 · Управляемое удаление источника.** Добавить обнаружение изменённых/удалённых опубликованных записей без отдельного частого обхода: статус, журнал решения и безопасное исключение из активности после проверки. +- [ ] **Q03 · Целостность ссылок.** Проверять исходные ссылки только во время разрешённого планового обращения к площадке, разделяя `missing`, `temporary_error` и `blocked`; не создавать дополнительный сетевой цикл. +- [ ] **Q04 · Skeleton и переходы.** Добавить лёгкие skeleton-состояния динамическим публичным блокам, без layout shift и с учётом `prefers-reduced-motion`. +- [ ] **Q05 · Визуальная матрица.** Проверить empty/one/many/long/error на 320/390/768/1280 px, keyboard и 200% zoom; исправить только воспроизведённые проблемы. +- [ ] **Q06 · Performance baseline.** Повторить Lighthouse на production-сборке после оптимизации hero; записать LCP/CLS/INP и бюджет в документацию. +- [ ] **Q07 · Нагрузочная методика.** Подготовить воспроизводимый сценарий измерения p95 для activity, records, staging и moderation без объявления результатов до запуска на целевом сервере. +- [ ] **Q08 · Политика MinIO.** Ограничить app credentials одним bucket и добавить безопасную автоматическую проверку policy; root credentials оставить только bootstrap-задаче. +- [ ] **Q09 · Release-процедура.** Разделить миграционный/release-шаг и запуск приложения либо документировать выбранную стратегию отката; проверить upgrade с предыдущей ревизии на копии данных. +- [ ] **Q10 · Документальная ревизия.** После каждого пакета обновлять этот файл и README, не возвращая закрытые R/A/T-задачи в активный backlog. -## Этап 2 — завершить официальный импорт +## Готовность открытой альфы — требуется сервер или внешний сервис -- [x] Добавить административный endpoint ручного запуска импорта `POST /api/v1/admin/imports/official-records` (проверено API-тестом). -- [x] Привести журнал импорта к административному контракту `GET /api/v1/admin/imports` с авторизацией, пагинацией и стабильной сортировкой (проверено API-тестом). -- [x] Добавить HTTP-кэширование источника (`ETag`/`Last-Modified`, если источник их отдаёт) и сохранить диагностические метаданные ответа (миграция `0005`, тест условного запроса и `304`). -- [x] Добавить планировщик импорта с безопасной частотой по умолчанию один раз в 60 минут; отдельный opt-in контейнер/процесс (профиль `scheduler`, обычным запуском не активируется). -- [x] Защитить официальный импорт PostgreSQL session advisory lock: одинаковая source/region/category не запускается параллельно, admin получает `409`, scheduler безопасно пропускает цикл; проверено двумя независимыми PostgreSQL-соединениями. -- [x] Проверить актуальные `robots.txt` и условия использования перед включением расписания; результат записать в `docs/data-sources.md` (`robots.txt` вернул `404`; автоматический профиль оставлен выключенным до явного разрешения). -- [x] Добавить интеграционные тесты: повторный импорт не создаёт дубликаты, сбой источника не удаляет данные, изменение DOM завершается понятной ошибкой. +- [ ] Купить/подготовить Linux-сервер и подтвердить его публичный IPv4/IPv6. +- [ ] Настроить DNS `rf4spotter.ru` и `files.rf4spotter.ru`, открыть только необходимые внешние порты и получить корректный TLS через Caddy. +- [ ] Создать `.env.production`, заменить все демонстрационные секреты и выполнить `deploy/preflight.sh`. +- [ ] Создать публичные контакты privacy/abuse и подключить их к сайту и alpha-баннеру. +- [ ] Настроить внешний backup, выполнить восстановление с сервера и подключить реальный канал уведомлений. +- [ ] Наполнить альфу небольшим разрешённым набором данных и провести финальную приёмку по [open-alpha-acceptance.md](open-alpha-acceptance.md). +- [ ] После 24 часов стабильной работы пригласить первых игроков, собрать обратную связь и закрыть блокирующие проблемы пилота. +- [ ] Подключить Search Console/Яндекс Вебмастер и проверить реальные canonical, sitemap, robots, OG и JSON-LD. +- [ ] Снять серверные p95 и Lighthouse; скорректировать индексы, кэш и изображения только по измерениям. -Критерий готовности: официальный импорт запускается вручную и по расписанию, наблюдаем, идемпотентен и безопасно переживает недоступность источника. +## После пилота -## Этап 3 — завершить пользовательские уловы +- [ ] Решить по обратной связи, нужны ли OCR, Telegram, профили и уведомления о клёве. +- [ ] Рассмотреть cursor pagination при росте объёмов; текущая offset pagination достаточна для альфы. +- [ ] Рассмотреть общую инвалидацию кэша при нескольких API-процессах; сейчас действует TTL и локальная инвалидация. +- [ ] Подготовить тематические обложки и индивидуальные OG для рыб/водоёмов, если страницы подтверждают поисковую ценность. -- [x] Добавить административный веб-интерфейс очереди модерации поверх существующего API (`/admin/moderation`, токен только в памяти страницы). -- [x] Показать скриншот, данные улова и причину решения; реализовать действия «одобрить» и «отклонить» (проверено в браузере на desktop и 390 px). -- [x] Добавить удаление пользовательского сообщения администратором с аудитом действия (обезличивание записи, удаление объекта MinIO, миграция `0006`). -- [x] Заменить in-memory rate limit на общее хранилище, пригодное для нескольких API-процессов и перезапусков (PostgreSQL, HMAC-отпечаток без хранения исходного IP, миграция `0007`). -- [x] Валидировать одновременно содержимое, MIME, расширение и лимит изображения; добавить тесты каждого отказа. -- [x] Добавить сквозной тест: отправка → pending → модерация → появление одобренного улова в публичной статистике (Compose/Playwright: `2 passed`). -- [x] Добавить понятные состояния успеха и ошибок загрузки в форму, включая отдельную ошибку скриншота без потери уже созданной заявки (повторная загрузка по ID сохранённой заявки). +## Правила выполнения -Критерий готовности: полный пользовательский сценарий проходит через браузер, а модератору не нужен ручной вызов API. - -## Этап 4 — индекс клёва - -- [x] Сверить текущую формулу активности и уверенности с разделом 11 спецификации и зафиксировать формулу в `docs/activity-index.md`. -- [x] Покрыть unit-тестами затухание по свежести, доверие к официальным и пользовательским источникам, повторные сообщения одного игрока и вклад разных игроков. -- [x] Не учитывать pending/rejected/удалённые записи и доказать это тестами. -- [x] Добавить детерминированные агрегаты для окон 6, 12, 24 и 72 часа. -- [x] На карточке и странице точки показывать человекочитаемое объяснение оценки и объём данных, на котором она основана (unit-тест объяснения и Astro build). -- [x] Реализовать состояния «данных мало», «данных нет», «источник недоступен» и ошибки валидации фильтров (Astro build; браузерная проверка войдёт в общий прогон фильтров). -- [x] Проверить фильтры главной страницы сквозным тестом на desktop и mobile (Playwright, 1280 px и 390 px). - -Критерий готовности: оценка объяснима, воспроизводима тестами и никогда не маскирует недостаток или устаревание данных. - -## Подготовка MVP к пилоту - -- [x] Добавить health/readiness-проверки PostgreSQL, MinIO, API и импорта; отразить их в Compose (`/health` без зависимостей, `/ready` с компонентами и режимом обязательного импорта). -- [x] Добавить host-side production monitor контейнеров, `/ready`, диска, свежести/целостности backup и срока TLS; подготовлены systemd timer и runbook, реальный канал уведомлений подключается на сервере. -- [x] Автоматизировать ежедневную цепочку backup → dry-run → retention с блокировкой параллельного запуска; ограничить Docker JSON-логи пятью файлами по 10 МБ на сервис. -- [x] Добавить структурированные JSON-логи без пользовательских секретов и персональных технических данных (whitelist полей, redaction, request ID; Uvicorn access-log отключён). -- [x] Добавить Gitea Actions CI: backend tests, Astro check/build, E2E и применение всех миграций на чистой PostgreSQL; сохранять логи Compose и Playwright-артефакты при падении (`.gitea/workflows/ci.yml`). -- [x] Добавить отдельный тест полного bootstrap: пустые production volumes → миграции `0011` → seed без демо-уловов → readiness → браузерная отправка и проверка moderation API (`deploy/test-production-bootstrap.sh`, 7 сентября 2026). -- [x] Сделать seed устойчивым к частично заполненной БД: справочники досеиваются независимо, демо-уловы идемпотентны и принудительно отключены в production; повторный/частичный запуск покрыт конфигурационными и интеграционными проверками. -- [x] Проверить списочные API по требованию раздела 12: все выдачи имеют ограниченные `limit`/`offset`, детерминированный tie-breaker и типизированные фильтры; фильтр категории рекордов перенесён до пагинации. -- [x] Добавить составные индексы PostgreSQL для activity, модерации, официальных рекордов, staging, импорта, аудита и очистки rate limit (миграция `0011`); бюджет и процедура проверки планов зафиксированы в `docs/query-performance.md`. -- [x] Включить все пять разрешённых community-источников и автоматическую публикацию полных наблюдений по ранее подтверждённым алиасам без межисточникового склеивания (миграция `0012`, 7 сентября 2026). -- [x] Добавить обязательную публичную атрибуцию записей и агрегатов, а также отдельную ленту неполных community-наблюдений с явным перечнем отсутствующих полей без влияния на индекс активности (7 сентября 2026). -- [x] Провести security-проверку admin-аутентификации, CORS, headers, загрузок, контейнерных пользователей и секретов: двойная защита admin web/API, constant-time token, no-store, non-root API/web и отдельные MinIO root/app credentials; остаточные ограничения записаны в `docs/security-review.md`. -- [x] Проверить авторизацию повторной загрузки скриншота: используется отдельный одноразовый случайный токен, в БД хранится только SHA-256, UUID заявки недостаточно. -- [x] Определить сроки хранения ников, исходных payload, staging-наблюдений, moderation events и submission attempts; добавлены настраиваемая dry-run-first очистка, тест и `docs/data-retention.md`. -- [x] Добавить резервное копирование и документированное восстановление PostgreSQL и MinIO: консистентные `pg_dump` и MinIO API mirror, контрольные суммы, runbook и успешный изолированный drill с намеренным удалением данных (6 сентября 2026). -- [x] Проверить доступность публичного интерфейса: focus states, skip-link, контраст, подписи полей и axe на главной/рекордах/форме без critical/serious нарушений. -- [x] Провести Lighthouse-проверку главной: accessibility 100, performance 75, FCP 1,2 с, TBT 0 мс; LCP 9,3 с оставлен наблюдаемым бюджетом оптимизации после размещения CDN. -- [x] Провести UI/UX-аудит desktop/mobile и сформировать приоритетный план (`docs/UI_UX_AUDIT.md`). -- [x] Исправить единую шкалу активности и русские числительные во всех публичных представлениях (пакет A UI/UX-аудита; unit-тест границ и E2E согласованности). -- [x] Дополнить визуальный язык авторскими рыболовными SVG-иконками и шкалой активности в форме поплавка; анимации учитывают `prefers-reduced-motion`. -- [x] Сократить мобильный путь до результатов и улучшить фильтры: компактный hero, основные фильтры перед глазами, раскрываемые период/сортировка, строка условий и сброс (пакет B UI/UX-аудита). -- [x] Упростить форму улова, добавить помощь форматов, валидацию и сохранение значений при ошибке (пакет C UI/UX-аудита). -- [x] Заменить slug-фильтры справочниками, добавить сброс и самодостаточные мобильные строки рекордов (пакет D UI/UX-аудита; detail уже адаптивен). -- [x] Завершить accessibility/admin safety пакет с воспроизводимыми axe/Lighthouse-командами (пакет E). -- [x] Добавить smoke-проверку административной очереди внешних источников на desktop/mobile: API-фикстура, неполная запись, disabled publish, ноль mutation-запросов и отсутствие overflow. -- [x] Обновить README: актуальный статус, архитектура, группы переменных окружения, импорт, модерация, backup/restore, эксплуатация логов и известные ограничения. -- [x] Выбрать лицензию кода `AGPL-3.0-only` и оформить отдельную политику использования, минимизации, хранения и удаления данных (`LICENSE`, `docs/data-policy.md`). -- [ ] Завершить production-профиль для `rf4spotter.ru`: приложение и `deploy/preflight.sh` готовы; внешняя проверка 7 сентября не установила соединение с обоими доменами, требуются IP целевого сервера, DNS, запуск и канал уведомлений (`docs/deployment-status.md`). -- [ ] Заменить демонстрационные секреты и определить целевое размещение перед внешней публикацией. - -## Источники данных и согласование - -- [x] Провести аудит подключённых источников, потенциальных поставщиков и всех существующих парсеров; результат записан в `docs/data-source-audit.md`. -- [x] Проверить оба официальных HTML-парсера на актуальной странице и добавить общий контрактный тест эквивалентности. -- [x] Добавить `data_source` и алиасы рыб/водоёмов до подключения второго автоматического источника (миграции `0008`–`0009`; алиасы приманок уже нормализуются в `bait`). -- [x] Вынести общий официальный DOM-парсер, устранив дублирование исследовательской и продуктивной реализации (`rf4_research/official_parser.py`). -- [x] Добавить отдельную фикстуру и безопасный ручной импорт недельных официальных рекордов одной категории. -- [x] Получено подтверждение владельца проекта о разрешениях RF4DB и RF4-STAT; добавлены пилотные HTML-парсеры и отчёт `docs/community-source-pilot.md`. -- [x] Добавлены общий nullable-контракт, парсер detail-страницы RF4DB и ограниченный read-only CLI для RF4DB/RF4-STAT. -- [x] Исследовать дополнительные публичные источники: добавлены read-only detail-парсеры RF4MAP и RF4 Posts, живые контрольные прогоны и тест разделения пространств ID; rf4pro/Farm.Trof отклонены для текущего пилота. -- [x] Получить разрешение RF4MAP/RF4 Posts и зафиксировать интервал не менее 30 минут, хранение только URL изображений и семантику агрегированной точки; источники добавлены в выключенный staging, CLI блокирует ранний повтор. -- [x] Зафиксировать проектное подтверждение разрешений, текущую атрибуцию и консервативные пилотные лимиты в `docs/data-permissions.md`. -- [ ] Приложить или сослаться на первичный документ разрешения и зафиксировать точные продуктивные лимиты, срок хранения, удаление и обязательную атрибуцию до включения scheduler RF4DB/RF4-STAT. -- [x] Добавить staging-модель внешних наблюдений и идемпотентный импорт RF4DB/RF4-STAT без автоматического влияния на индекс (миграция `0008`, сквозной контрактный тест). -- [x] Добавить административную очередь сопоставления staging-записей с каноническими рыбами/водоёмами и явную публикацию в `catch_report` (`/admin/external-sources`, миграция `0009`; неполные записи публиковать запрещено). -- [ ] Найти разрешённый способ получать полные наблюдения с рыбой, водоёмом, координатами и весом из одного источника либо через подтверждённый общий ID; текущие 139 записей неполны и не публикуются. -- [x] Добавить защищённые подсказки алиасов по точным подтверждённым сопоставлениям без применения и запретить конфликтующую перезапись алиаса (7 сентября 2026). -- [ ] Добавить управляемый повторный импорт staging с отчётом `created/updated/rejected`, лимитами запросов и наблюдаемым отказом при изменении DOM; регулярный запуск оставить выключенным до фиксации условий. -- [ ] Определить процедуру повторной проверки опубликованного внешнего улова при изменении или удалении записи у источника. -- [ ] Согласовать один добровольный канал сообщества и правила происхождения, модерации и удаления сообщений. - -## Pre-deploy: SEO, визуальный язык и техническая полировка - -### SEO и структура публичного сайта - -- [x] Добавить единый SEO-контракт страниц: уникальные `title`/`description`, canonical URL, Open Graph и Twitter Card (7 сентября 2026). -- [x] Подготовить и подключить фирменное OG-изображение 1200×630; локально проверены размер и метатеги, внешняя проверка превью выполняется после DNS/TLS (7 сентября 2026). -- [x] Добавить production-aware `robots.txt`, исключить `/admin`, `/api`, `/health` и `/ready` из индексации (7 сентября 2026). -- [x] Добавить динамический `sitemap.xml` для существующих статических страниц и публичных точек; страницы рыб и водоёмов включить после реализации их маршрутов (7 сентября 2026). -- [x] Добавить JSON-LD: `WebSite`, `Dataset` и `BreadcrumbList` на соответствующих страницах (7 сентября 2026). -- [x] Сделать собственную полезную страницу 404 с возвратом к свежим точкам (7 сентября 2026). -- [x] Явно отдавать `noindex` на административных страницах и состояниях ошибок (7 сентября 2026). -- [x] Добавить постоянные URL точек `/spots/{waterbody}-{x}x{y}`, перевести карточки и sitemap, а старые UUID-ссылки сохранить через 301 redirect (7 сентября 2026). -- [x] Создать индексируемые каталоги и страницы `/fish/{slug}`, `/waterbodies/{slug}` и сочетания водоём + рыба с уникальными метаданными и включением в sitemap (7 сентября 2026). - -### Графические элементы и объяснение данных - -- [x] Не показывать дублирующий sidebar лидера при единственной найденной точке (7 сентября 2026). -- [x] Показывать у каждого улова на detail-странице источник, относительную свежесть и точную дату в подсказке (7 сентября 2026). -- [x] Подготовить фирменный знак «крючок + поплавок + координатная сетка» и согласованный набор favicon/app icons (7 сентября 2026). -- [x] Добавить честный координатный радар без имитации отсутствующей карты на страницу точки (7 сентября 2026). -- [x] Добавить временную шкалу активности 72 часа с 12-часовым шагом в виде лески с поплавками (7 сентября 2026). -- [x] Добавить лёгкие детерминированные SVG-силуэты видов рыб в карточки результатов и каталог (7 сентября 2026). -- [x] Собрать единый визуальный «паспорт данных»: источник, свежесть, полнота и доверие; применить к карточкам активности (7 сентября 2026). -- [x] Добавить публичную легенду цветов источников и статусов качества на странице `/status` (7 сентября 2026). -- [ ] Добавить skeleton-состояния для динамических публичных блоков. -- [x] Добавить ненавязчивый глобальный баннер открытой альфы со ссылками на статус, правила и отправку улова (7 сентября 2026). -- [ ] Подключить к баннеру публичный канал обратной связи после получения его адреса; не раскрывать частный Gitea. -- [x] Дополнить пустые состояния собственной CSS-иллюстрацией поплавка и ряби с поддержкой `prefers-reduced-motion` (7 сентября 2026). - -### Производительность, данные и эксплуатация - -- [x] Добавить scheduler всех пяти разрешённых community-парсеров с устойчивым cooldown ≥30 минут, PostgreSQL lock, журналом запусков и opt-in локальным профилем; backoff после повторных ошибок остаётся отдельным улучшением (7 сентября 2026). -- [x] Добавить экспоненциальный backoff community scheduler после повторных ошибок от 30 минут до 24 часов со сбросом после успеха (7 сентября 2026). -- [x] Показывать на `/status` безопасное состояние источников: актуален, устарел, временно ограничен, изменился DOM, ожидает запуска или выключен (7 сентября 2026). -- [x] Добавить 20-секундный серверный кэш агрегата активности с явной инвалидацией после публикации, модерации и удаления (7 сентября 2026). -- [x] Настроить долгий immutable cache для хешированных assets и разумный cache для изображений/favicon (7 сентября 2026). -- [x] Добавить серверное «Показать ещё» для публичной ленты полевых сигналов с сохранением фильтров и пределом 48 записей (7 сентября 2026). -- [x] Объединять одинаковые полевые сигналы в сюжеты без потери уникальных ссылок provenance и показывать число совпадений (7 сентября 2026). -- [x] Добавить защищённый JSON-экспорт диагностики со сборкой и агрегированными счётчиками без персональных данных, URL и ошибок источников (7 сентября 2026). -- [x] Контролировать рост PostgreSQL и MinIO host-monitor'ом с настраиваемыми порогами и runbook реакции (7 сентября 2026). -- [ ] Добавить фоновую проверку битых исходных ссылок с соблюдением лимитов источников. -- [x] Показывать версию и commit SHA в readiness и защищённой административной диагностике (7 сентября 2026). -- [x] Добавить публичную `/status` без внутренних адресов, секретов и текстов ошибок (7 сентября 2026). -- [ ] После появления сервера подключить privacy-friendly аналитику без cookies либо собственные агрегированные счётчики. -- [ ] Зафиксировать нагрузочный бюджет и проверить p95 публичных API на целевом сервере. - -### Обязательные внешние условия открытия альфы - -- [ ] Заменить все демонстрационные production-секреты. -- [ ] Настроить DNS `rf4spotter.ru` и `files.rf4spotter.ru`, корректный TLS и закрыть внутренние порты. -- [ ] Создать контакты `privacy`/`abuse` и определить срок реакции. -- [ ] Приложить первичные документы разрешений и точные продуктивные лимиты источников. -- [ ] Настроить внешнее хранение резервных копий и проверить восстановление с сервера. -- [ ] Подключить реальный канал уведомлений мониторинга. -- [ ] Наполнить альфу разрешённым набором реальных данных и выполнить финальный `preflight`. - -## Этап 5 — пилот - -- [x] Опубликовать страницы `/rules` и `/privacy`, добавить ссылки в footer и обязательное несохраняемое согласие перед отправкой улова. -- [ ] Создать и проверить ящики `privacy@rf4spotter.ru` и `abuse@rf4spotter.ru`, определить срок реакции на обращения. -- [x] Проверить локально публичные abuse-сценарии: шестая заявка блокируется, файл > 8 МБ отклоняется до декодирования, повтор screenshot запрещён, admin queue ограничена 100 строками; нагрузочный прогон остаётся серверным шагом. -- [x] Зафиксировать сценарий приёмки открытой альфы, измеримые пороги и стоп-критерии (`docs/open-alpha-acceptance.md`). -- [x] Зафиксировать охват открытой альфы: без продуктового allowlist, доступны все корректно загруженные категории, водоёмы и виды рыб из разрешённых источников; ограничения качества и модерации сохраняются. -- [ ] Наполнить базу небольшим разрешённым набором реальных данных. -- [ ] Провести тестирование с несколькими игроками по подготовленному сценарию. -- [ ] Собрать обратную связь по полезности точек, понятности уверенности, форме улова и мобильному интерфейсу. -- [ ] Исправить блокирующие проблемы пилота и повторить проверку критериев MVP из раздела 16 спецификации. -- [ ] Только после пилота принять решение по OCR, Telegram, профилям, уведомлениям и импорту сообществ. - -## Ближайший рабочий пакет - -Следующая задача — **A01: цикл readiness/scheduler**, затем A02: атомарный общий cooldown. Чекбоксы и критерии текущей очереди ведутся в [RECOVERY_PLAN_2026-09-10.md](RECOVERY_PLAN_2026-09-10.md); не дублировать их статусы здесь. После A13 сверить прежние R/T/D/U/V/S по доказательствам. - -### Повторная приёмка 9 сентября 2026 - -Исторический пакет: [повторный аудит](REGRESSION_AUDIT_2026-09-09.md). Часть изменений уже внесена, но полная приёмка перечисленных требований не завершена. Текущие остатки и новые регрессии учтены в A01–A13; этот список не задаёт следующий шаг. - -- [ ] R01 (P0, T05): исправить невалидный Caddyfile, проверить adapt, 413 и маршруты. -- [ ] R02 (P0, U03/D08): согласовать activity envelope со всеми страницами; SSR populated/empty и API regression tests. -- [ ] R03 (P1, D02): восстановить CLI state; атомарная проверка/резервирование, flush, миграция и конкурентные тесты. -- [ ] R04 (P1, D01/D02): исключать disabled из ротации, но сохранять всю историю сайта для cooldown; убрать гонки registry. -- [ ] R05 (P1, T06): изолировать bootstrap-порты/домены и fixture-источники; проверить сценарии через proxy без внешних запросов. -- [ ] R11 (P1, D03): проверять URL до запроса и каждый redirect; единый ключ сайта и ограниченное чтение. -- [ ] R06 (P1, U02): согласовать slug-фильтры полевых сигналов с alias/mapping, сохранить источник и пометки неполноты. -- [ ] R07 (P1, S01): единый HTTP/noindex/cache/JSON-LD контракт ошибок после загрузки данных. -- [ ] R08 (P1, U01): восстановить label/select сетку, selected всех периодов и mobile/no-JS управление. -- [ ] R09 (P1, U03): добавить настоящую пагинацию activity/records/catalogs с сохранением фильтров и честным total. -- [ ] R10 (P1, U04/T05): черновик и фокус для всех ошибок, TimeoutError, безопасный повтор и обработка multipart/413. -- [ ] R12 (P1, T06/D10): мониторить здоровье каждого enabled источника/площадки, stale/running/failed; разбирать JSON статусов. -- [ ] R13 (P1, T04): определить proxy trust boundary, валидировать IP и проверить независимость rate limit двух клиентов. -- [ ] R14 (P2, D01/T08): отделить registry от БД; CLI help и unit-тесты работают без внешнего PostgreSQL. -- [ ] R15 (P1, D04/D06/D07/D08): единые правила alias fallback, честная уверенность/время, адресный агрегат точки и рыбы. -- [ ] Приёмка пакета: зелёный Python suite, web unit в CI, SSR и одна общая desktop/mobile проверка populated/empty/error/long/keyboard/zoom; один изолированный production acceptance без живого scraping. -- [ ] Сверить T03/T07 и остальные частично реализованные старые задачи с критериями; только после проверки перенести отметки `[x]` и обновить README. - -После пакета: D05/S02 → V01–V04/U05–U07 → S03–S06 → T08–T10/D09–D10. Серверные S07 и launch checklist остаются отдельной стадией; смена Astro-стека не планируется. - -### P0 — блокеры production - -- [x] T01: Caddy направляет в FastAPI только `/api/v1/*`, `/health`, `/ready`, обработчики формы остаются в Astro (правка `bb61d21`). Проверено 9 сентября: `sh deploy/test-proxy-routing.sh`, оба POST дают ожидаемый 303, каталог и readiness доступны. Тест использует временный proxy и не создаёт уловов; успешная отправка с сохранением входит в T06. -- [x] T02: Basic применяется к admin-страницам, Bearer — к admin API, конфликт Authorization устранён. 9 сентября: `sh deploy/test-proxy-routing.sh` проверяет доступ к странице/диагностике, 401 без правильных credentials и авторизованный PATCH с невалидным UUID (422, без записи). Полный цикл модерации — T06. -- [ ] T03: обеспечить исходящую сеть community scheduler при изоляции БД/MinIO. - -### P1 — до открытой альфы - -- [ ] T04: сохранить реальную идентичность клиента для rate limit с проверенной цепочкой доверия proxy. -- [ ] T05: ограничить request body и время POST-запросов, обработать multipart/413/429. -- [ ] T06: расширить production acceptance на Caddy и scheduler; включить scheduler в мониторинг. -- [ ] T07: убрать диагностические подробности из публичного журнала импортов. -- [ ] D01: исключить disabled endpoint из ротации сайтов, проверить конкурирующие запуски. -- [ ] D02: атомарный cooldown research CLI, миграция старого state, единый production-путь запросов. -- [ ] D03: allowlist URL/redirects, общий ключ площадки и ограниченное чтение HTTP-ответов. -- [ ] D04: согласовать fallback alias по имени с автоматической публикацией. -- [ ] D05: расширить справочники и охват detail-источников через управляемую очередь с лимитом сайта. -- [ ] D06: устранить неверное обещание защиты от одного игрока и определить ограничения его вклада. -- [ ] D07: разделить время улова/публикации/получения/повторного обнаружения. -- [ ] D08: запрашивать оценку конкретной точки и рыбы без поиска в глобальном top-100. -- [ ] U01: исправить desktop-сетку фильтров, проверить раскрытие и мобильный layout. -- [ ] U02: согласовать область действия фильтров активности и полевых сигналов. -- [ ] U03: добавить публичную пагинацию и честные общие счётчики. -- [ ] U04: полезные ошибки формы, ожидание отправки и защита от двойного submit. -- [ ] S01: единый HTTP/SEO-контракт пустых, ошибочных и недоступных страниц. -- [ ] S02: получать сущности по slug, исключить ложные 404 после первых 500 записей каталога. - -### P2 — качество интерфейса, SEO и сопровождения - -- [ ] V01: согласовать основное имя RF4 Spotter и роль слогана «Ни хвоста, ни чешуи». -- [ ] V02: оформить CSS-токены и компонентные состояния, разделить глобальные стили. -- [ ] V03: компактный паспорт точки, копирование координат, ясная легенда шкалы. -- [ ] V04: проверить малые и maskable-иконки, качество OG и точность alt. -- [ ] U05: сократить первый экран, улучшить мобильную навигацию и empty/stale/error действия. -- [ ] U06: упростить карточки, подписи качества и терминологию. -- [ ] U07: визуальная матрица empty/1/many/long/error, клавиатура, zoom и повторный axe. -- [ ] S03: единый site origin, canonical/query/trailing-slash политика и конечные внутренние URL. -- [ ] S04: полезный постоянный контент рыб/водоёмов и архив с честной датой/атрибуцией. -- [ ] S05: ограничить срок sitemap fallback, документировать двойной URL-контракт и подготовить sitemap index. -- [ ] S06: проверить кэш hero и снять новый performance baseline после исправлений. -- [ ] T08: Python lock/constraints, CI web unit tests и регулярный аудит зависимостей. -- [ ] T09: нагрузочный бюджет агрегации/истории и решение об общей инвалидации по замерам. -- [ ] T10: release/migration шаг, bucket-scoped MinIO policy, план персонального admin-доступа. -- [ ] D09: частичные результаты импорта, история значимых редакций и процедура удаления оригиналов. -- [ ] D10: endpoint backoff, running/stalled состояния и достоверный последний успех. - -### После появления сервера / после пилота - -- [ ] S07 (P2): закрыть staging от индексации, подключить Search Console/Яндекс Вебмастер и проверить рабочие canonical/sitemap/OG/JSON-LD. -- [ ] V05 (P3): тематические обложки и OG рыб/водоёмов после обратной связи. -- [ ] Выполнить существующий внешний launch checklist: секреты, DNS/TLS, backup, мониторинг, контакты и реальные данные. - -После завершения задачи: адресная проверка по риску, отметка `[x]` со ссылкой на коммит/результат, обновление README при изменении поведения и отдельный коммит. Docker запускается для инфраструктурных или общих интеграционных проверок, а не после каждой правки документации. UI проверяется на desktop/mobile с наполненными и пустыми состояниями. +- Сетевой парсинг одной площадки — не чаще одного раза за 30 минут, включая ошибки и разные endpoint. +- Каждая публичная запись обязана показывать источник; неполные данные — отдельную пометку и список отсутствующих полей. +- Реальные источники не используются в тестах: только fixtures и изолированные Docker-сценарии. +- Docker запускается одним общим прогоном для инфраструктурного пакета, а не после каждой правки. +- Пункт закрывается только после адресной проверки; команда и результат фиксируются в коммите или отчёте. +- Не менять целевой стек Astro + FastAPI + PostgreSQL.