Commit Graph

77 Commits

Author SHA1 Message Date
Toutsu 11b145a967 chore: add platform identity and platform_messages for multi-platform support (#23)
PR Checks / test-and-build (pull_request) Successful in 9m36s
TDD cycle for issue #23:
- RED: 9 migration smoke tests (file presence + schema expectations)
- GREEN: V016 migration adding platform identity columns
- GREEN: CreateSessionHandler, JoinSessionHandler, Web SessionService updated
  with dual-write to legacy and new identity columns + COALESCE fallbacks
- GREEN: get_group_attendance_stats recreated for external_username
- Bump version to 2.0.0

Changes:
- V016__add_platform_identity.sql:
  - players: platform, external_user_id, external_username
  - game_groups: platform, external_group_id, external_channel_id
  - platform_messages table with cross-platform message tracking
  - Backfill all existing Telegram data into new columns
  - Recreate get_group_attendance_stats with COALESCE fallback
- V012__add_attendance_stats.sql: use COALESCE(external_username, telegram_username)
- CreateSessionHandler: dual-write + COALESCE fallbacks in SELECTs
- JoinSessionHandler: dual-write to new identity columns
- Web SessionService: dual-write to new identity columns
- PlatformIdentityMigrationTests (9 smoke tests covering all handlers)
- Version synced: Directory.Build.props, compose.yaml, deploy.yml, NavMenu.razor → 2.0.0

Legacy telegram_* columns preserved for backward compatibility.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 10:48:10 +03:00
Toutsu 105b3c59d7 fix: address review feedback for health check endpoints
PR Checks / test-and-build (pull_request) Successful in 8m34s
- Install wget in Web Dockerfile for compose healthcheck
- Ensure HttpListener response is always closed in BotHealthCheckHostedService
- Use ephemeral port in Bot health check test to avoid port conflicts
- Rename NpgsqlHealthCheck test to reflect actual behavior

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 11:16:58 +03:00
Toutsu 3bea327043 feat: add health check endpoints for Bot and Web
PR Checks / test-and-build (pull_request) Successful in 8m53s
- Web: add /health endpoint with PostgreSQL readiness check (returns 200+JSON or 503)
- Web: add /alive endpoint for liveness probe
- Bot: add BotHealthCheckHostedService serving /health on port 8081 via HttpListener
- Bot: expose port 8081 in Dockerfile and install wget for healthcheck
- compose.yaml: add healthcheck sections for bot and web services
- tests: add TDD tests for both health endpoints

Bump version -> 1.16.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 10:54:22 +03:00
Toutsu 9deccd3a9d docs: add MIT LICENSE file
PR Checks / test-and-build (pull_request) Successful in 7m7s
Add LICENSE file with MIT License text to repository root.
README.md already references it; the file was missing.

Includes TDD-verified tests ensuring LICENSE exists and contains
MIT License text, and README references it correctly.

Bump version → 1.15.1

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 16:25:17 +03:00
Toutsu 81d4ec2c97 fix(web): ensure dataprotection-keys dir is owned by app user before switching USER
Deploy Telegram Bot / build-and-push (push) Successful in 3m58s
Deploy Telegram Bot / scan-images (push) Successful in 1m58s
Deploy Telegram Bot / deploy (push) Successful in 13s
The volume mount /app/dataprotection-keys was created under root:root
permissions on the host. When the container restarted with the 1.15.0
image, the non-root app user (uid=1654) could no longer read/write
DataProtection keys, causing every request to fail with
UnauthorizedAccessException and fall back to the generic /Error page.

Add RUN chown during the final Docker stage so the directory ownership
matches the runtime user before USER $APP_UID takes effect.
2026-05-12 16:05:48 +03:00
Toutsu 121272fdfe infra: add PostgreSQL daily backup via pg_dump with rotation
PR Checks / test-and-build (pull_request) Successful in 6m24s
- Add db-backup service to compose.yaml (postgres:17-alpine + cron)
- Add pgbackups volume for backup storage
- Add scripts/restore.sh for manual restore from latest backup
- Update .env.example with BACKUP_RETENTION_DAYS and BACKUP_VOLUME_NAME
- Document backup/restore flow in README

Bump version -> 1.15.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 13:36:47 +03:00
Toutsu e3fdac15b5 ci: satisfy trivy dockerfile checks
PR Checks / test-and-build (pull_request) Successful in 5m12s
Run runtime images as the built-in non-root .NET app user and install Web runtime OS dependencies with --no-install-recommends.
2026-05-12 12:31:20 +03:00
Toutsu 105a051c2f ci: install latest trivy and verify scan inputs
PR Checks / test-and-build (pull_request) Failing after 6m30s
Enable NuGet lock files so Trivy has dependency targets, fail PR checks when no lock files or language-specific files are detected, and let the installer fetch the latest Trivy release.
2026-05-12 12:20:42 +03:00
Toutsu de9f56c97d feat(#21): support selected telegram topics for schedules
PR Checks / test-and-build (pull_request) Failing after 3m18s
Route new schedules to an existing forum topic when /newsession is sent inside one, create bot-owned topics only from the forum root, and keep group notifications/dashboard updates threaded to the stored topic.

Persist topic ownership so deletion only removes empty bot-created topics, add topic routing tests and smoke coverage, and bump release metadata to 1.14.0.
2026-05-12 12:07:51 +03:00
Toutsu 025c7c2f9a fix(#20): reset confirmation_sent_at on reschedule and add guard
PR Checks / test-and-build (pull_request) Successful in 3m17s
- RescheduleVotingDeadlineService: clear confirmation_sent_at +
  confirmation_message_id when moving session back to Planned.
- HandleRescheduleTimeInputHandler.RescheduleImmediately: same reset.
- SendConfirmationHandler: add confirmation_sent_at IS NULL guard
  to prevent duplicate confirmation messages if DB update fails.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 13:49:30 +03:00
Toutsu e6e6d17b72 feat(#20): довести RSVP и напоминания до полного набора событий
PR Checks / test-and-build (pull_request) Successful in 3m12s
- Добавлена абстракция ISystemClock + SystemClock / FakeSystemClock
  для тестируемого scheduling.
- Добавлена миграция V014: confirmation_sent_at в sessions.
- Обновлен SendConfirmationHandler: записывает confirmation_sent_at.
- Обновлен SessionSchedulerService:
  - выделен ISessionTriggerStore / DbSessionTriggerStore
  - SQL-запросы используют параметр @Now вместо now()
  - добавлен публичный TickAsync для тестов
  - защита от дублей через confirmation_sent_at IS NULL
- Обновлен RescheduleVotingDeadlineService: использует ISystemClock.
- Добавлены интерфейсы ISendConfirmationHandler, ISendOneHourReminderHandler,
  ISendJoinLinkHandler для unit-тестируемости.
- Добавлены 8 unit-тестов SessionSchedulerService:
  - все 3 триггера (T-24h, T-1h, T-5min)
  - идемпотентность при повторном запуске
  - ошибки handler не падают и не блокируют другие сессии
  - ошибки store логируются без падения worker-а

Bump version -> 1.13.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 13:38:34 +03:00
Toutsu e2303490e9 feat(#15): add session audit log history tests and bump version to 1.12.0
PR Checks / test-and-build (pull_request) Successful in 4m4s
Adds missing tests for GetSessionHistoryForGmAsync authorization.
Syncs version across all 4 files for the 1.12.0 minor release.

Bump version -> 1.12.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 18:57:07 +03:00
Toutsu c0c8f852d2 feat(#19): добавить ссылку на игру в карточку батча
PR Checks / test-and-build (pull_request) Successful in 3m49s
- SessionBatchDto: добавлено поле JoinLink
- SessionViewItem: добавлено поле JoinLink
- SessionBatchViewBuilder: прокидывание JoinLink из DTO в ViewModel
- CreateSessionHandler, SessionService: обновлены все вызовы конструктора
- TelegramSessionBatchRenderer (Bot + Web): рендеринг ссылки в карточке
- Добавлены тесты на наличие ссылки в рендере
- Все 7 SQL-запросов, загружающих SessionBatchDto, обновлены с join_link AS JoinLink
- Бамп версии до 1.11.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 18:13:55 +03:00
Toutsu 9374ff16ed fix(ui): prevent NavMenu logo from overlapping hamburger on mobile
PR Checks / test-and-build (pull_request) Successful in 3m37s
On viewports ≤768px the burger button is position:fixed at the
viewport edge, while the header retained its default 1rem left
padding. The logo image therefore sat completely underneath the
button, causing a visible overlap on hover.

Increase .nav-header padding-left to 3.75rem on mobile so the
.nav-brand clears the 2.5rem fixed toggle with a 0.5rem gap.

Bump version → 1.10.6

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 13:41:48 +03:00
Toutsu d2edbf16cc fix(ci): bump version to 1.10.5
PR Checks / test-and-build (pull_request) Successful in 3m49s
Synchronize version across:
- Directory.Build.props
- compose.yaml (bot and web images)
- deploy.yml
- NavMenu version display

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 13:16:16 +03:00
Toutsu b16627c2b6 feat(ui): replace emoji logos with new app icon across dashboard
- NavMenu: swap 🐢 emoji for <img src="logo.png">
- Login page: swap 🎲 emoji for <img src="logo.png">
- Mini App page: swap 🎲 emoji for <img src="logo.png">
- Replace favicon.png with the new logo
- Add logo.png to wwwroot
- Update CSS for .nav-brand-icon, .login-logo, .mini-app-logo to use object-fit: contain sizing

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 13:15:53 +03:00
Toutsu 4f7afb3bc9 fix(ci): sync NavMenu version to 1.10.4
Deploy Telegram Bot / build-and-push (push) Successful in 3m42s
Deploy Telegram Bot / deploy (push) Successful in 9s
2026-05-07 16:24:46 +03:00
Hermes Agent a0d9d1bc44 fix(#47): use align-items: baseline + vertical-align + nudge for emoji icon
Deploy Telegram Bot / build-and-push (push) Successful in 3m34s
Deploy Telegram Bot / deploy (push) Successful in 9s
2026-05-07 13:18:57 +00:00
Hermes Agent 46527fe761 fix(#47): align NavMenu emoji icon — line-height: 1, increase gap
PR Checks / test-and-build (pull_request) Successful in 3m17s
Deploy Telegram Bot / build-and-push (push) Successful in 3m47s
Deploy Telegram Bot / deploy (push) Failing after 7s
2026-05-07 12:59:50 +00:00
Hermes Agent 0dbd4064ac fix(#15): bump NavMenu version and fix audit log test expectations for MaxPlayers
PR Checks / test-and-build (pull_request) Failing after 3m11s
2026-05-07 12:37:36 +00:00
Hermes Agent 6d90ba8274 feat(#15): add SessionHistory.razor, navigation links, and bump version to 1.10.2 2026-05-07 12:20:44 +00:00
Hermes Agent 35894bf89e feat(#15): session audit log domain, store, and instrumentation 2026-05-07 12:16:54 +00:00
root 6394b1fe8c fix: mobile menu overlay z-index and add stats link on group page 2026-05-07 12:08:37 +00:00
root 4d3362d93f fix: GroupStats.razor syntax and missing using for Claims
PR Checks / test-and-build (pull_request) Failing after 3m14s
- Add @using System.Security.Claims
- Fix quotation marks in @onclick lambdas (Razor parser error CS1026)
2026-05-07 11:21:42 +00:00
root b03929174a fix: move PlayerAttendanceStats out of interface scope
PR Checks / test-and-build (pull_request) Failing after 2m53s
The record was nested inside ISessionStore, making it ISessionStore.PlayerAttendanceStats.
C# does not infer nested types in return signatures; callers and implementors failed
with CS0246 / CS0738. Moving it to namespace scope resolves the build.
2026-05-07 11:16:13 +00:00
root 7e2747ec73 feat: implement GetGroupAttendanceStatsAsync (#14)
PR Checks / test-and-build (pull_request) Failing after 2m57s
2026-05-07 11:05:38 +00:00
Toutsu ae6be912e3 feat(#14): add GroupStats.razor attendance page
PR Checks / test-and-build (pull_request) Failing after 3m14s
2026-05-07 13:26:03 +03:00
Toutsu 116bed16a8 feat(#14): add PlayerAttendanceStats record + interface method 2026-05-07 13:26:01 +03:00
Toutsu 063de7ee3e feat(#14): add get_group_attendance_stats SQL function 2026-05-07 13:12:39 +03:00
Toutsu dbd481566c fix(#13): bump version label in NavMenu to v1.10.1
PR Checks / test-and-build (pull_request) Successful in 3m57s
2026-05-07 10:32:23 +03:00
Toutsu 8c1e7991cd feat(#13): add calendar subscription link to Telegram export 2026-05-07 10:22:35 +03:00
Toutsu c1fdba510b feat(#13): add Web:BaseUrl config for calendar subscription links 2026-05-07 10:21:07 +03:00
Toutsu 435399dcf2 fix(#13): revert ExportCalendarHandler subscription logic (cross-project ref) 2026-05-07 10:18:25 +03:00
Toutsu ddaa0f4279 feat(#13): register CalendarSubscriptionService and add public /calendar/{token}.ics endpoint 2026-05-07 10:16:02 +03:00
Toutsu b205967f1a feat(#13): add CalendarSubscriptionService with token generation and ICS rendering 2026-05-07 10:15:06 +03:00
Toutsu 7457315d6f feat(#13): add SubscriptionNotFoundException 2026-05-07 10:13:45 +03:00
Toutsu 59f9904d66 feat(#13): add CalendarSubscriptionFilter enum 2026-05-07 10:12:34 +03:00
root 3b91a009ea feat(#13): add calendar subscriptions migration 2026-05-07 06:59:56 +00:00
root dc26b4d7e4 test: trigger pr-checks workflow
PR Checks / test-and-build (pull_request) Successful in 4m24s
2026-05-06 10:25:02 +00:00
root bc6136d91e chore(web): bump NavMenu version label to v1.10.0
Deploy Telegram Bot / build-and-push (push) Successful in 4m13s
Deploy Telegram Bot / deploy (push) Successful in 13s
2026-05-06 10:24:32 +00:00
root 89b5196676 fix(#22): resolve Telegram namespace collision and add missing MoscowTime using
Deploy Telegram Bot / build-and-push (push) Successful in 7m24s
Deploy Telegram Bot / deploy (push) Successful in 12s
2026-05-06 09:23:52 +00:00
root 14b9bf15f2 refactor(#22): разделить SessionBatchRenderer на neutral view и Telegram renderer
- SessionBatchViewBuilder в Shared собирает нейтральную view model
- TelegramSessionBatchRenderer в Bot/Web рендерит HTML + InlineKeyboardMarkup
- DiscordSessionBatchRenderer заглушка подготовлена
- BatchMessageEditor перенесён из Shared в Bot/Web
- Удалён SessionBatchRenderer, убран Telegram.Bot из Shared.csproj
- Обновлены все вызовы (7 handler-ов + Web SessionService + smoke tests)
- Новые тесты на builder и Telegram renderer
2026-05-06 08:28:25 +00:00
Toutsu 5dee2d87f5 test: cover Telegram landing promise smoke
Deploy Telegram Bot / build-and-push (push) Successful in 5m32s
Deploy Telegram Bot / deploy (push) Successful in 12s
2026-05-05 13:06:09 +03:00
root c1f5d96e25 feat: show participant list, kick player, auto-promote waitlist 2026-05-04 17:11:23 +00:00
Toutsu c874f7b797 fix: combine session image and text into single Telegram message
Deploy Telegram Bot / build-and-push (push) Successful in 4m2s
Deploy Telegram Bot / deploy (push) Successful in 10s
When creating a session with an image, send it as a single SendPhoto
with the schedule text as caption (+ reply markup), instead of two
separate messages. Falls back to two messages if caption exceeds
Telegram's 1024-char limit.

Also adds BatchMessageEditor helper that transparently handles
EditMessageText vs EditMessageCaption depending on whether the batch
message is a text or photo message. Updated all handlers and web
service to use this helper.

Version bump to 1.9.7.
2026-05-04 10:33:06 +03:00
Toutsu aefed5abd4 feat: improve telegram session posts
Deploy Telegram Bot / build-and-push (push) Successful in 4m28s
Deploy Telegram Bot / deploy (push) Successful in 11s
2026-05-04 09:52:07 +03:00
Toutsu 25c22b2ff5 fix: stabilize session table layout
Deploy Telegram Bot / build-and-push (push) Successful in 4m6s
Deploy Telegram Bot / deploy (push) Successful in 12s
2026-05-02 15:40:24 +03:00
Toutsu cb40c2438d docs: clarify mini app dashboard for GMs
Deploy Telegram Bot / build-and-push (push) Successful in 4m18s
Deploy Telegram Bot / deploy (push) Successful in 12s
2026-04-28 21:01:30 +03:00
Toutsu 2a76ec0fb8 fix: stabilize mini app login and safe area
Deploy Telegram Bot / build-and-push (push) Successful in 3m53s
Deploy Telegram Bot / deploy (push) Successful in 17s
2026-04-28 20:25:18 +03:00
Toutsu 57c8714889 fix: refresh login fallback in mini app
Deploy Telegram Bot / build-and-push (push) Successful in 4m11s
Deploy Telegram Bot / deploy (push) Successful in 12s
2026-04-28 17:20:29 +03:00