chore: remove AI working directories (docs/superpowers, docs/plans) from repo
Deploy Telegram Bot / build-and-push (push) Successful in 32s
Deploy Telegram Bot / scan-images (push) Successful in 1m45s
Deploy Telegram Bot / deploy (push) Successful in 15s

Add docs/superpowers/, docs/plans/, *.diff to .gitignore.
These directories contain implementation plans and design specs
used during agentic development; they are not needed in source control.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 18:58:57 +03:00
parent 73714c9525
commit b57332bd5c
12 changed files with 0 additions and 6308 deletions
@@ -1,44 +0,0 @@
# Telegram Mini App Dashboard Design
## Goal
Issue #17 adds a Telegram Mini App dashboard as the mobile entry point for the existing Web Dashboard. Owner and co-GM users must be able to open the dashboard from Telegram, pass server-side Telegram WebApp `initData` validation, and manage only their own groups.
## Scope
- Add Mini App authentication using Telegram WebApp `initData`.
- Add a `/miniapp` entry page that signs the user into the existing cookie auth flow, then opens the regular dashboard UI in mobile-first mode.
- Reuse `AuthorizedSessionService`, `SessionService`, and existing Blazor pages for groups, sessions, templates, waitlist promotion, edit forms, and bulk batch operations.
- Add bot entry points: a Mini App button in `/start` and a configurable default menu button when `Telegram:MiniAppUrl` is set.
- Update README, wiki, deployment config, and visible version strings to `1.9.0`.
## Architecture
The Mini App is not a second dashboard implementation. It is a Telegram-authenticated entrance into the existing Blazor dashboard. This keeps authorization, domain operations, Telegram message synchronization, and Web Dashboard behavior in one place.
`TelegramAuthService` gains a second verification method for WebApp `initData`. The server accepts the raw URL-encoded init payload at `/auth/telegram-webapp`, verifies the Telegram HMAC with the bot token, extracts the user id/name from the embedded `user` JSON, and issues the same auth cookie as the login widget endpoint.
`/miniapp` loads `telegram-web-app.js`, posts `window.Telegram.WebApp.initData` to the server endpoint, expands the WebApp viewport, and redirects to `/`. If a user opens `/miniapp` outside Telegram, the page shows the regular login fallback.
## Data Flow
1. User opens the Mini App from the bot menu button or `/start` inline button.
2. Telegram injects `initData` into the WebApp JavaScript API.
3. `/miniapp` posts `{ initData }` to `/auth/telegram-webapp`.
4. The server verifies the WebApp signature and expiry.
5. The server creates the same claims used by Telegram Login Widget.
6. Existing Blazor pages load groups through `AuthorizedSessionService`.
7. Any edit, waitlist, template, or batch action still goes through existing services and keeps Telegram messages synchronized.
## Error Handling
- Missing or invalid init data returns `401` and leaves the user on the Mini App page.
- Expired auth data is rejected with the same 24-hour window used by the Login Widget.
- A verified Telegram user with no owner/co-GM groups sees the existing empty dashboard state.
- Direct navigation to a foreign group/session still redirects to `/access-denied` through existing authorization checks.
## Testing
- Unit tests cover valid and invalid WebApp `initData`.
- File-level regression tests ensure `/miniapp`, `/auth/telegram-webapp`, Telegram WebApp script loading, bot Mini App button, menu button setup, and mobile Mini App CSS hooks remain present.
- Existing `AuthorizedSessionServiceTests` continue covering owner/co-GM access behavior.
@@ -1,140 +0,0 @@
# Platform Messenger Scheduler Notifications Design
## Goal
Issue #31 moves scheduler-driven notifications and reschedule deadline message updates behind `IPlatformMessenger`, preserving Telegram behavior and adding full Discord support instead of no-op placeholders.
## Scope
- `SessionSchedulerService` remains the trigger orchestrator, but scheduler handlers stop depending on Telegram API types for outbound notification work.
- Confirmation requests, one-hour reminders, join-link notifications, RSVP follow-up messages, and reschedule deadline updates use platform-neutral contracts.
- Telegram keeps the current user-visible behavior: same message content, RSVP buttons, direct messages, topic/thread targeting, and stored legacy message ids.
- Discord receives full channel and direct notifications:
- confirmation requests are sent to the Discord channel with RSVP buttons;
- Discord RSVP button clicks update participant RSVP state, refresh the confirmation message, and send the same group/GM outcome notifications where applicable;
- one-hour reminders and join-link notifications are sent as Discord DMs when direct notifications are enabled;
- join-link notifications also post the channel message with participant mentions;
- reschedule deadline processing updates Discord vote and schedule messages through the same messenger boundary.
- Discord DM failures are non-fatal: log a warning and continue without posting a public fallback message.
## Architecture
The platform boundary should be semantic, not Telegram-shaped. `GmRelay.Shared.Platform` already owns `PlatformKind`, `PlatformUser`, `PlatformGroup`, `PlatformMessageRef`, and `IPlatformMessenger`; issue #31 extends that layer with notification-specific DTOs and messenger methods.
The scheduler handlers own database queries and notification eligibility. They load platform-neutral groups, users, message refs, and session data, then ask the platform messenger to send or update the platform message. Platform implementations own rendering details: Telegram renders HTML and inline keyboards; Discord renders embeds, components, channel messages, mentions, and DMs.
RSVP handling should become platform-neutral enough for both Telegram and Discord. The current `HandleRsvpHandler` logic is not duplicated. Its command changes from Telegram ids to `PlatformUser`, `PlatformGroup`, `PlatformMessageRef`, and `InteractionId`. Telegram update routing maps callback queries into that command; Discord component routing maps RSVP button interactions into the same command.
Reschedule finalization already has shared database logic in `RescheduleVotingFinalizer`. The remaining platform-specific deadline services should stop editing messages through `ITelegramBotClient` or Discord `RestClient` directly. They should load message refs and call `IPlatformMessenger` to update vote messages, schedule messages, and direct result notifications.
## Platform Contracts
Add semantic notification records in `GmRelay.Shared.Platform`, with names finalized during implementation planning:
- `PlatformSessionParticipant`: a `PlatformUser` plus RSVP, registration, and display metadata needed by notification renderers.
- `PlatformSessionNotification`: common session title, time, join link, notification mode, group, optional existing message, and participants.
- `PlatformConfirmationRequest`: confirmation-specific session notification with RSVP actions.
- `PlatformJoinLinkNotification`: join-link group/direct notification data.
- `PlatformOneHourReminder`: one-hour direct reminder data.
- `PlatformRsvpMessageUpdate`: refreshed confirmation message state after a participant responds.
- `PlatformRescheduleVoteUpdate`: finalized reschedule vote message state, including selected option or rejection reason.
Extend `IPlatformMessenger` with methods for these semantic operations while keeping existing schedule, group, private, interaction, and calendar methods intact for current flows:
- send and update confirmation request messages;
- send one-hour reminder direct notifications;
- send join-link channel and direct notifications;
- update finalized reschedule vote messages;
- send RSVP outcome messages to the group and GM recipients.
The exact method names should be chosen in the implementation plan after tests define the desired API, but each method should accept platform-neutral DTOs and return `PlatformMessageRef` when the caller must persist a sent message id.
## Telegram Behavior
Telegram implementation lives in `GmRelay.Bot.Infrastructure.Telegram.TelegramPlatformMessenger`.
It must preserve:
- `messageThreadId` handling for forum topics;
- HTML parse mode where the existing flow uses HTML;
- current confirmation and RSVP button callback payloads;
- `confirmation_message_id` and `link_message_id` storage in `sessions`;
- direct notification behavior controlled by `SessionNotificationMode`;
- warning-and-continue behavior for failed direct messages;
- existing schedule rendering through `TelegramSessionBatchRenderer` and `BatchMessageEditor`.
Telegram-specific inbound parsing remains at the Telegram boundary. `UpdateRouter` can still use `Telegram.Bot.Types`, but the command it passes into the RSVP handler should be platform-neutral.
## Discord Behavior
Discord implementation lives in `GmRelay.DiscordBot.Infrastructure.Discord.DiscordPlatformMessenger`.
It must support:
- channel messages through the configured channel id in `PlatformGroup.ExternalChannelId`;
- interactive RSVP buttons routed by `DiscordSessionInteractionModule`;
- ephemeral interaction replies via the existing `DiscordInteractionReplyCache` pattern;
- DMs through Discord user ids in `PlatformUser.ExternalUserId`;
- non-fatal DM failures with warning logs;
- Discord-friendly rendering, not raw Telegram HTML;
- persistence of Discord schedule and notification message refs in `platform_messages` where later updates need them.
The current Discord reschedule deadline service directly uses `RestClient` for vote and schedule message edits. This should be folded into `DiscordPlatformMessenger` so deadline services and future platform handlers do not need to know Discord API details.
## Data Flow
1. `SessionSchedulerService.TickAsync` asks `ISessionTriggerStore` for due confirmation, one-hour reminder, and join-link session ids.
2. Each handler loads the session, group platform identity, message refs, participants, RSVP state, and notification mode.
3. The handler builds a semantic platform notification DTO and calls `IPlatformMessenger`.
4. The messenger renders and sends/updates platform messages.
5. The handler persists sent message ids where required, using legacy `sessions.confirmation_message_id` and `sessions.link_message_id` for Telegram and `platform_messages` for Discord refs that need later updates.
6. Telegram callback queries and Discord component interactions both call the same platform-neutral RSVP handler.
7. Reschedule deadline services use `RescheduleVotingFinalizer`, then call `IPlatformMessenger` for vote message updates, schedule updates, and direct result notifications.
## Error Handling
- A failed trigger query still logs and lets the scheduler continue to the next trigger category.
- A failed send/update for one session logs and does not stop other sessions in the same tick.
- DM failures are warning-level and non-fatal for Telegram and Discord.
- A missing platform message ref logs a warning and skips only the update that needs the ref.
- Unsupported platform values throw at the messenger boundary, not inside scheduler orchestration.
- If Discord cannot parse a stored channel, message, or user id, it logs the bad external id and skips that platform send/update.
## Testing
Use TDD for implementation.
Focused tests should cover:
- `IPlatformMessenger` exposes semantic notification methods without referencing Telegram or Discord assemblies from `GmRelay.Shared`.
- `SendConfirmationHandler`, `SendOneHourReminderHandler`, `SendJoinLinkHandler`, `HandleRsvpHandler`, and reschedule deadline services do not call `ITelegramBotClient`, `BatchMessageEditor`, or Discord `RestClient` directly for notification output.
- Telegram source/regression tests preserve thread ids, callback payloads, message id persistence, and direct notification mode behavior.
- Discord source tests verify registration of scheduler handlers, RSVP component routes, and messenger methods.
- RSVP flow tests run through platform-neutral `PlatformUser` identity, including Discord users without Telegram ids.
- Discord messenger tests verify DMs are attempted, DM failures are swallowed after logging, channel notifications include buttons or mentions as appropriate, and message refs are returned.
- Full regression: `dotnet test tests/GmRelay.Bot.Tests/GmRelay.Bot.Tests.csproj`, `dotnet build`, and `dotnet format --verify-no-changes --verbosity diagnostic`.
## Versioning
Current repository version is `2.6.0`. Although the Gitea issue is labeled `type:refactor`, the approved scope adds full Discord notification behavior. Proposed bump: `2.6.0` to `2.7.0`.
Synchronize:
- `Directory.Build.props`
- `compose.yaml` image tags for bot, discord, and web
- `.gitea/workflows/deploy.yml` `VERSION`
- `src/GmRelay.Web/Components/Layout/NavMenu.razor`
## Out Of Scope
- Moving the entire scheduler hosted service into `GmRelay.Shared`.
- Removing legacy Telegram columns such as `telegram_chat_id`, `confirmation_message_id`, or `link_message_id`.
- Reworking Web dashboard Telegram behavior.
- Public fallback messages when a Discord DM is blocked.
## Self-Review
- Spec coverage: every issue acceptance criterion is represented by scheduler handler boundaries, messenger contracts, Telegram behavior preservation, and Discord implementation requirements.
- Placeholder scan: no TBD/TODO/fill-in-later sections remain.
- Internal consistency: the design uses semantic platform DTOs consistently and keeps SDK-specific rendering in platform implementations.
- Scope check: the work is large but still one coherent platform-notification refactor; moving the whole scheduler to shared remains explicitly out of scope.
@@ -1,166 +0,0 @@
# Дизайн: Синхронизация документации после MVP2 (Discord + кросс-платформенность)
**Дата:** 2026-05-21
**Версия проекта:** v2.7.2
**Статус:** Approved
---
## 1. Цель
Привести всю проектную документацию в актуальное состояние после завершения MVP2:
- Discord-интеграция (slash-команды, кнопки, RSVP, reschedule voting, DM-уведомления).
- Кросс-платформенная архитектура (`IPlatformMessenger`, `SessionBatchViewBuilder`, platform-specific renderers).
- Новые env-переменные (`DISCORD_BOT_TOKEN`), healthcheck на 8082, Docker Compose сервис `discord`.
- Регрессионные тесты, обновлённый CI/CD.
---
## 2. Аудитории и каналы
| Аудитория | Канал | Фокус |
|---|---|---|
| ГМы и игроки | Gitea Wiki | Как пользоваться ботом: команды, кнопки, уведомления, FAQ |
| Разработчики и хостеры | `README.md` + `docs/` | Архитектура, сборка, деплой, env-переменные, ADR |
**Принцип:** Wiki — только пользовательская документация. Технические детали (архитектура, БД, разработка) удаляются из Wiki и консолидируются в репозитории.
---
## 3. Wiki (пользовательская документация)
### Новая структура страниц
1. **Home**
- Общее описание GM-Relay (Telegram + Discord).
- Текущая версия v2.7.2.
- Ссылки: Быстрый старт, Руководство ГМа, Руководство игрока.
- Убираем: технический стек, ссылки на Архитектуру/БД/Разработка.
2. **Быстрый старт**
- Шаг 1: Добавление Telegram-бота в группу.
- Шаг 2: Приглашение Discord-приложения на сервер (scopes: bot, applications.commands).
- Шаг 3: Создание первой группы (`/newgroup` в Telegram или через Web).
- Шаг 4: Создание первого batch (`/newsession`).
- Шаг 5: Публикация расписания (`/listsessions`).
3. **Руководство ГМа**
- Telegram-команды: `/newgroup`, `/newsession`, `/listsessions`, `/exportcalendar`.
- Discord slash-команды: `/newsession`, `/listsessions`.
- Создание и управление batch: картинки, повторы, bulk-операции (Web).
- Co-GM и делегирование.
- Переносы (reschedule): как инициировать голосование, как работает дедлайн.
- Шаблоны кампаний.
- Статистика посещаемости (Web).
- Управление очередью (waitlist, promote).
4. **Руководство игрока**
- Telegram: запись через inline-кнопки, отмена.
- Discord: кнопки Join/Leave в schedule message, RSVP (Confirm/Decline).
- Уведомления: за 24ч, за 1ч, ссылка перед игрой, DM vs группа.
- Лист ожидания: как попасть, как автоматически продвинуться.
5. **FAQ / Устранение неполадок**
- Бот не отвечает: проверить права, перезапустить.
- Кнопки не работают: проверить права Manage Messages / Embed Links.
- Mini App не открывается: HTTPS, domain в BotFather.
- Discord DM не приходят: privacy settings, бот не может писать first.
- Reschedule голосование не завершилось: дедлайн, минимум голосов.
### Удаляемые Wiki-страницы (контент переходит в README/docs)
- `Архитектура``docs/c4-system-context.md` + `docs/adr/`
- `База данных``docs/adr/` (описание схемы)
- `Разработка``README.md` (раздел для контрибьюторов)
- `Развёртывание``README.md` (Docker Compose quick start)
---
## 4. README.md (разработчики и хостеры)
### Что обновить
- **Версия:** с `v2.7.0``v2.7.2`.
- **Key Features — Discord:**
- Slash-команды `/newsession`, `/listsessions`.
- Кнопки Join/Leave/RSVP с ephemeral-ответами.
- DM-напоминания и ссылки (с fallback-логированием).
- Reschedule voting с дедлайном.
- Waitlist и auto-promote.
- **Технологический стек:**
- Добавить NetCord Gateway для Discord.
- Уточнить: `GmRelay.DiscordBot` — это NetCord Gateway worker (не отдельный проект в solution, а runtime-роль внутри Bot/Web).
- Добавить `IPlatformMessenger` в архитектурное описание.
- **Структура репозитория:**
- Убрать `GmRelay.DiscordBot` как отдельный проект (согласно CLAUDE.md, его нет; Discord-логика внутри `GmRelay.Bot`).
- Добавить `GmRelay.ServiceDefaults`.
- **Переменные окружения:**
- Добавить `DISCORD_BOT_TOKEN`.
- Добавить `DISCORD_BOT_CLIENT_ID` (для регистрации slash-команд).
- **Docker Compose:**
- Добавить сервис `discord` с healthcheck на `:8082`.
- Уточнить multi-arch (AMD64/ARM64 для Raspberry Pi).
- **Quick Start:**
- Добавить шаг приглашения Discord-бота.
- Добавить настройку домена для Mini App.
### Новый раздел (опционально)
- **Для разработчиков:**
- Краткое описание Vertical Slice + Native AOT.
- Ссылка на `docs/adr/0001-...` и `docs/adr/002-...`.
- Как добавить handler и зарегистрировать в Program.cs.
- Как написать миграцию (DbUp).
---
## 5. `docs/` (архитектурная и техническая документация)
### `docs/c4-system-context.md`
- **Level 1 (System Context):** Добавить Discord Gateway and REST API как external system. Добавить игрокам Discord-взаимодействие.
- **Level 2 (Container):** Уточнить, что `GmRelay.Bot` содержит **оба** runtime-роли: Telegram long polling **и** Discord Gateway worker (или уточнить, что Discord worker — отдельный контейнер внутри той же сборки). Проверить текущую C4-диаграмму — она уже содержит `discordBot`, так что нужно только убедиться, что он соответствует `GmRelay.Bot` (а не `GmRelay.DiscordBot`).
- **Level 3 (Component):** Уже содержит Discord-компоненты. Проверить актуальность: `DiscordSessionInteractionModule`, `DiscordPlatformMessenger`. Добавить `RescheduleVotingFinalizer` (shared). Добавить `DiscordHealthCheckHostedService`.
### `docs/adr/0001-use-vertical-slice-native-aot-and-aspire.md`
- Добавить Discord-аспект: NetCord Gateway worker, slash-команды.
- Уточнить, что Aspire оркестрирует **три** сервиса: Bot (Telegram + Discord), Web, PostgreSQL.
### `docs/adr/002-platform-neutral-batch-rendering.md`
- Уже содержит Discord renderer. Дополнить:
- Issue #30 (reschedule voting) использует `IPlatformMessenger`.
- Issue #31 (scheduler notifications) тоже использует `IPlatformMessenger`.
- Issue #32 (compose wiring) добавил Discord healthcheck.
- Issue #33 (регрессионные тесты) покрывает оба renderer'а.
### Новый ADR (опционально, если есть время)
- **ADR-003: Discord Integration Architecture** — почему NetCord (а не DSharpPlus), как Gateway events маршрутизируются в vertical slice handlers, как ephemeral-ответы работают.
- Это необязательно, но полезно для будущих разработчиков.
---
## 6. Порядок выполнения
1. **Wiki Home** — обновить описание, версию, ссылки.
2. **Wiki Быстрый старт** — переписать с учётом Discord.
3. **Wiki Руководство ГМа** — добавить Discord-команды, reschedule voting, статистику.
4. **Wiki Руководство игрока** — новая страница (или раздел в Руководстве ГМа).
5. **Wiki FAQ** — новая страница.
6. **README.md** — версия, features, env, Docker, quick start.
7. **`docs/c4-system-context.md`** — Discord-компоненты, healthcheck.
8. **`docs/adr/0001-...`** — Discord-аспекты.
9. **Удалить устаревшие Wiki-страницы** (Архитектура, База данных, Разработка, Развёртывание) или заменить их редиректами на README.
---
## 7. Критерии готовности
- [ ] Все wiki-страницы отражают текущую версию v2.7.2.
- [ ] Все Discord-фичи задокументированы для пользователей.
- [ ] README содержит актуальную версию, env-переменные, структуру репозитория.
- [ ] C4-диаграмма и ADR'ы отражают Discord-архитектуру и `IPlatformMessenger`.
- [ ] Нет противоречий между Wiki и README (например, версия, команды).
- [ ] Устаревшие wiki-страницы удалены или содержат редирект.