# GM-Relay - C4 Model ## Level 1: System Context ```mermaid C4Context title GM-Relay System Context Person(gm, "Game Master", "Creates sessions and manages schedules") Person(player, "Player", "Joins, leaves, confirms, and receives reminders") System(gmrelay, "GM-Relay", "Telegram bot, Discord worker, web dashboard, and shared scheduling logic") System_Ext(telegram, "Telegram Bot API", "Commands, inline keyboards, callback queries, Mini App entry points") System_Ext(discord, "Discord Gateway and REST API", "Slash commands, button interactions, message edits, ephemeral replies") SystemDb_Ext(postgres, "PostgreSQL", "Sessions, players, participants, groups, platform identities") Rel(gm, telegram, "Creates and manages sessions") Rel(gm, discord, "Uses /newsession and /listsessions") Rel(player, telegram, "Uses inline buttons") Rel(player, discord, "Uses Join/Leave buttons") Rel(telegram, gmrelay, "Updates via long polling") Rel(discord, gmrelay, "Gateway events and component interactions") Rel(gmrelay, telegram, "SendMessage, EditMessage, AnswerCallbackQuery") Rel(gmrelay, discord, "Send/edit schedule messages and ephemeral interaction replies") Rel(gmrelay, postgres, "SQL via Npgsql and Dapper") ``` ## Level 2: Container ```mermaid C4Container title GM-Relay Containers Person(gm, "Game Master") Person(player, "Player") System_Boundary(runtime, "Docker Compose / Aspire runtime") { Container(bot, "GmRelay.Bot", "Worker Service, .NET 10 AOT", "Telegram long polling, commands, callback routing, reminders") Container(discordBot, "GmRelay.DiscordBot", "Worker Service, .NET 10", "NetCord Gateway, slash commands, Join/Leave button interactions") Container(web, "GmRelay.Web", "Blazor Server", "Dashboard, Mini App pages, editing and stats") Container(shared, "GmRelay.Shared", ".NET library", "Shared domain models, rendering, and platform-neutral join/leave handlers") ContainerDb(db, "PostgreSQL", "Database", "sessions, players, session_participants, game_groups, platform identities") } System_Ext(telegram, "Telegram Bot API") System_Ext(discord, "Discord Gateway and REST API") Rel(gm, telegram, "Commands") Rel(gm, discord, "Slash commands") Rel(player, telegram, "Callback queries") Rel(player, discord, "Button interactions") Rel(telegram, bot, "GetUpdates") Rel(discord, discordBot, "Gateway events") Rel(bot, telegram, "Bot API calls") Rel(discordBot, discord, "REST send/edit/reply calls") Rel(bot, shared, "Uses shared renderers and join/leave handlers") Rel(discordBot, shared, "Uses shared renderers and join/leave handlers") Rel(web, shared, "Uses shared domain and rendering models") Rel(bot, db, "Npgsql + Dapper.AOT") Rel(discordBot, db, "Npgsql + Dapper") Rel(web, db, "Npgsql + Dapper") ``` ## Level 3: Component - Session Interactions ```mermaid C4Component title Platform-Neutral Session Interactions Container_Boundary(shared, "GmRelay.Shared") { Component(join, "JoinSessionHandler", "Feature handler", "Adds players as Active or Waitlisted with session row locking") Component(leave, "LeaveSessionHandler", "Feature handler", "Removes players and promotes the first waitlisted player when capacity allows") Component(updateLock, "ScheduleMessageUpdateLock", "In-memory keyed lock", "Serializes DB changes and schedule message edits per platform message") Component(renderer, "SessionBatchViewBuilder", "Renderer model builder", "Builds platform-neutral schedule views and actions") } Container_Boundary(discordBot, "GmRelay.DiscordBot") { Component(discordModule, "DiscordSessionInteractionModule", "NetCord component module", "Maps join_session/leave_session buttons to neutral commands") Component(discordMessenger, "DiscordPlatformMessenger", "IPlatformMessenger", "Edits Discord schedule messages and stores interaction replies") } Container_Boundary(bot, "GmRelay.Bot") { Component(updateRouter, "UpdateRouter", "Telegram adapter", "Maps callback queries to neutral commands") Component(telegramMessenger, "TelegramPlatformMessenger", "IPlatformMessenger", "Edits Telegram schedule messages and answers callback queries") } ContainerDb(db, "PostgreSQL") System_Ext(telegram, "Telegram Bot API") System_Ext(discord, "Discord Gateway and REST API") Rel(discord, discordModule, "Button interaction") Rel(discordModule, join, "JoinSessionCommand") Rel(discordModule, leave, "LeaveSessionCommand") Rel(discordModule, discord, "Deferred ephemeral reply, then modify response") Rel(updateRouter, join, "JoinSessionCommand") Rel(updateRouter, leave, "LeaveSessionCommand") Rel(join, updateLock, "Acquire by PlatformMessageRef") Rel(leave, updateLock, "Acquire by PlatformMessageRef") Rel(join, db, "SELECT FOR UPDATE, INSERT participant") Rel(leave, db, "SELECT FOR UPDATE, DELETE/promote participant") Rel(join, renderer, "Build updated schedule view") Rel(leave, renderer, "Build updated schedule view") Rel(join, discordMessenger, "Update Discord schedule when command is Discord") Rel(leave, discordMessenger, "Update Discord schedule when command is Discord") Rel(join, telegramMessenger, "Update Telegram schedule when command is Telegram") Rel(leave, telegramMessenger, "Update Telegram schedule when command is Telegram") Rel(discordMessenger, discord, "ModifyMessage + ephemeral text") Rel(telegramMessenger, telegram, "EditMessage + AnswerCallbackQuery") ```