Commit Graph

237 Commits

Author SHA1 Message Date
Toutsu e5945288ac feat(web): add local portfolio cover storage 2026-06-02 12:35:00 +03:00
Toutsu 7d1489445e feat(web): define portfolio contracts and validation 2026-06-02 12:21:55 +03:00
Toutsu a20da4b1a0 fix(data): serialize portfolio mutations before rows 2026-06-02 10:32:13 +03:00
Toutsu 1a8161027c fix(data): reject stale reschedule snapshots 2026-06-02 07:57:30 +03:00
Toutsu ea714480d3 fix(data): serialize new-link publication races 2026-06-02 07:31:35 +03:00
Toutsu 1d62f69ff0 fix(data): lock racing portfolio publications 2026-06-02 07:10:37 +03:00
Toutsu d762ecc377 fix(data): serialize portfolio future reschedules 2026-06-01 20:58:53 +03:00
Toutsu a28b75dd5b fix(data): align portfolio mutation lock order 2026-06-01 20:23:43 +03:00
Toutsu da0a306340 fix(data): enforce completed portfolio sessions 2026-06-01 15:04:20 +03:00
Toutsu f493836b77 fix(data): reject stale portfolio trigger snapshots 2026-06-01 14:39:04 +03:00
Toutsu 6e7a0cb493 fix(data): enforce portfolio validation isolation 2026-06-01 14:28:51 +03:00
Toutsu 76b3ff7ddf fix(data): serialize portfolio publication validation 2026-06-01 14:12:29 +03:00
Toutsu 3c1a98bcc4 fix(data): harden portfolio publication concurrency 2026-06-01 09:46:18 +03:00
Toutsu d591e5ed5a fix(data): protect portfolio publication invariant 2026-06-01 09:20:27 +03:00
Toutsu ed842d2195 test(data): harden portfolio migration contract 2026-05-30 23:37:40 +03:00
Toutsu 67b8aafd97 feat(data): add completed game portfolio schema 2026-05-30 23:21:31 +03:00
Toutsu d54950698a feat(web): redesign profile page to match design system
PR Checks / test-and-build (pull_request) Successful in 12m8s
- Rewrite Profile.razor to use .page-container, .glass-card, .gm-alert,

  .btn-gm, .status-badge, .empty-state and other standard design system classes

- Replace custom unstyled markup with breadcrumb, page-header, skeleton loaders

- Add .identity-list styles to app.css for linked accounts section

- Unify visual language with Home, Templates and GroupDetails pages
2026-05-29 15:15:48 +03:00
Toutsu b52d4000b4 fix(web): restore public game pages
PR Checks / test-and-build (pull_request) Successful in 11m56s
Use the existing group_managers.created_at column when picking owner profile links for public pages.

Bump version -> 3.5.1
2026-05-29 09:27:01 +03:00
Toutsu 0c1d3abd7e feat(web): add public master profiles
PR Checks / test-and-build (pull_request) Successful in 12m32s
Add sanitized public GM profiles with publication controls, public /gm/{slug} pages, and links from public game surfaces.

Bump version -> 3.5.0
2026-05-29 00:08:14 +03:00
Toutsu accb3b2405 fix(web): правильный парсинг query string для ?register=1
PR Checks / test-and-build (pull_request) Successful in 12m50s
Заменен Navigation.Uri.Contains() на QueryHelpers.ParseQuery
для корректного определения параметра register без ложных
срабатываний на подстроки (например, register=10).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 17:28:51 +03:00
Toutsu a63e3bef1e fix: финальные правки ревью для issue #39
PR Checks / test-and-build (pull_request) Successful in 13m16s
- PublicSession.razor: добавлена обработка ?register=1, AuthStateProvider,
  TryGetPlatformIdentity, кнопки записи для авторизованных/неавторизованных
  пользователей, отображение результата регистрации
