Система объявлений в main без рейтинга (#84) #86

Merged
NotBigGhost merged 3 commits from issue-84-announcements-main into main 2026-09-18 22:06:50 +03:00
Collaborator

Что сделано

Объявления администрации (#84) — те же изменения, что в PR #85 в dev, но перенесённые на main без рейтинговых изменений из dev (#22, #23, #76, #77, #80) и без удаления test-контура. Ветка сделана от origin/main, коммиты объявлений перенесены через cherry-pick.

Описание самой фичи, модель угрозы и детали — в PR #85.

Коммиты

  • 07a14ec Гитигнор: локальный AGENTS.md не идёт в репозиторий (из 2e496a3)
  • 976b8fc Объявления: модель, API игрока и админки, очистка HTML (из a0a0e52; конфликт только в импортах schemas/api.py, в main нет Annotated из рейтинга; миграция 0015 сразу от 0013)
  • d31e998 Объявления: окно у игрока и редактор в админке (из ab1fc3f, без конфликтов)

Миграции

В main последняя миграция — 0013, в dev — рейтинговая 0014. Поэтому 0015_announcements отходит от 0013 в обеих ветках, а в dev пустая 0016 сводит ветки 0014 и 0015 (коммит ec0445f в PR #85). Проверенный путь прода на копии базы:

  1. сейчас прод на 0013;
  2. этот релиз: 0013 → 0015 — создаются таблицы объявлений;
  3. позже, когда в main придёт dev с рейтингом: alembic сам применит 0014 (рейтинговые столбцы) и 0016.

Без этого прод после релиза стоял бы на 0015, и при переходе на dev alembic счёл бы базу актуальной — 0014 не применилась бы никогда.

Проверки

  • pytest — 161 passed (набор main + 14 тестов объявлений).
  • npm run build (typecheck + сборка) — зелёный.
  • schema.d.ts сверен с живым OpenAPI этой ветки — совпадает с перенесённым (полей рейтинга нет).
  • Миграции: путь прода 0013 → 0015 → (dev) 0014 + 0016 прогнан на одной базе; все таблицы и столбцы на месте.
  • В браузере не проверялось — расширение Chrome в сессии не подключено.

Отклонения от плана

Нет в самой фиче. Этот PR — дополнительный, по просьбе владельца: объявления нужны в проде раньше рейтинга.

Будущее слияние dev → main

В main нет собственных изменений, кроме релизных merge-коммитов. Пробное слияние dev (с PR #85) в эту ветку даёт один конфликт — строка импортов в backend/app/schemas/api.py; правильная версия — из dev (from typing import Annotated, Literal). Остальное, включая schema.d.ts, сливается автоматически.

Часть #84 — задачу закроет PR #85 в dev.

🤖 Generated with Claude Code

## Что сделано Объявления администрации (#84) — те же изменения, что в PR #85 в `dev`, но перенесённые на `main` **без** рейтинговых изменений из `dev` (#22, #23, #76, #77, #80) и без удаления test-контура. Ветка сделана от `origin/main`, коммиты объявлений перенесены через cherry-pick. Описание самой фичи, модель угрозы и детали — в PR #85. ## Коммиты - `07a14ec` Гитигнор: локальный AGENTS.md не идёт в репозиторий (из `2e496a3`) - `976b8fc` Объявления: модель, API игрока и админки, очистка HTML (из `a0a0e52`; конфликт только в импортах `schemas/api.py`, в `main` нет `Annotated` из рейтинга; миграция `0015` сразу от `0013`) - `d31e998` Объявления: окно у игрока и редактор в админке (из `ab1fc3f`, без конфликтов) ## Миграции В `main` последняя миграция — `0013`, в `dev` — рейтинговая `0014`. Поэтому `0015_announcements` отходит от `0013` в обеих ветках, а в `dev` пустая `0016` сводит ветки `0014` и `0015` (коммит `ec0445f` в PR #85). Проверенный путь прода на копии базы: 1. сейчас прод на `0013`; 2. этот релиз: `0013 → 0015` — создаются таблицы объявлений; 3. позже, когда в `main` придёт `dev` с рейтингом: alembic сам применит `0014` (рейтинговые столбцы) и `0016`. Без этого прод после релиза стоял бы на `0015`, и при переходе на `dev` alembic счёл бы базу актуальной — `0014` не применилась бы никогда. ## Проверки - `pytest` — **161 passed** (набор `main` + 14 тестов объявлений). - `npm run build` (typecheck + сборка) — зелёный. - `schema.d.ts` сверен с живым OpenAPI этой ветки — совпадает с перенесённым (полей рейтинга нет). - Миграции: путь прода `0013 → 0015 → (dev) 0014 + 0016` прогнан на одной базе; все таблицы и столбцы на месте. - В браузере не проверялось — расширение Chrome в сессии не подключено. ## Отклонения от плана Нет в самой фиче. Этот PR — дополнительный, по просьбе владельца: объявления нужны в проде раньше рейтинга. ## Будущее слияние dev → main В `main` нет собственных изменений, кроме релизных merge-коммитов. Пробное слияние `dev` (с PR #85) в эту ветку даёт **один** конфликт — строка импортов в `backend/app/schemas/api.py`; правильная версия — из `dev` (`from typing import Annotated, Literal`). Остальное, включая `schema.d.ts`, сливается автоматически. Часть #84 — задачу закроет PR #85 в `dev`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Agent added 3 commits 2026-09-18 22:00:48 +03:00
AGENTS.md — такой же локальный гайд для ассистента, как CLAUDE.md, только
для другого инструмента. Он лежал в рабочем дереве незакоммиченным и висел
в git status; теперь он в блоке «AI-ассистенты» рядом с CLAUDE.md
и .claude/, так что случайный `git add .` его не подхватит. #84

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Объявление администрации показывается игроку окном в свой период, пока игрок
не закроет его («Понятно»). Отметка о закрытии хранится на сервере с номером
версии: правка с «показать заново» поднимает версию, и закрывшие прежнюю
увидят объявление снова — ответ помечен updated («обновлено»). Флаг
show_to_new_players=false прячет объявление от зарегистрировавшихся после
начала показа. Пересекающиеся объявления идут от старого к новому.

Текст приходит HTML-ом из редактора админки и сохраняется только после
очистки по белому списку (b, em, mark и mark.red, p, br): атрибуты
отбрасываются, script/style/svg — вместе с содержимым, текст экранируется
заново. Фронт вставляет только этот HTML.

API: GET /api/announcements/pending, POST /api/announcements/{id}/ack;
админка — список со статусом и счётчиком «закрыли N из M», создание, правка,
«снять с показа», удаление, всё в аудит. SSE-событие announcements активным
игрокам. Миграция 0015 идемпотентная.

Тесты: очистка (XSS-попытки, вложенные div), права, период и порядок,
«новые игроки», повторный показ, снятие, удаление, валидация. #84

Перенесено в main без рейтинга из a0a0e52; миграция 0015 — сразу от 0013
(как в ec0445f).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Окно — вариант E из макетов: заголовок в плашке-шапке, текст, точки очереди
и «Понятно», крестика нет. Очередь идёт от старого к новому; закрытое сразу
уходит из кэша, следующее открывается без ожидания сети. У повторно
показанного объявления под заголовком — красная пометка «обновлено».
AppShell показывает окно на любой странице и только когда пароль задан:
обязательное окно пароля всегда первое. Новые и изменённые объявления
приходят SSE-событием announcements, отложенное начало показа — перезапросом
раз в 5 минут.

Админка — вкладка «Объявления» с редактором R1: contenteditable и панель
(жирный, курсив, золотой и красный акцент, эмодзи, снятие оформления),
вставка и перетаскивание только простым текстом, счётчик символов, период
показа по МСК, переключатели «показывать новым игрокам» и «показать заново».
Предпросмотр — тем же окном, что у игрока. Список со статусом, счётчиком
«закрыли N из M» и действиями: изменить, снять с показа, дублировать,
удалить. Выделение текста в форме — полупрозрачный оранжевый вместо синего.

schema.d.ts пересобран из OpenAPI. #84

Перенесено в main без рейтинга из ab1fc3f; schema.d.ts сверен с OpenAPI этой ветки.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NotBigGhost merged commit 551032d66e into main 2026-09-18 22:06:50 +03:00
NotBigGhost deleted branch issue-84-announcements-main 2026-09-18 22:06:50 +03:00
Sign in to join this conversation.