26 KiB
План работ RF4 Spotter
Этот файл — единственный актуальный список задач. Завершённые аудиты сохранены как история в PROJECT_AUDIT_2026-09-08.md, REGRESSION_AUDIT_2026-09-09.md и RECOVERY_PLAN_2026-09-10.md; их старые чекбоксы не являются текущей очередью.
Последняя сверка: 13 сентября 2026.
Подтверждено:
- пакет восстановления A01–A13 завершён; итог и доказательства собраны в RECOVERY_FIXES_REPORT.md;
- полный Python suite: 130 passed, 1 skipped; skip относится к интеграционной проверке PostgreSQL и покрывается Docker-приёмкой;
- Astro check: 40 файлов, 0 errors / 0 warnings / 0 hints; production build проходит;
- API после миграции healthy;
apps/api/tests/test_api.py: 20 passed; - локальная БД и чистый bootstrap достигают Alembic head
20260910_recovery; - изолированный production bootstrap проходит Caddy adapt, scheduler validation и Playwright-сценарий отправки/модерации без обращения к внешним источникам;
- Astro + FastAPI + PostgreSQL остаются целевым стеком; Next.js и Vinext не используются.
Ближайший пакет — без сервера
Пункты выполняются сверху вниз, небольшими связанными коммитами.
Брендинг и визуальная идентичность
-
B01 · Иерархия имени. RF4 Spotter — единое имя продукта в UI, metadata, manifest и документации; «Ни хвоста, ни чешуи» — поддерживающий слоган. Обновлены wordmark в header/footer и подпись выпуска.
-
B02 · Дизайн-токены. Добавлены семантические роли поверхностей, текста, границ, фокуса, success/warning/danger и всех источников. На токены переведены паспорта данных, status-карточки, skeleton и focus; контрастные пары зафиксированы в brand system.
-
B03 · Графическая грамматика. Мотивы закреплены за функциями: крючок — бренд, поплавок — активность/ожидание, леска — время, радар — координаты, силуэт — сущность рыбы. Убраны ложная рябь неполных сигналов и дублирующие радар круги карточки лидера; неполнота теперь подчёркнута спокойной полевой меткой.
-
B04 · Компонентная подпись.
SectionHeading,PageHeroиStatePanelунифицируют заголовки, hero и состояния; семантическая иерархияdata-actionсогласует CTA публичных и admin-страниц. -
B05 · Motion-система. Смысловые микроанимации пульса, поплавка, загрузки и интерактивного отклика используют общие duration/easing-токены; декоративное движение empty-state удалено, reduced motion покрывает элементы и псевдоэлементы.
-
B06 · Brand QA. Desktop/mobile-проверка усилила каталоги atlas-hero, счётчиками, береговыми контурами и выразительными карточками. Favicon/PWA PNG перегенерированы из SVG-мастера без размытия;
anyи полнофоновыеmaskable-иконки разделены, manifest и Caddy cache обновлены, OG подтверждён как 1200×630. -
B07 · Аудит официальных изображений. Текущий records-parser получает названия рыб/водоёмов и
titleприманки, но не image URL; официальные gallery/userguide содержат тематические медиа без устойчивого полного соответствия каноническим сущностям. Изображения не хотлинкать и не считать разрешение на данные автоматическим разрешением на медиапубликацию. -
B08 · Семейства силуэтов рыб. Три случайных hash-варианта заменены классификатором и отдельными формами
pike,salmonid,cyprinid,perch,catfish,eel,flatfish,marine, плюс честныйgeneric. Компонент допускает ручное переопределение family; название остаётся главным идентификатором. -
B09 · Глифы снастей и приманок. Добавлены SVG-глифы
spinner,wobbler,soft,boilie,worm,rig,unknownи стабильная палитра по normalized name. Классификация срабатывает только по явным словам; глиф сопровождает текст в activity, лидере, уловах, рекордах и списке лучших приманок, не выдавая категорию за точную модель. -
B10 · Визуальные отпечатки водоёмов. Для каждого slug воспроизводимо выбираются один из восьми береговых контуров, число волн, положение точки и двухсимвольный индекс. Знак используется в каталоге и detail-hero; это явно абстрактный отпечаток, а не карта или игровая география.
-
B11 · Разрешённый media pipeline — в работе. Версионированный baseline на 12.09.2026 содержит 19 водоёмов и 252 рыбы; полное число снастей неизвестно и остаётся
null, а не подменяется числом приманок. Воспроизводимыйmedia_cli --coverageсчитает уникальные нормализованные подписи, а не файлы: 228/252 fish-кандидатов (1 approved), 0/19 waterbody, 149 tackle/bait (2 approved); ещё одна официальная Zig-Rig схема approved как reference. URL-классификация имеет приоритет над словами в названии, а две общие userguide-схемы карты больше не выдаются за водоёмы. Следующие gaps: минимум 24 рыбы, все 19 водоёмов и все категории снастей за пределами найденных приманок; получить канонические перечни и устойчивые ID, затем загружать не более одного asset с домена за окно и вручную сопоставлять. RF4DB вернул 403 — повторять только после cooldown. Официальные/media/fische/,/media/levels/и.bait_iconrecords исследовать только через публичные контракты без обхода защиты. -
B12 · Эмблема сочетания. Страница «водоём + рыба» получила составной атласный seal: собственный отпечаток водоёма пересекается со смысловым силуэтом рыбы. Так визуальная идентичность сопровождает всю иерархию каталога и не требует внешних изображений.
-
B13 · Навигационная леска атласа. Разрозненные ссылки назад на detail-страницах заменены доступной breadcrumb-цепочкой с мотивом лески и узлов. Страница точки связывает главную, водоём и координаты; сочетание — каталог, водоём и рыбу. Текущий узел всегда подписан текстом и отмечен
aria-current. -
B14 · Атласные переходы сущностей. Боковые списки рыб и водоёмов на detail-страницах получили компактные силуэты и отпечатки рядом с полным текстовым названием. Знаки продолжают систему каталога в рабочей навигации, а стрелка явно показывает переход к странице сочетания.
-
B15 · Целостность медиакаталога. Локальный audit сводит статусы очереди и проверяет наличие файлов, SHA-256, фактические dimensions/MIME, каноническое соответствие approved-записей и бесхозные файлы. Проверка не обращается в сеть и может использоваться как pre-publication gate.
-
Q01 · Документы источников. Приложить или дать устойчивые ссылки на первичные разрешения RF4DB, RF4-STAT, RF4MAP и RF4 Posts; для каждого зафиксировать атрибуцию, точный production-лимит, срок хранения и процедуру удаления.
-
Q02 · Управляемое удаление источника. Добавить обнаружение изменённых/удалённых опубликованных записей без отдельного частого обхода: статус, журнал решения и безопасное исключение из активности после проверки.
-
Q03 · Целостность ссылок. Проверять исходные ссылки только во время разрешённого планового обращения к площадке, разделяя
missing,temporary_errorиblocked; не создавать дополнительный сетевой цикл. -
Q04 · Состояния ожидания. Асинхронные admin-очереди получили каркасные карточки,
aria-busy, очистку при ошибке и поддержкуprefers-reduced-motion. Публичные страницы остаются SSR и не показывают искусственный skeleton; форма уже блокирует повторную отправку и сообщает «Отправка…». -
Q05 · Базовая визуальная матрица. Главная проверена в браузере на 320/390/768/1280 px, ключевые public-маршруты — на 320 px; удалён корневой
min-width, создававший горизонтальный scroll. Добавлен E2E-контракт для/, records, report, waterbodies, status и видимого skip-link. Ширина 320 px также покрывает reflow, эквивалентный 200% zoom для окна 640 px. Расширенная матрица наполненных/длинных/error-состояний остаётся постоянной частью приёмки UI, а не отдельным блокером. -
Q06 · Performance baseline. На локальной production-сборке после оптимизации hero: performance 100, LCP 1,66 с, FCP 1,15 с, CLS 0,023, TBT 9 мс. Устранены найденные Lighthouse проблемы контраста и accessible name; методика и бюджеты записаны в performance-baseline.md. Полевой INP измеряется только после запуска.
-
Q07 · Нагрузочная методика. Добавлен read-only runner для activity, records, staging и moderation с warm-up, p50/p95/max, распределением HTTP-кодов и ограниченной concurrency. Методика фиксирует контекст запуска, ступени нагрузки и бюджеты, но не объявляет результатов до трёх прогонов на целевом сервере.
-
Q08 · Политика MinIO. Production bootstrap создаёт bucket и отдельную policy только с bucket location/list и get/put/delete его объектов. App credentials проверяются через bucket stat и отрицательную проверку глобального list; API больше не требует
ListAllMyBucketsи не пытается создавать bucket. Root credentials остаются только у init-задачи. -
Q09 · Release-процедура. Миграции вынесены из API runtime в одноразовый
migrateservice; API запускается только после успешного Alembic upgrade. Документированы backup, rollout и два варианта отката. Изолированный drill поднимает предыдущую ревизию схемы, добавляет контрольные данные, обновляет до head и проверяет их сохранность и новые колонки. -
Q10 · Документальная ревизия. После каждого пакета обновлять этот файл и README, не возвращая закрытые R/A/T-задачи в активный backlog.
Дополнения после ревизии PROJECT_AUDIT_2026-09-10
Аудит выполнен на старой базе 13e04e6; рекомендации ниже повторно проверены по текущей ветке. Уже реализованные или неприменимые предложения не возвращаются в backlog.
- Q11 · Декомпозиция API — в работе. После фиксации OpenAPI публичные catalog, activity/spots и records/community/status/import-history вынесены в отдельные
APIRouter; submission endpoints уже принадлежат собственному router, а их security-слой изолирован вsubmission_security. URL, response models и generated contract сохранены. Далее: физически вынести submission handlers изmain.py, затем admin. - Q12 · Query-plan gate. В рамках Q07 снять
EXPLAIN (ANALYZE, BUFFERS)для activity, records, spot detail и public spot pages на реалистичном наборе данных. Существующие индексы миграции0011_query_indexesне дублировать; индекс сfish_id, SQL-агрегацию или materialized view добавлять только по измеренному плану и p95. - Q13 · Production bootstrap в CI. Отдельный workflow запускает
deploy/test-production-bootstrap.shвручную или раз в неделю, а не на каждом push. Вывод bootstrap всегда сохраняется 14 дней; при падении добавляются Compose status и Playwright diagnostics. - Q14 · Полная CSP. Расширить текущую CSP (
frame-ancestors,base-uri,object-src) доdefault-src,script-src,style-src,img-src,connect-srcиform-action. Сначала инвентаризировать inline scripts/styles Astro, затем внедрить nonce/hash или безопасное вынесение; проверить report/admin/OG без ослабления до произвольных внешних origin. - Q15 · Частичная деградация главной. Разделить получение activity, community signals и справочников так, чтобы отказ одного источника не превращал всю главную в общий 503. Для SSR не добавлять искусственный client-side loading/optimistic UI; показывать независимые
StatePanelи корректный HTTP/cache статус. - Q16 · Контракт OpenAPI.
apps/api/openapi.jsonдетерминированно генерируется из FastAPI; CI проверяет его актуальность после backend suite. Изменение artifact обязательно рассматривается вместе с реализацией, а ручное редактирование не используется. - Q17 · Эксплуатационные документы. Добавить короткие ADR по Astro/FastAPI/PostgreSQL, локальному cache и стратегии scheduler, а также incident runbook для заполнения диска/PostgreSQL, отказа MinIO, зависших импортов, ошибок миграции и компрометации секретов.
- Q18 · Минимальная observability. До открытой альфы определить дешёвые метрики request count/latency/error rate, глубины moderation/staging и возраста последнего успешного импорта. Формат и exporter выбрать после выбора мониторинга сервера; полноценный tracing не внедрять без подтверждённой потребности.
Административная панель
- M01 · Усиление административного входа. Сохранён двойной барьер Caddy Basic Auth + API Bearer; внешние ссылки ограничены
http/https, UI завершает сессию после 15 минут бездействия, предоставляет явный выход и возвращает вход после401. Неуспешная API-авторизация ограничена постоянным счётчиком по HMAC-идентификатору клиента с учётом доверенного proxy; успешный вход очищает ошибки клиента. Bearer-токен не сохраняется в URL, cookie или browser storage. - M02 · Единый dashboard.
/adminпоказывает счётчики pending-уловов и staging-наблюдений, число активных источников, их безопасные публичные статусы, последние импорты и быстрые переходы в очереди. Dashboard использует тот же memory-only токен и 15-минутную сессию, не выводит секреты, внутренние URL и полные тексты исключений. - M03 · Эффективность очередей. Очередь внешних наблюдений получила серверные фильтры по источнику и полноте, безопасный поиск по рыбе/водоёму и сортировку по свежести или риску; проблемный порядок поднимает неполные и несопоставленные записи, а параметры работают до пагинации. Обе очереди блокируют всю карточку на время решения, сохраняют введённую причину при ошибке, явно подтверждают успех и переводят фокус к следующей записи. Безопасные горячие клавиши работают только внутри карточки с фокусом и отключены в полях ввода; отклонение и удаление намеренно оставлены только на кнопках.
- M04 · Полный provenance и история решений. Admin API отдаёт время первого/последнего обнаружения и проверки, явный список missing fields и allowlist безопасных скалярных полей исходной записи; карточка показывает их перед публикацией. Единый read-only журнал объединяет решения по пользовательским и внешним записям без ников, URL и исходных payload и отображается на dashboard. Отдельный JSON-экспорт исключает также UUID сущностей, оператора и свободный текст причины; токен остаётся только в памяти вкладки.
- M05 · Защита от параллельных решений. Ввести version/updated-at precondition для optimistic locking и возвращать понятный
409, если запись уже изменена другим модератором. - M06 · Персональные роли — после пилота. Если модераторов станет больше одного, заменить общий токен индивидуальными аккаунтами, короткими сессиями, отзывом доступа и ролями; писать идентификатор оператора в аудит. Для одного владельца альфы не добавлять отдельный auth-сервис заранее.
Готовность открытой альфы — требуется сервер или внешний сервис
- Купить/подготовить Linux-сервер и подтвердить его публичный IPv4/IPv6.
- Настроить DNS
rf4spotter.ruиfiles.rf4spotter.ru, открыть только необходимые внешние порты и получить корректный TLS через Caddy. - Создать
.env.production, заменить все демонстрационные секреты и выполнитьdeploy/preflight.sh. - Создать публичные контакты privacy/abuse и подключить их к сайту и alpha-баннеру.
- Настроить внешний backup, выполнить восстановление с сервера и подключить реальный канал уведомлений.
- Наполнить альфу небольшим разрешённым набором данных и провести финальную приёмку по open-alpha-acceptance.md.
- После 24 часов стабильной работы пригласить первых игроков, собрать обратную связь и закрыть блокирующие проблемы пилота.
- Подключить Search Console/Яндекс Вебмастер и проверить реальные canonical, sitemap, robots, OG и JSON-LD.
- Снять серверные p95 и Lighthouse; скорректировать индексы, кэш и изображения только по измерениям.
После пилота
- Решить по обратной связи, нужны ли OCR, Telegram, профили и уведомления о клёве.
- Рассмотреть cursor pagination при росте объёмов; текущая offset pagination достаточна для альфы.
- Рассмотреть общую инвалидацию кэша при нескольких API-процессах; сейчас действует TTL и локальная инвалидация.
- Рассмотреть Redis только при переходе к нескольким API-процессам или после измеренного дефицита локального cache; не добавлять отдельный stateful-сервис заранее.
- Подготовить тематические обложки и индивидуальные OG для рыб/водоёмов, если страницы подтверждают поисковую ценность.
Правила выполнения
- Сетевой парсинг одной площадки — не чаще одного раза за 30 минут, включая ошибки и разные endpoint.
- Каждая публичная запись обязана показывать источник; неполные данные — отдельную пометку и список отсутствующих полей.
- Реальные источники не используются в тестах: только fixtures и изолированные Docker-сценарии.
- Docker запускается одним общим прогоном для инфраструктурного пакета, а не после каждой правки.
- Пункт закрывается только после адресной проверки; команда и результат фиксируются в коммите или отчёте.
- Не менять целевой стек Astro + FastAPI + PostgreSQL.