- CreateSessionHandler: добавлен cover_image_url в INSERT SQL
- DiscordProjectStructureTests: версия 3.4.0 во всех проверках
- README.md: актуальная версия v3.4.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 17:00:33 +03:00
Toutsu 9d9aca53df chore: bump version to 3.4.0 2026-05-28 16:43:11 +03:00
Toutsu 76c6818952 fix(shared): add missing Platform parameter in players upsert 2026-05-28 16:28:25 +03:00
Toutsu 633a020212 fix(shared): convert GameSystem to string in SQL, guard rollback after commit 2026-05-28 16:26:54 +03:00
Toutsu ab38238fe8 feat(shared): extend CreateSessionCommand with showcase metadata
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:20:44 +03:00
Toutsu 4145cacc52 fix(web): add session-description styles for public session detail 2026-05-28 16:18:58 +03:00
Toutsu 6d59737d07 feat(web): update public session detail with showcase fields
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:13:35 +03:00
Toutsu 71ffcce06b fix(web): add try/finally, concurrency guard, accessible label, registration link to showcase 2026-05-28 16:07:09 +03:00
Toutsu 72f43dbef2 feat(web): add /showcase catalog page with filters
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:00:21 +03:00
Toutsu a5f4a68c6a fix(web): add public-session guards and ON CONFLICT to RegisterFromShowcaseAsync 2026-05-28 15:40:21 +03:00
Toutsu b2497ed877 feat(web): add showcase query and registration methods 2026-05-28 15:27:18 +03:00
Toutsu 9b42ea034a fix(shared): align GameSystem enum with spec, make TryParseFuzzy nullable and display-name based 2026-05-28 15:06:39 +03:00
Toutsu f94bea3e74 feat(shared): add GameSystem enum and Showcase DTOs
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 14:58:49 +03:00
Toutsu cde1e4311f feat(db): V027 add showcase fields to sessions 2026-05-28 14:46:04 +03:00
Toutsu 3418d1a46c feat: add public club pages
PR Checks / test-and-build (pull_request) Successful in 12m47s
Add publication settings for clubs and sessions, read-only public club/session pages, dashboard controls, privacy-focused public queries, docs, and tests.

Bump version to 3.3.0
2026-05-28 12:23:47 +03:00
Toutsu fac5d75c7e Fix Discord co-GM management
Deploy Telegram Bot / build-and-push (push) Successful in 5m58s
Deploy Telegram Bot / scan-images (push) Successful in 3m39s
Deploy Telegram Bot / deploy (push) Successful in 34s
2026-05-27 16:32:47 +03:00
Toutsu 7a2965b43f fix(bot): add missing DI registrations for shared DeleteSessionHandler and ListSessionsHandler
Deploy Telegram Bot / build-and-push (push) Successful in 6m39s
Deploy Telegram Bot / scan-images (push) Successful in 3m26s
Deploy Telegram Bot / deploy (push) Successful in 29s
PR #106 extracted DeleteSessionHandler and ListSessionsHandler to GmRelay.Shared,
but forgot to register the shared implementations in Program.cs. This caused
an InvalidOperationException at startup on Native AOT builds because the Bot
wrappers could not resolve their shared dependencies.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 15:58:51 +03:00
Toutsu 542f15f2d6 refactor: extract remaining Telegram handlers to platform-neutral contracts
PR Checks / test-and-build (pull_request) Successful in 13m48s
- Extract CreateSessionHandler, ListSessionsHandler, DeleteSessionHandler,
  ExportCalendarHandler, HandleRescheduleTimeInputHandler,
  HandleRescheduleVoteHandler to GmRelay.Shared
- Add IPlatformMessenger methods: SendScheduleAsync, UpdateScheduleAsync,
  SendGroupMessageAsync with actions, CreateThreadAsync, DeleteThreadAsync
- Rewrite Telegram Bot wrappers as thin adapters delegating to shared handlers
- Rewrite DiscordRescheduleVoteHandler to use shared HandleRescheduleVoteHandler
- Update UpdateRouter with explicit type aliases for ambiguous handler names
- Add contract and source-inspection tests for extracted handlers
- Bump version 3.1.1 → 3.2.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 14:52:09 +03:00
Toutsu 383e2c1d8d fix: create Telegram topics for template batches
PR Checks / test-and-build (pull_request) Successful in 12m56s
Create a Telegram forum topic when Web creates a batch from a campaign template, persist thread ownership on the generated sessions, and send the batch schedule into that topic.

Bump version -> 3.1.1
2026-05-27 13:50:18 +03:00
Toutsu 040b0a3cdb refactor: завершить platform migration и удалить deprecated telegram_* scaffolding
PR Checks / test-and-build (pull_request) Failing after 13m15s
- Добавлены миграции V024 (backfill + deprecation comments + calendar_subscriptions platform identity) и V025 (backfill proposed_by_external_user_id)
- Все Bot handlers переведены с telegram_id/chat_id на platform + external_*
- Shared handlers очищены от COALESCE fallback с telegram_* колонками
- DiscordBot очищен от COALESCE fallback
- Web SessionService и CalendarSubscriptionService переведены на external_*
- HandleRsvpHandler: убран legacy UNION с gm_telegram_id, теперь только group_managers
- RescheduleVotingFinalizer: переведен на external_username/external_user_id
- Tests: добавлены asserts для V024/V025
- Версия обновлена до 3.1.0

Bump version → 3.1.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 16:41:15 +03:00
Toutsu a5aed14dd2 fix(discord): add backoff to scheduler to prevent 403 spam
Deploy Telegram Bot / build-and-push (push) Successful in 6m37s
Deploy Telegram Bot / scan-images (push) Successful in 3m45s
Deploy Telegram Bot / deploy (push) Successful in 33s
- SessionSchedulerService now backs off for 15 minutes after any
  handler failure (confirmation, one-hour reminder, join link),
  preventing infinite retry loops on Discord 403 Missing Access.
- Added per-session ConcurrentDictionary backoff tracking with
  automatic cleanup on success.
- Enhanced DiscordPlatformMessenger logging for SendConfirmation
  and SendJoinLink to aid permission diagnostics.
- Added 3 regression tests for backoff behavior.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 15:51:25 +03:00
Toutsu 9fc434b42b fix(discord): treat /newsession and /reschedule input as Moscow time (UTC+3)
Deploy Telegram Bot / build-and-push (push) Successful in 6m15s
Deploy Telegram Bot / scan-images (push) Successful in 3m20s
Deploy Telegram Bot / deploy (push) Successful in 34s
DiscordNewSessionHandler.ParseTimeInput used DateTimeStyles.AssumeUniversal,
which interpreted user input as UTC. A user entering 15:00 got a session
scheduled at 18:00 MSK after rendering. Align with Telegram behavior by
treating input as Moscow time and converting to UTC before storage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 15:12:00 +03:00
Toutsu c2cc7fd9a8 fix(web): show discord sessions and integration labels
Deploy Telegram Bot / build-and-push (push) Successful in 5m46s
Deploy Telegram Bot / scan-images (push) Successful in 3m29s
Deploy Telegram Bot / deploy (push) Successful in 29s
2026-05-26 14:43:33 +03:00
Toutsu 3447acd8c4 fix(discord): update sessions via interactions
Deploy Telegram Bot / build-and-push (push) Successful in 6m14s
Deploy Telegram Bot / scan-images (push) Successful in 3m12s
Deploy Telegram Bot / deploy (push) Successful in 31s
2026-05-26 14:24:06 +03:00
Toutsu 56aeca5288 fix(discord): sanitize embed join links
Deploy Telegram Bot / build-and-push (push) Successful in 5m53s
Deploy Telegram Bot / scan-images (push) Successful in 3m6s
Deploy Telegram Bot / deploy (push) Successful in 29s
2026-05-26 13:57:11 +03:00
Toutsu 6ed0a120a0 fix(discord): avoid duplicate schedule send after new session
Deploy Telegram Bot / build-and-push (push) Successful in 6m0s
Deploy Telegram Bot / scan-images (push) Successful in 3m22s
Deploy Telegram Bot / deploy (push) Successful in 29s
2026-05-26 13:40:59 +03:00
Toutsu c955e1572f fix(db): make legacy telegram_* columns nullable for Discord multi-platform
PR Checks / test-and-build (pull_request) Successful in 18m38s
V023 migration drops NOT NULL constraints on:
- game_groups.telegram_chat_id
- game_groups.gm_telegram_id
- players.telegram_id

This allows Discord (and future platforms) to create players and
game_groups without legacy Telegram identifiers.

Bump version → 3.0.10

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 12:51:45 +03:00
Toutsu dcbd9bab41 fix(discord): add missing Dapper.AOT reference to DiscordBot project
PR Checks / test-and-build (pull_request) Successful in 11m4s
GmRelay.Shared references Dapper.AOT with PrivateAssets=all, which
prevents the runtime DLL from flowing to downstream projects. Telegram
bot works because it explicitly references Dapper.AOT directly, but
Discord bot did not — causing FileNotFoundException for Dapper.AOT
at runtime, breaking the scheduler and slash commands.

- Add Dapper.AOT 1.0.48 to GmRelay.DiscordBot.csproj
- Add regression test: DiscordWorkerProject_ShouldExist asserts
  Dapper.AOT is present in the DiscordBot csproj
- Bump version → 3.0.9

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 12:20:56 +03:00
Toutsu a5624897e9 fix(discord): add console logging and deferred responses
PR Checks / test-and-build (pull_request) Failing after 12m3s
- Add builder.Logging.AddConsole() to DiscordBot Program.cs so logs
  are visible in docker logs.
- Add granular LogInformation/LogError calls to DiscordNewSessionCommand
  and DiscordRescheduleCommand to diagnose failures.
- Use InteractionCallback.DeferredMessage() + ModifyResponseAsync pattern
  for /newsession and /reschedule to avoid Discord 3-second interaction
  timeout.
- Bump version → 3.0.8

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 11:18:09 +03:00
Toutsu 2942da0c35 fix(discord): use GuildInteractionUser.Permissions instead of REST guild lookup
PR Checks / test-and-build (pull_request) Successful in 11m25s
Replace REST GetGuildAsync/GetGuildUserAsync calls with authoritative
member.Permissions from the slash-command interaction payload. Discord
already resolves channel/guild permissions in the interaction JSON, so
we no longer need to fetch the guild via REST (which returns 404 when
the bot is not a REST member of the guild, e.g. user-installed apps).

Keep a best-effort GetGuildAsync call only to obtain OwnerId for the
permission checker fallback, swallowing 404 silently.

Bump version → 3.0.7

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 10:44:59 +03:00