From 007806a5d8d12a36e7231289ffca733554608d43 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Mon, 11 May 2026 20:11:15 +0000 Subject: [PATCH 1/4] feat(ci): add C# linter and security scanner to PR checks - dotnet format --verify-no-changes (C# code style linting) - dotnet list package --vulnerable --include-transitive (NuGet vulnerability check) - Trivy filesystem scan (CVE, secrets, dependency scanning) --- .gitea/workflows/pr-checks.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.gitea/workflows/pr-checks.yml b/.gitea/workflows/pr-checks.yml index b9177cb..2f82d1b 100644 --- a/.gitea/workflows/pr-checks.yml +++ b/.gitea/workflows/pr-checks.yml @@ -20,6 +20,31 @@ jobs: - name: Restore dependencies run: dotnet restore + # ── Linting ── + + - name: Lint C# code style + run: dotnet format --verify-no-changes --verbosity diagnostic + + # ── Security ── + + - name: Check NuGet packages for vulnerabilities + run: | + dotnet list package --vulnerable --include-transitive 2>&1 | tee nuget-audit.txt + if grep -qi "has the following vulnerable packages" nuget-audit.txt; then + echo "::error::Vulnerable NuGet packages found!" + exit 1 + fi + echo "No vulnerable packages detected." + + - name: Install Trivy + run: | + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.60.0 + + - name: Trivy filesystem security scan + run: trivy fs --exit-code 1 --severity HIGH,CRITICAL . + + # ── Build ── + - name: Build Shared run: dotnet build src/GmRelay.Shared/GmRelay.Shared.csproj --no-restore @@ -29,5 +54,7 @@ jobs: - name: Build Web (compile check) run: dotnet build src/GmRelay.Web/GmRelay.Web.csproj --no-restore + # ── Tests ── + - name: Run tests run: dotnet test tests/GmRelay.Bot.Tests/GmRelay.Bot.Tests.csproj --verbosity normal \ No newline at end of file From de9f56c97dc379cdbc059b533e5157cab48472e7 Mon Sep 17 00:00:00 2001 From: Toutsu Date: Tue, 12 May 2026 12:01:10 +0300 Subject: [PATCH 2/4] feat(#21): support selected telegram topics for schedules 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. --- .gitea/workflows/deploy.yml | 2 +- Directory.Build.props | 2 +- README.md | 4 +- compose.yaml | 4 +- .../HandleRsvp/HandleRsvpHandler.cs | 7 +- .../SendConfirmationHandler.cs | 3 + .../SendJoinLink/SendJoinLinkHandler.cs | 3 + .../CreateSession/CancelSessionHandler.cs | 12 ++- .../CreateSession/CreateSessionHandler.cs | 36 ++++++--- .../ListSessions/DeleteSessionHandler.cs | 33 ++++++-- .../HandleRescheduleTimeInputHandler.cs | 6 +- .../InitiateRescheduleHandler.cs | 2 + .../RescheduleVotingDeadlineService.cs | 3 + .../Telegram/TelegramTopicRouting.cs | 40 ++++++++++ .../Infrastructure/Telegram/UpdateRouter.cs | 4 +- .../Migrations/V015__add_topic_ownership.sql | 6 ++ src/GmRelay.Shared/Domain/MoscowTime.cs | 2 +- .../Components/Layout/NavMenu.razor | 4 +- src/GmRelay.Web/Services/SessionService.cs | 55 +++++++++---- .../TelegramTopicIntegrationSmokeTests.cs | 76 ++++++++++++++++++ .../Telegram/TelegramTopicRoutingTests.cs | 80 +++++++++++++++++++ 21 files changed, 334 insertions(+), 50 deletions(-) create mode 100644 src/GmRelay.Bot/Infrastructure/Telegram/TelegramTopicRouting.cs create mode 100644 src/GmRelay.Bot/Migrations/V015__add_topic_ownership.sql create mode 100644 tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicIntegrationSmokeTests.cs create mode 100644 tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicRoutingTests.cs diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index ff9e9e4..c31e0bc 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -6,7 +6,7 @@ on: - main env: - VERSION: 1.13.0 + VERSION: 1.14.0 jobs: # ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами) diff --git a/Directory.Build.props b/Directory.Build.props index efc3923..385424b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 1.13.0 + 1.14.0 net10.0 preview enable diff --git a/README.md b/README.md index 955faa4..f9ada98 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Проект разработан с упором на производительность, архитектуру Vertical Slice, Native AOT (для бота) и удобство развертывания с использованием .NET Aspire. -**Текущая версия:** `v1.10.2`. +**Текущая версия:** `v1.14.0`. --- @@ -16,7 +16,7 @@ - **⚡ Быстрые повторы расписания**: Для регулярной кампании можно указать одну дату, количество игр и интервал, а бот сам развернёт повторяющийся batch. - **✋ Интерактивная запись и выход**: Игроки записываются на конкретные даты и самостоятельно снимают запись нажатием одной кнопки. - **👥 Лимит мест и лист ожидания**: ГМ задаёт максимальный состав, бот не переполняет сессию, автоматически ведёт очередь ожидания и освобождённое место отдаёт первому ожидающему. -- **📁 Поддержка Форумов (Telegram Topics)**: Бот автоматически создает тему во вложенных чатах Telegram под каждую новую пачку игр. +- **📁 Поддержка Форумов (Telegram Topics)**: Если `/newsession` запущен в теме форума Telegram, расписание и групповые уведомления остаются в этой теме; при запуске из корня форума бот создает отдельную тему и сообщает о необходимости прав admin/Manage Topics, если их не хватает. - **❌ Управление сессиями**: Owner и назначенные co-GM могут создавать, отменять, удалять и переносить игры из Telegram через `/listsessions`; публичный пост записи показывает только кнопки игроков. - **🔄 Голосование за перенос**: Быстрый поиск свободного места с через свободное недель и кнопками новых времени и дедлайном. - **🔔 Уведомления**: Игрок получают за 24 часа, напоминание за 1 час, ссылку перед игрой, отмены и переносы; групповые уведомления при этом остаются. diff --git a/compose.yaml b/compose.yaml index a21fd8c..3f17b13 100644 --- a/compose.yaml +++ b/compose.yaml @@ -17,7 +17,7 @@ services: retries: 10 bot: - image: git.codeanddice.ru/toutsu/gmrelay-bot:1.13.0 + image: git.codeanddice.ru/toutsu/gmrelay-bot:1.14.0 restart: always depends_on: db: @@ -30,7 +30,7 @@ services: - gmrelay web: - image: git.codeanddice.ru/toutsu/gmrelay-web:1.13.0 + image: git.codeanddice.ru/toutsu/gmrelay-web:1.14.0 restart: always depends_on: db: diff --git a/src/GmRelay.Bot/Features/Confirmation/HandleRsvp/HandleRsvpHandler.cs b/src/GmRelay.Bot/Features/Confirmation/HandleRsvp/HandleRsvpHandler.cs index 7f231c5..987fd91 100644 --- a/src/GmRelay.Bot/Features/Confirmation/HandleRsvp/HandleRsvpHandler.cs +++ b/src/GmRelay.Bot/Features/Confirmation/HandleRsvp/HandleRsvpHandler.cs @@ -21,7 +21,8 @@ internal sealed record SessionContext( DateTime ScheduledAt, string Status, long GmTelegramId, - long TelegramChatId); + long TelegramChatId, + int? ThreadId); internal sealed record ParticipantRsvp( long TelegramId, @@ -95,7 +96,8 @@ public sealed class HandleRsvpHandler( s.scheduled_at AS ScheduledAt, s.status AS Status, g.gm_telegram_id AS GmTelegramId, - g.telegram_chat_id AS TelegramChatId + g.telegram_chat_id AS TelegramChatId, + s.thread_id AS ThreadId FROM sessions s JOIN game_groups g ON g.id = s.group_id WHERE s.id = @SessionId @@ -191,6 +193,7 @@ public sealed class HandleRsvpHandler( { await bot.SendMessage( chatId: session.TelegramChatId, + messageThreadId: session.ThreadId, text: $"🎉 Игра «{session.Title}» подтверждена! Все участники на месте.", cancellationToken: ct); } diff --git a/src/GmRelay.Bot/Features/Confirmation/SendConfirmation/SendConfirmationHandler.cs b/src/GmRelay.Bot/Features/Confirmation/SendConfirmation/SendConfirmationHandler.cs index 1a4f404..59a664d 100644 --- a/src/GmRelay.Bot/Features/Confirmation/SendConfirmation/SendConfirmationHandler.cs +++ b/src/GmRelay.Bot/Features/Confirmation/SendConfirmation/SendConfirmationHandler.cs @@ -15,6 +15,7 @@ internal sealed record SessionInfo( DateTime ScheduledAt, Guid GroupId, long TelegramChatId, + int? ThreadId, string NotificationMode); internal sealed record ParticipantInfo( @@ -43,6 +44,7 @@ public sealed class SendConfirmationHandler( """ SELECT s.id, s.title, s.scheduled_at AS ScheduledAt, s.group_id AS GroupId, g.telegram_chat_id AS TelegramChatId, + s.thread_id AS ThreadId, s.notification_mode AS NotificationMode FROM sessions s JOIN game_groups g ON g.id = s.group_id @@ -99,6 +101,7 @@ public sealed class SendConfirmationHandler( // 4. Send to group var message = await bot.SendMessage( chatId: session.TelegramChatId, + messageThreadId: session.ThreadId, text: text, replyMarkup: keyboard, cancellationToken: ct); diff --git a/src/GmRelay.Bot/Features/Reminders/SendJoinLink/SendJoinLinkHandler.cs b/src/GmRelay.Bot/Features/Reminders/SendJoinLink/SendJoinLinkHandler.cs index 261b041..593ce60 100644 --- a/src/GmRelay.Bot/Features/Reminders/SendJoinLink/SendJoinLinkHandler.cs +++ b/src/GmRelay.Bot/Features/Reminders/SendJoinLink/SendJoinLinkHandler.cs @@ -14,6 +14,7 @@ internal sealed record JoinLinkSession( string JoinLink, DateTime ScheduledAt, long TelegramChatId, + int? ThreadId, string NotificationMode); internal sealed record ConfirmedPlayer( @@ -42,6 +43,7 @@ public sealed class SendJoinLinkHandler( """ SELECT s.id, s.title, s.join_link AS JoinLink, s.scheduled_at AS ScheduledAt, g.telegram_chat_id AS TelegramChatId, + s.thread_id AS ThreadId, s.notification_mode AS NotificationMode FROM sessions s JOIN game_groups g ON g.id = s.group_id @@ -94,6 +96,7 @@ public sealed class SendJoinLinkHandler( // 4. Send var message = await bot.SendMessage( chatId: session.TelegramChatId, + messageThreadId: session.ThreadId, text: text, cancellationToken: ct); diff --git a/src/GmRelay.Bot/Features/Sessions/CreateSession/CancelSessionHandler.cs b/src/GmRelay.Bot/Features/Sessions/CreateSession/CancelSessionHandler.cs index 9d3e428..16af575 100644 --- a/src/GmRelay.Bot/Features/Sessions/CreateSession/CancelSessionHandler.cs +++ b/src/GmRelay.Bot/Features/Sessions/CreateSession/CancelSessionHandler.cs @@ -14,6 +14,7 @@ public sealed record CancelSessionCommand( long TelegramUserId, string CallbackQueryId, long ChatId, + int? MessageThreadId, int MessageId); // DTOs for AOT compilation @@ -29,7 +30,7 @@ public sealed class CancelSessionHandler( { await using var connection = await dataSource.OpenConnectionAsync(ct); await using var transaction = await connection.BeginTransactionAsync(ct); - + // 1. Проверяем, что запрос делает управляющий данной группы. var session = await connection.QuerySingleOrDefaultAsync( """ @@ -117,9 +118,14 @@ public sealed class CancelSessionHandler( ct); await bot.AnswerCallbackQuery(command.CallbackQueryId, "Сессия отменена!", cancellationToken: ct); - + // Опционально: написать отдельное сообщение в чат - await bot.SendMessage(command.ChatId, $"❌ Внимание! Сессия \"{System.Net.WebUtility.HtmlEncode(session.Title)}\" отменена.", parseMode: Telegram.Bot.Types.Enums.ParseMode.Html, cancellationToken: ct); + await bot.SendMessage( + chatId: command.ChatId, + messageThreadId: command.MessageThreadId, + text: $"❌ Внимание! Сессия \"{System.Net.WebUtility.HtmlEncode(session.Title)}\" отменена.", + parseMode: Telegram.Bot.Types.Enums.ParseMode.Html, + cancellationToken: ct); var mode = SessionNotificationModeExtensions.FromDatabaseValue(session.NotificationMode); if (mode.ShouldSendDirectMessages()) diff --git a/src/GmRelay.Bot/Features/Sessions/CreateSession/CreateSessionHandler.cs b/src/GmRelay.Bot/Features/Sessions/CreateSession/CreateSessionHandler.cs index a55e2b5..b49ed5a 100644 --- a/src/GmRelay.Bot/Features/Sessions/CreateSession/CreateSessionHandler.cs +++ b/src/GmRelay.Bot/Features/Sessions/CreateSession/CreateSessionHandler.cs @@ -144,14 +144,31 @@ public sealed class CreateSessionHandler( transaction); } - int? messageThreadId = null; - if (message.Chat.IsForum) + var topicDestination = TelegramTopicRouting.ResolveNewScheduleDestination( + message.Chat.IsForum, + message.MessageThreadId); + var messageThreadId = topicDestination.MessageThreadId; + var topicCreatedByBot = topicDestination.TopicCreatedByBot; + if (topicDestination.ShouldCreateForumTopic) { - var topic = await botClient.CreateForumTopic( - chatId: chatId, - name: $"🎲 Игры: {title}", - cancellationToken: cancellationToken); - messageThreadId = topic.MessageThreadId; + try + { + var topic = await botClient.CreateForumTopic( + chatId: chatId, + name: $"🎲 Игры: {title}", + cancellationToken: cancellationToken); + messageThreadId = topic.MessageThreadId; + } + catch (Telegram.Bot.Exceptions.ApiRequestException ex) + when (TelegramTopicRouting.IsMissingForumTopicRightsError(ex.Message)) + { + await transaction.RollbackAsync(cancellationToken); + await botClient.SendMessage( + chatId, + TelegramTopicRouting.MissingForumTopicRightsMessage, + cancellationToken: cancellationToken); + return; + } } var batchId = Guid.NewGuid(); @@ -161,8 +178,8 @@ public sealed class CreateSessionHandler( { var sessionId = await connection.ExecuteScalarAsync( """ - INSERT INTO sessions (batch_id, group_id, title, join_link, scheduled_at, status, thread_id, max_players) - VALUES (@BatchId, @GroupId, @Title, @Link, @ScheduledAt, @Status, @ThreadId, @MaxPlayers) + INSERT INTO sessions (batch_id, group_id, title, join_link, scheduled_at, status, thread_id, topic_created_by_bot, max_players) + VALUES (@BatchId, @GroupId, @Title, @Link, @ScheduledAt, @Status, @ThreadId, @TopicCreatedByBot, @MaxPlayers) RETURNING id; """, new @@ -173,6 +190,7 @@ public sealed class CreateSessionHandler( Link = link, ScheduledAt = scheduledAt, ThreadId = messageThreadId, + TopicCreatedByBot = topicCreatedByBot, MaxPlayers = parseResult.MaxPlayers, Status = SessionStatus.Planned }, diff --git a/src/GmRelay.Bot/Features/Sessions/ListSessions/DeleteSessionHandler.cs b/src/GmRelay.Bot/Features/Sessions/ListSessions/DeleteSessionHandler.cs index edddbf5..46ed206 100644 --- a/src/GmRelay.Bot/Features/Sessions/ListSessions/DeleteSessionHandler.cs +++ b/src/GmRelay.Bot/Features/Sessions/ListSessions/DeleteSessionHandler.cs @@ -1,6 +1,7 @@ using Dapper; using Npgsql; using Telegram.Bot; +using GmRelay.Bot.Infrastructure.Telegram; using GmRelay.Shared.Domain; namespace GmRelay.Bot.Features.Sessions.ListSessions; @@ -12,7 +13,13 @@ public sealed record DeleteSessionCommand( long ChatId, int MessageId); -internal sealed record DeleteSessionInfoDto(string Title, Guid BatchId, bool CanManage, int? ThreadId); +internal sealed record DeleteSessionInfoDto( + string Title, + Guid BatchId, + Guid GroupId, + bool CanManage, + int? ThreadId, + bool TopicCreatedByBot); public sealed class DeleteSessionHandler( NpgsqlDataSource dataSource, @@ -29,7 +36,9 @@ public sealed class DeleteSessionHandler( """ SELECT s.title AS Title, s.batch_id AS BatchId, + s.group_id AS GroupId, s.thread_id AS ThreadId, + s.topic_created_by_bot AS TopicCreatedByBot, EXISTS ( SELECT 1 FROM group_managers gm @@ -57,15 +66,23 @@ public sealed class DeleteSessionHandler( // 2. Delete session await connection.ExecuteAsync("DELETE FROM sessions WHERE id = @Id", new { Id = command.SessionId }, transaction); - // 3. Check if any sessions are left in the batch - var remainingInBatch = await connection.ExecuteScalarAsync( - "SELECT COUNT(*) FROM sessions WHERE batch_id = @BatchId", - new { BatchId = session.BatchId }, transaction); + var remainingInTopic = session.ThreadId.HasValue + ? await connection.ExecuteScalarAsync( + """ + SELECT COUNT(*) + FROM sessions + WHERE group_id = @GroupId + AND thread_id = @ThreadId + """, + new { session.GroupId, ThreadId = session.ThreadId.Value }, + transaction) + : 0; await transaction.CommitAsync(ct); - // 4. If no sessions left and we have a forum topic, delete the topic - if (remainingInBatch == 0 && session.ThreadId.HasValue) + // 4. If no sessions are left in a bot-owned forum topic, delete the topic. + if (session.ThreadId.HasValue && + TelegramTopicRouting.ShouldDeleteForumTopic(session.TopicCreatedByBot, remainingInTopic)) { try { @@ -113,7 +130,7 @@ public sealed class DeleteSessionHandler( if (sessionsList.Count == 0) { - try { await bot.EditMessageText(command.ChatId, command.MessageId, "📭 В этой группе нет предстоящих игр.", cancellationToken: ct); } catch {} + try { await bot.EditMessageText(command.ChatId, command.MessageId, "📭 В этой группе нет предстоящих игр.", cancellationToken: ct); } catch { } return; } diff --git a/src/GmRelay.Bot/Features/Sessions/RescheduleSession/HandleRescheduleTimeInputHandler.cs b/src/GmRelay.Bot/Features/Sessions/RescheduleSession/HandleRescheduleTimeInputHandler.cs index e255761..e1569e6 100644 --- a/src/GmRelay.Bot/Features/Sessions/RescheduleSession/HandleRescheduleTimeInputHandler.cs +++ b/src/GmRelay.Bot/Features/Sessions/RescheduleSession/HandleRescheduleTimeInputHandler.cs @@ -14,7 +14,7 @@ namespace GmRelay.Bot.Features.Sessions.RescheduleSession; internal sealed record AwaitingProposalDto( Guid Id, Guid SessionId, string Title, DateTime CurrentScheduledAt, - Guid BatchId, int? BatchMessageId, long TelegramChatId, string NotificationMode); + Guid BatchId, int? BatchMessageId, long TelegramChatId, int? ThreadId, string NotificationMode); internal sealed record VoteParticipantDto( Guid PlayerId, @@ -57,6 +57,7 @@ public sealed class HandleRescheduleTimeInputHandler( SELECT rp.id AS Id, rp.session_id AS SessionId, s.title AS Title, s.scheduled_at AS CurrentScheduledAt, s.batch_id AS BatchId, s.batch_message_id AS BatchMessageId, g.telegram_chat_id AS TelegramChatId, + s.thread_id AS ThreadId, s.notification_mode AS NotificationMode FROM reschedule_proposals rp JOIN sessions s ON s.id = rp.session_id @@ -84,6 +85,7 @@ public sealed class HandleRescheduleTimeInputHandler( { await bot.SendMessage( chatId: chatId, + messageThreadId: proposal.ThreadId, text: $"⚠️ {parseError}\n\nИспользуйте формат:\n25.04.2026 19:30\n26.04.2026 18:00\nДедлайн: 25.04.2026 12:00", parseMode: Telegram.Bot.Types.Enums.ParseMode.Html, cancellationToken: ct); @@ -161,6 +163,7 @@ public sealed class HandleRescheduleTimeInputHandler( var voteMsg = await bot.SendMessage( chatId: chatId, + messageThreadId: proposal.ThreadId, text: voteText, parseMode: Telegram.Bot.Types.Enums.ParseMode.Html, replyMarkup: keyboard, @@ -242,6 +245,7 @@ public sealed class HandleRescheduleTimeInputHandler( await bot.SendMessage( chatId: chatId, + messageThreadId: proposal.ThreadId, text: $"✅ Сессия «{proposal.Title}» перенесена!\n\n📅 Новое время: {newTime.ToOffset(TimeSpan.FromHours(3)).ToString("d MMMM yyyy, HH:mm", System.Globalization.CultureInfo.GetCultureInfo("ru-RU"))} (МСК)\n\nУчастников нет — голосование не требуется.", parseMode: Telegram.Bot.Types.Enums.ParseMode.Html, cancellationToken: ct); diff --git a/src/GmRelay.Bot/Features/Sessions/RescheduleSession/InitiateRescheduleHandler.cs b/src/GmRelay.Bot/Features/Sessions/RescheduleSession/InitiateRescheduleHandler.cs index c6238ff..fd813fc 100644 --- a/src/GmRelay.Bot/Features/Sessions/RescheduleSession/InitiateRescheduleHandler.cs +++ b/src/GmRelay.Bot/Features/Sessions/RescheduleSession/InitiateRescheduleHandler.cs @@ -12,6 +12,7 @@ public sealed record InitiateRescheduleCommand( long TelegramUserId, string CallbackQueryId, long ChatId, + int? MessageThreadId, int MessageId); // ── DTOs ───────────────────────────────────────────────────────────── @@ -96,6 +97,7 @@ public sealed class InitiateRescheduleHandler( await bot.SendMessage( chatId: command.ChatId, + messageThreadId: command.MessageThreadId, text: $""" ⏰ Укажите 2-3 варианта времени для сессии «{session.Title}» и дедлайн голосования. diff --git a/src/GmRelay.Bot/Features/Sessions/RescheduleSession/RescheduleVotingDeadlineService.cs b/src/GmRelay.Bot/Features/Sessions/RescheduleSession/RescheduleVotingDeadlineService.cs index 3c856cd..012f4a1 100644 --- a/src/GmRelay.Bot/Features/Sessions/RescheduleSession/RescheduleVotingDeadlineService.cs +++ b/src/GmRelay.Bot/Features/Sessions/RescheduleSession/RescheduleVotingDeadlineService.cs @@ -20,6 +20,7 @@ internal sealed record DueRescheduleProposalDto( int? BatchMessageId, int? VoteMessageId, long TelegramChatId, + int? ThreadId, string NotificationMode); public sealed class RescheduleVotingDeadlineService( @@ -93,6 +94,7 @@ public sealed class RescheduleVotingDeadlineService( s.batch_id AS BatchId, s.batch_message_id AS BatchMessageId, s.notification_mode AS NotificationMode, + s.thread_id AS ThreadId, g.telegram_chat_id AS TelegramChatId FROM reschedule_proposals rp JOIN sessions s ON s.id = rp.session_id @@ -324,6 +326,7 @@ public sealed class RescheduleVotingDeadlineService( { await bot.SendMessage( chatId: proposal.TelegramChatId, + messageThreadId: proposal.ThreadId, text: $"📣 Расписание обновлено после голосования за перенос сессии «{System.Net.WebUtility.HtmlEncode(proposal.Title)}».", parseMode: ParseMode.Html, cancellationToken: ct); diff --git a/src/GmRelay.Bot/Infrastructure/Telegram/TelegramTopicRouting.cs b/src/GmRelay.Bot/Infrastructure/Telegram/TelegramTopicRouting.cs new file mode 100644 index 0000000..b72528a --- /dev/null +++ b/src/GmRelay.Bot/Infrastructure/Telegram/TelegramTopicRouting.cs @@ -0,0 +1,40 @@ +namespace GmRelay.Bot.Infrastructure.Telegram; + +public sealed record TelegramTopicDestination( + int? MessageThreadId, + bool ShouldCreateForumTopic, + bool TopicCreatedByBot); + +public static class TelegramTopicRouting +{ + public const string MissingForumTopicRightsMessage = + "Не удалось создать Telegram topic. Сделайте бота admin и включите право Manage Topics, затем повторите команду."; + + public static TelegramTopicDestination ResolveNewScheduleDestination( + bool chatIsForum, + int? incomingMessageThreadId) + { + if (!chatIsForum) + { + return new TelegramTopicDestination(null, ShouldCreateForumTopic: false, TopicCreatedByBot: false); + } + + if (incomingMessageThreadId.HasValue) + { + return new TelegramTopicDestination( + incomingMessageThreadId, + ShouldCreateForumTopic: false, + TopicCreatedByBot: false); + } + + return new TelegramTopicDestination(null, ShouldCreateForumTopic: true, TopicCreatedByBot: true); + } + + public static bool ShouldDeleteForumTopic(bool topicCreatedByBot, int remainingSessionsInTopic) => + topicCreatedByBot && remainingSessionsInTopic == 0; + + public static bool IsMissingForumTopicRightsError(string apiError) => + apiError.Contains("not enough rights", StringComparison.OrdinalIgnoreCase) || + apiError.Contains("CHAT_ADMIN_REQUIRED", StringComparison.OrdinalIgnoreCase) || + apiError.Contains("not an administrator", StringComparison.OrdinalIgnoreCase); +} diff --git a/src/GmRelay.Bot/Infrastructure/Telegram/UpdateRouter.cs b/src/GmRelay.Bot/Infrastructure/Telegram/UpdateRouter.cs index 28a7e14..0538a55 100644 --- a/src/GmRelay.Bot/Infrastructure/Telegram/UpdateRouter.cs +++ b/src/GmRelay.Bot/Infrastructure/Telegram/UpdateRouter.cs @@ -80,7 +80,7 @@ public sealed class UpdateRouter( CallbackQueryId: query.Id, ChatId: message.Chat.Id, MessageId: message.MessageId); - + await joinSessionHandler.HandleAsync(command, ct); return; } @@ -105,6 +105,7 @@ public sealed class UpdateRouter( TelegramUserId: query.From.Id, CallbackQueryId: query.Id, ChatId: message.Chat.Id, + MessageThreadId: message.MessageThreadId, MessageId: message.MessageId); await cancelSessionHandler.HandleAsync(command, ct); @@ -144,6 +145,7 @@ public sealed class UpdateRouter( TelegramUserId: query.From.Id, CallbackQueryId: query.Id, ChatId: message.Chat.Id, + MessageThreadId: message.MessageThreadId, MessageId: message.MessageId); await initiateRescheduleHandler.HandleAsync(command, ct); diff --git a/src/GmRelay.Bot/Migrations/V015__add_topic_ownership.sql b/src/GmRelay.Bot/Migrations/V015__add_topic_ownership.sql new file mode 100644 index 0000000..1acd26e --- /dev/null +++ b/src/GmRelay.Bot/Migrations/V015__add_topic_ownership.sql @@ -0,0 +1,6 @@ +ALTER TABLE sessions + ADD COLUMN topic_created_by_bot BOOLEAN NOT NULL DEFAULT FALSE; + +UPDATE sessions +SET topic_created_by_bot = TRUE +WHERE thread_id IS NOT NULL; diff --git a/src/GmRelay.Shared/Domain/MoscowTime.cs b/src/GmRelay.Shared/Domain/MoscowTime.cs index 823f6bf..01c630b 100644 --- a/src/GmRelay.Shared/Domain/MoscowTime.cs +++ b/src/GmRelay.Shared/Domain/MoscowTime.cs @@ -21,7 +21,7 @@ public static class MoscowTime public static bool TryParseMoscow(string text, out DateTimeOffset utcTime) { - if (DateTime.TryParseExact(text, new[] { "dd.MM.yyyy HH:mm", "dd.MM.yyyy H:mm", "d.MM.yyyy HH:mm" }, + if (DateTime.TryParseExact(text, new[] { "dd.MM.yyyy HH:mm", "dd.MM.yyyy H:mm", "d.MM.yyyy HH:mm" }, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var localDt)) { utcTime = new DateTimeOffset(localDt, MoscowOffset).ToUniversalTime(); diff --git a/src/GmRelay.Web/Components/Layout/NavMenu.razor b/src/GmRelay.Web/Components/Layout/NavMenu.razor index 0afd0c0..b32e0d7 100644 --- a/src/GmRelay.Web/Components/Layout/NavMenu.razor +++ b/src/GmRelay.Web/Components/Layout/NavMenu.razor @@ -56,7 +56,7 @@ - + @@ -79,4 +79,4 @@ private void ToggleMenu() => isOpen = !isOpen; private void CloseMenu() => isOpen = false; -} \ No newline at end of file +} diff --git a/src/GmRelay.Web/Services/SessionService.cs b/src/GmRelay.Web/Services/SessionService.cs index 1524c67..ba98850 100644 --- a/src/GmRelay.Web/Services/SessionService.cs +++ b/src/GmRelay.Web/Services/SessionService.cs @@ -38,7 +38,8 @@ public sealed record WebSession( int? MaxPlayers, int ActivePlayerCount, int WaitlistedPlayerCount, - string NotificationMode = SessionNotificationModeExtensions.GroupAndDirectValue); + string NotificationMode = SessionNotificationModeExtensions.GroupAndDirectValue, + int? ThreadId = null); public sealed record WebParticipant( Guid Id, @@ -73,7 +74,8 @@ internal sealed record WebBatchSessionRow( int? BatchMessageId, long TelegramChatId, int? ThreadId, - string NotificationMode); + string NotificationMode, + bool TopicCreatedByBot = false); internal sealed record WebTemplateGroupDto(long TelegramChatId); public sealed class SessionService( @@ -314,7 +316,8 @@ public sealed class SessionService( s.max_players AS MaxPlayers, COALESCE(active_counts.count, 0)::int AS ActivePlayerCount, COALESCE(waitlist_counts.count, 0)::int AS WaitlistedPlayerCount, - s.notification_mode AS NotificationMode + s.notification_mode AS NotificationMode, + s.thread_id AS ThreadId FROM sessions s JOIN game_groups g ON g.id = s.group_id LEFT JOIN LATERAL ( @@ -351,7 +354,8 @@ public sealed class SessionService( s.max_players AS MaxPlayers, COALESCE(active_counts.count, 0)::int AS ActivePlayerCount, COALESCE(waitlist_counts.count, 0)::int AS WaitlistedPlayerCount, - s.notification_mode AS NotificationMode + s.notification_mode AS NotificationMode, + s.thread_id AS ThreadId FROM sessions s JOIN game_groups g ON g.id = s.group_id LEFT JOIN LATERAL ( @@ -409,7 +413,8 @@ public sealed class SessionService( s.max_players AS MaxPlayers, 0 AS ActivePlayerCount, 0 AS WaitlistedPlayerCount, - s.notification_mode AS NotificationMode + s.notification_mode AS NotificationMode, + s.thread_id AS ThreadId FROM sessions s JOIN game_groups g ON g.id = s.group_id WHERE s.id = @Id AND s.group_id = @GroupId", @@ -463,7 +468,11 @@ public sealed class SessionService( "\n" + $"👥 Мест: {(maxPlayers.HasValue ? maxPlayers.Value.ToString(System.Globalization.CultureInfo.InvariantCulture) : "без лимита")}"; - await bot.SendMessage(oldSession.TelegramChatId, notification, parseMode: Telegram.Bot.Types.Enums.ParseMode.Html); + await bot.SendMessage( + chatId: oldSession.TelegramChatId, + messageThreadId: oldSession.ThreadId, + text: notification, + parseMode: Telegram.Bot.Types.Enums.ParseMode.Html); var mode = SessionNotificationModeExtensions.FromDatabaseValue(oldSession.NotificationMode); if (mode.ShouldSendDirectMessages()) @@ -490,7 +499,8 @@ public sealed class SessionService( s.max_players AS MaxPlayers, 0 AS ActivePlayerCount, 0 AS WaitlistedPlayerCount, - s.notification_mode AS NotificationMode + s.notification_mode AS NotificationMode, + s.thread_id AS ThreadId FROM sessions s JOIN game_groups g ON g.id = s.group_id WHERE s.id = @SessionId AND s.group_id = @GroupId @@ -567,8 +577,9 @@ public sealed class SessionService( await transaction.CommitAsync(); await bot.SendMessage( - session.TelegramChatId, - $"⬆️ {System.Net.WebUtility.HtmlEncode(promoted.DisplayName)} переведен(а) из листа ожидания в основной состав «{System.Net.WebUtility.HtmlEncode(session.Title)}».", + chatId: session.TelegramChatId, + messageThreadId: session.ThreadId, + text: $"⬆️ {System.Net.WebUtility.HtmlEncode(promoted.DisplayName)} переведен(а) из листа ожидания в основной состав «{System.Net.WebUtility.HtmlEncode(session.Title)}».", parseMode: Telegram.Bot.Types.Enums.ParseMode.Html); if (session.BatchMessageId.HasValue) @@ -612,7 +623,8 @@ public sealed class SessionService( s.max_players AS MaxPlayers, 0 AS ActivePlayerCount, 0 AS WaitlistedPlayerCount, - s.notification_mode AS NotificationMode + s.notification_mode AS NotificationMode, + s.thread_id AS ThreadId FROM sessions s JOIN game_groups g ON g.id = s.group_id WHERE s.id = @SessionId AND s.group_id = @GroupId @@ -697,15 +709,17 @@ public sealed class SessionService( await transaction.CommitAsync(); await bot.SendMessage( - session.TelegramChatId, - $"🚪 {System.Net.WebUtility.HtmlEncode(participant.DisplayName)} удален(а) из сессии «{System.Net.WebUtility.HtmlEncode(session.Title)}».", + chatId: session.TelegramChatId, + messageThreadId: session.ThreadId, + text: $"🚪 {System.Net.WebUtility.HtmlEncode(participant.DisplayName)} удален(а) из сессии «{System.Net.WebUtility.HtmlEncode(session.Title)}».", parseMode: Telegram.Bot.Types.Enums.ParseMode.Html); if (promoted is not null) { await bot.SendMessage( - session.TelegramChatId, - $"⬆️ {System.Net.WebUtility.HtmlEncode(promoted.DisplayName)} переведен(а) из листа ожидания в основной состав «{System.Net.WebUtility.HtmlEncode(session.Title)}».", + chatId: session.TelegramChatId, + messageThreadId: session.ThreadId, + text: $"⬆️ {System.Net.WebUtility.HtmlEncode(promoted.DisplayName)} переведен(а) из листа ожидания в основной состав «{System.Net.WebUtility.HtmlEncode(session.Title)}».", parseMode: Telegram.Bot.Types.Enums.ParseMode.Html); if (session.BatchMessageId.HasValue) @@ -813,6 +827,7 @@ public sealed class SessionService( s.batch_message_id AS BatchMessageId, g.telegram_chat_id AS TelegramChatId, s.thread_id AS ThreadId, + s.topic_created_by_bot AS TopicCreatedByBot, s.notification_mode AS NotificationMode FROM sessions s JOIN game_groups g ON g.id = s.group_id @@ -865,7 +880,11 @@ public sealed class SessionService( $"🗓 Новое начало: {firstScheduledAt.FormatMoscow()} (МСК)\n" + $"↔️ Шаг: {intervalDays} дн."; - await bot.SendMessage(firstSession.TelegramChatId, notification, parseMode: Telegram.Bot.Types.Enums.ParseMode.Html); + await bot.SendMessage( + chatId: firstSession.TelegramChatId, + messageThreadId: firstSession.ThreadId, + text: notification, + parseMode: Telegram.Bot.Types.Enums.ParseMode.Html); var mode = SessionNotificationModeExtensions.FromDatabaseValue(firstSession.NotificationMode); if (mode.ShouldSendDirectMessages()) @@ -892,6 +911,7 @@ public sealed class SessionService( s.batch_message_id AS BatchMessageId, g.telegram_chat_id AS TelegramChatId, s.thread_id AS ThreadId, + s.topic_created_by_bot AS TopicCreatedByBot, s.notification_mode AS NotificationMode FROM sessions s JOIN game_groups g ON g.id = s.group_id @@ -920,8 +940,8 @@ public sealed class SessionService( var scheduledAt = BatchSchedulePlanner.ShiftForClone(sourceSession.ScheduledAt, interval); var sessionId = await conn.ExecuteScalarAsync( """ - INSERT INTO sessions (batch_id, group_id, title, join_link, scheduled_at, status, thread_id, max_players, notification_mode) - VALUES (@BatchId, @GroupId, @Title, @JoinLink, @ScheduledAt, @Status, @ThreadId, @MaxPlayers, @NotificationMode) + INSERT INTO sessions (batch_id, group_id, title, join_link, scheduled_at, status, thread_id, topic_created_by_bot, max_players, notification_mode) + VALUES (@BatchId, @GroupId, @Title, @JoinLink, @ScheduledAt, @Status, @ThreadId, @TopicCreatedByBot, @MaxPlayers, @NotificationMode) RETURNING id """, new @@ -933,6 +953,7 @@ public sealed class SessionService( ScheduledAt = scheduledAt, Status = SessionStatus.Planned, ThreadId = threadId, + sourceSession.TopicCreatedByBot, sourceSession.MaxPlayers, sourceSession.NotificationMode }, diff --git a/tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicIntegrationSmokeTests.cs b/tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicIntegrationSmokeTests.cs new file mode 100644 index 0000000..0e33432 --- /dev/null +++ b/tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicIntegrationSmokeTests.cs @@ -0,0 +1,76 @@ +namespace GmRelay.Bot.Tests.Infrastructure.Telegram; + +public sealed class TelegramTopicIntegrationSmokeTests +{ + [Fact] + public async Task BotAndWebCode_ShouldPersistAndUseTopicOwnership() + { + var migration = await ReadRepositoryFileAsync("src/GmRelay.Bot/Migrations/V015__add_topic_ownership.sql"); + var createHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Sessions/CreateSession/CreateSessionHandler.cs"); + var deleteHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Sessions/ListSessions/DeleteSessionHandler.cs"); + + Assert.Contains("topic_created_by_bot", migration, StringComparison.Ordinal); + Assert.Contains("ResolveNewScheduleDestination", createHandler, StringComparison.Ordinal); + Assert.Contains("message.MessageThreadId", createHandler, StringComparison.Ordinal); + Assert.Contains("topic_created_by_bot", createHandler, StringComparison.Ordinal); + Assert.Contains("MissingForumTopicRightsMessage", createHandler, StringComparison.Ordinal); + Assert.Contains("TopicCreatedByBot", deleteHandler, StringComparison.Ordinal); + Assert.Contains("ShouldDeleteForumTopic", deleteHandler, StringComparison.Ordinal); + Assert.Contains("remainingInTopic", deleteHandler, StringComparison.Ordinal); + } + + [Fact] + public async Task GroupNotifications_ShouldSendToStoredForumTopic() + { + var confirmationHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Confirmation/SendConfirmation/SendConfirmationHandler.cs"); + var joinLinkHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Reminders/SendJoinLink/SendJoinLinkHandler.cs"); + var rsvpHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Confirmation/HandleRsvp/HandleRsvpHandler.cs"); + var cancelHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Sessions/CreateSession/CancelSessionHandler.cs"); + var initiateRescheduleHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Sessions/RescheduleSession/InitiateRescheduleHandler.cs"); + var rescheduleInputHandler = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Sessions/RescheduleSession/HandleRescheduleTimeInputHandler.cs"); + var rescheduleDeadlineService = await ReadRepositoryFileAsync("src/GmRelay.Bot/Features/Sessions/RescheduleSession/RescheduleVotingDeadlineService.cs"); + + Assert.Contains("int? ThreadId", confirmationHandler, StringComparison.Ordinal); + Assert.Contains("s.thread_id AS ThreadId", confirmationHandler, StringComparison.Ordinal); + Assert.Contains("messageThreadId: session.ThreadId", confirmationHandler, StringComparison.Ordinal); + + Assert.Contains("int? ThreadId", joinLinkHandler, StringComparison.Ordinal); + Assert.Contains("s.thread_id AS ThreadId", joinLinkHandler, StringComparison.Ordinal); + Assert.Contains("messageThreadId: session.ThreadId", joinLinkHandler, StringComparison.Ordinal); + + Assert.Contains("int? ThreadId", rsvpHandler, StringComparison.Ordinal); + Assert.Contains("s.thread_id AS ThreadId", rsvpHandler, StringComparison.Ordinal); + Assert.Contains("messageThreadId: session.ThreadId", rsvpHandler, StringComparison.Ordinal); + + Assert.Contains("int? MessageThreadId", cancelHandler, StringComparison.Ordinal); + Assert.Contains("messageThreadId: command.MessageThreadId", cancelHandler, StringComparison.Ordinal); + + Assert.Contains("int? MessageThreadId", initiateRescheduleHandler, StringComparison.Ordinal); + Assert.Contains("messageThreadId: command.MessageThreadId", initiateRescheduleHandler, StringComparison.Ordinal); + + Assert.Contains("int? ThreadId", rescheduleInputHandler, StringComparison.Ordinal); + Assert.Contains("s.thread_id AS ThreadId", rescheduleInputHandler, StringComparison.Ordinal); + Assert.Contains("messageThreadId: proposal.ThreadId", rescheduleInputHandler, StringComparison.Ordinal); + + Assert.Contains("int? ThreadId", rescheduleDeadlineService, StringComparison.Ordinal); + Assert.Contains("s.thread_id AS ThreadId", rescheduleDeadlineService, StringComparison.Ordinal); + Assert.Contains("messageThreadId: proposal.ThreadId", rescheduleDeadlineService, StringComparison.Ordinal); + } + + private static async Task ReadRepositoryFileAsync(string relativePath) + { + var directory = new DirectoryInfo(AppContext.BaseDirectory); + while (directory is not null) + { + var candidate = Path.Combine(directory.FullName, relativePath); + if (File.Exists(candidate)) + { + return await File.ReadAllTextAsync(candidate); + } + + directory = directory.Parent; + } + + throw new FileNotFoundException($"Could not locate repository file '{relativePath}'."); + } +} diff --git a/tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicRoutingTests.cs b/tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicRoutingTests.cs new file mode 100644 index 0000000..7949a70 --- /dev/null +++ b/tests/GmRelay.Bot.Tests/Infrastructure/Telegram/TelegramTopicRoutingTests.cs @@ -0,0 +1,80 @@ +using GmRelay.Bot.Infrastructure.Telegram; + +namespace GmRelay.Bot.Tests.Infrastructure.Telegram; + +public sealed class TelegramTopicRoutingTests +{ + [Fact] + public void ResolveNewScheduleDestination_UsesIncomingTopic_WhenForumCommandWasSentInsideTopic() + { + var destination = TelegramTopicRouting.ResolveNewScheduleDestination( + chatIsForum: true, + incomingMessageThreadId: 42); + + Assert.Equal(42, destination.MessageThreadId); + Assert.False(destination.ShouldCreateForumTopic); + Assert.False(destination.TopicCreatedByBot); + } + + [Fact] + public void ResolveNewScheduleDestination_CreatesBotOwnedTopic_WhenForumCommandWasSentInRoot() + { + var destination = TelegramTopicRouting.ResolveNewScheduleDestination( + chatIsForum: true, + incomingMessageThreadId: null); + + Assert.Null(destination.MessageThreadId); + Assert.True(destination.ShouldCreateForumTopic); + Assert.True(destination.TopicCreatedByBot); + } + + [Fact] + public void ResolveNewScheduleDestination_UsesPlainChat_WhenChatIsNotForum() + { + var destination = TelegramTopicRouting.ResolveNewScheduleDestination( + chatIsForum: false, + incomingMessageThreadId: 42); + + Assert.Null(destination.MessageThreadId); + Assert.False(destination.ShouldCreateForumTopic); + Assert.False(destination.TopicCreatedByBot); + } + + [Fact] + public void MissingForumTopicRightsMessage_NamesRequiredAdminRight() + { + Assert.Contains("admin", TelegramTopicRouting.MissingForumTopicRightsMessage, StringComparison.OrdinalIgnoreCase); + Assert.Contains("Manage Topics", TelegramTopicRouting.MissingForumTopicRightsMessage, StringComparison.Ordinal); + } + + [Theory] + [InlineData("Bad Request: not enough rights to create forum topic")] + [InlineData("Bad Request: CHAT_ADMIN_REQUIRED")] + [InlineData("Forbidden: bot is not an administrator")] + public void IsMissingForumTopicRightsError_MatchesAdminPermissionErrors(string apiError) + { + Assert.True(TelegramTopicRouting.IsMissingForumTopicRightsError(apiError)); + } + + [Fact] + public void IsMissingForumTopicRightsError_IgnoresUnrelatedApiErrors() + { + Assert.False(TelegramTopicRouting.IsMissingForumTopicRightsError("Bad Request: topic name is invalid")); + } + + [Theory] + [InlineData(true, 0, true)] + [InlineData(true, 1, false)] + [InlineData(false, 0, false)] + public void ShouldDeleteForumTopic_DeletesOnlyBotOwnedEmptyTopic( + bool topicCreatedByBot, + int remainingSessionsInTopic, + bool expected) + { + var shouldDelete = TelegramTopicRouting.ShouldDeleteForumTopic( + topicCreatedByBot, + remainingSessionsInTopic); + + Assert.Equal(expected, shouldDelete); + } +} From 105a051c2f0814acefb0a064e30e9bcf369cdad8 Mon Sep 17 00:00:00 2001 From: Toutsu Date: Tue, 12 May 2026 12:20:42 +0300 Subject: [PATCH 3/4] ci: install latest trivy and verify scan inputs 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. --- .gitea/workflows/pr-checks.yml | 24 +- Directory.Build.props | 1 + src/GmRelay.AppHost/packages.lock.json | 681 ++++++++++++++++ src/GmRelay.Bot/packages.lock.json | 683 ++++++++++++++++ .../packages.lock.json | 175 ++++ src/GmRelay.Shared/packages.lock.json | 6 + src/GmRelay.Web/packages.lock.json | 244 ++++++ tests/GmRelay.Bot.Tests/packages.lock.json | 765 ++++++++++++++++++ 8 files changed, 2576 insertions(+), 3 deletions(-) create mode 100644 src/GmRelay.AppHost/packages.lock.json create mode 100644 src/GmRelay.Bot/packages.lock.json create mode 100644 src/GmRelay.ServiceDefaults/packages.lock.json create mode 100644 src/GmRelay.Shared/packages.lock.json create mode 100644 src/GmRelay.Web/packages.lock.json create mode 100644 tests/GmRelay.Bot.Tests/packages.lock.json diff --git a/.gitea/workflows/pr-checks.yml b/.gitea/workflows/pr-checks.yml index 2f82d1b..073c238 100644 --- a/.gitea/workflows/pr-checks.yml +++ b/.gitea/workflows/pr-checks.yml @@ -20,6 +20,15 @@ jobs: - name: Restore dependencies run: dotnet restore + - name: Verify Trivy dependency scan inputs + run: | + lock_count="$(find . -name packages.lock.json -not -path "*/bin/*" -not -path "*/obj/*" | tee trivy-targets.txt | wc -l)" + echo "Trivy NuGet lock files: ${lock_count}" + if [ "${lock_count}" -eq 0 ]; then + echo "::error::No packages.lock.json files found. Trivy would scan 0 NuGet dependency files." + exit 1 + fi + # ── Linting ── - name: Lint C# code style @@ -38,10 +47,19 @@ jobs: - name: Install Trivy run: | - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.60.0 + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + trivy --version - name: Trivy filesystem security scan - run: trivy fs --exit-code 1 --severity HIGH,CRITICAL . + run: | + set +e + trivy fs --scanners vuln,misconfig,secret --exit-code 1 --severity HIGH,CRITICAL . 2>&1 | tee trivy-scan.log + trivy_exit="${PIPESTATUS[0]}" + if ! grep -Eq "Number of language-specific files[[:space:]]+num=[1-9][0-9]*" trivy-scan.log; then + echo "::error::Trivy did not detect any language-specific dependency files." + exit 1 + fi + exit "${trivy_exit}" # ── Build ── @@ -57,4 +75,4 @@ jobs: # ── Tests ── - name: Run tests - run: dotnet test tests/GmRelay.Bot.Tests/GmRelay.Bot.Tests.csproj --verbosity normal \ No newline at end of file + run: dotnet test tests/GmRelay.Bot.Tests/GmRelay.Bot.Tests.csproj --verbosity normal diff --git a/Directory.Build.props b/Directory.Build.props index 385424b..c0556fb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,5 +6,6 @@ enable enable true + true diff --git a/src/GmRelay.AppHost/packages.lock.json b/src/GmRelay.AppHost/packages.lock.json new file mode 100644 index 0000000..8e0fb8f --- /dev/null +++ b/src/GmRelay.AppHost/packages.lock.json @@ -0,0 +1,681 @@ +{ + "version": 1, + "dependencies": { + "net10.0": { + "Aspire.Dashboard.Sdk.win-x64": { + "type": "Direct", + "requested": "[13.2.1, )", + "resolved": "13.2.1", + "contentHash": "KLB9rXwY8kg2taWwxsJFoK0cAuupSZurcv1zTyYMqLyNuwvYYjs65Yz3g/cgh22QlUfOT3tOh+Jzk5MdJhy5+w==" + }, + "Aspire.Hosting.AppHost": { + "type": "Direct", + "requested": "[13.2.1, )", + "resolved": "13.2.1", + "contentHash": "4B/eoZPwOobxpMpvYnqe/EcXabjPhZJhfxlHXv5gdKd16duoWbHnvvAZJsVI3WUpakCwmsCiTrT4sNGfW8H+IQ==", + "dependencies": { + "AspNetCore.HealthChecks.Uris": "9.0.0", + "Aspire.Hosting": "13.2.1", + "Google.Protobuf": "3.33.5", + "Grpc.AspNetCore": "2.76.0", + "Grpc.Net.ClientFactory": "2.76.0", + "Grpc.Tools": "2.78.0", + "Humanizer.Core": "2.14.1", + "JsonPatch.Net": "3.3.0", + "KubernetesClient": "18.0.13", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.HealthChecks": "10.0.5", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.5", + "Microsoft.Extensions.Hosting": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Http": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5", + "ModelContextProtocol": "1.0.0", + "Newtonsoft.Json": "13.0.4", + "Polly.Core": "8.6.5", + "Semver": "3.0.0", + "StreamJsonRpc": "2.22.23", + "System.IO.Hashing": "10.0.3" + } + }, + "Aspire.Hosting.Orchestration.win-x64": { + "type": "Direct", + "requested": "[13.2.1, )", + "resolved": "13.2.1", + "contentHash": "39lRUH4WuCsBaYB7fZH1/r81SSJIXrA8WphBlAdP1QT95+1sKQHzXJuXU4nzKpBLv4oZmjcWzvA+FDMGZbWmkw==" + }, + "Aspire.Hosting.PostgreSQL": { + "type": "Direct", + "requested": "[13.2.1, )", + "resolved": "13.2.1", + "contentHash": "7F/nmeplR9cYE/B/E1haRjnkoBRQ/voMXpnK/SNJoXSFs4Vb/g00CDDvI/xfH3SAV7Xq8ekWa9ZbX56JuQ+YiA==", + "dependencies": { + "AspNetCore.HealthChecks.NpgSql": "9.0.0", + "AspNetCore.HealthChecks.Uris": "9.0.0", + "Aspire.Hosting": "13.2.1", + "Google.Protobuf": "3.33.5", + "Grpc.AspNetCore": "2.76.0", + "Grpc.Net.ClientFactory": "2.76.0", + "Grpc.Tools": "2.78.0", + "Humanizer.Core": "2.14.1", + "JsonPatch.Net": "3.3.0", + "KubernetesClient": "18.0.13", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.HealthChecks": "8.0.25", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.5", + "Microsoft.Extensions.Hosting": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Http": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5", + "ModelContextProtocol": "1.0.0", + "Newtonsoft.Json": "13.0.4", + "Polly.Core": "8.6.5", + "Semver": "3.0.0", + "StreamJsonRpc": "2.22.23", + "System.IO.Hashing": "10.0.3" + } + }, + "Aspire.Hosting": { + "type": "Transitive", + "resolved": "13.2.1", + "contentHash": "GY/T5iK2F4K3Sk60VUeVnTX1MhCjSaX48+qPUjA/rI1x1ONHevHzFj+Gc3fNlGEaZGY8L87hSxwGrV+Bjd5EJw==", + "dependencies": { + "AspNetCore.HealthChecks.Uris": "9.0.0", + "Google.Protobuf": "3.33.5", + "Grpc.AspNetCore": "2.76.0", + "Grpc.Net.ClientFactory": "2.76.0", + "Grpc.Tools": "2.78.0", + "Humanizer.Core": "2.14.1", + "JsonPatch.Net": "3.3.0", + "KubernetesClient": "18.0.13", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.HealthChecks": "8.0.25", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.5", + "Microsoft.Extensions.Hosting": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Http": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5", + "ModelContextProtocol": "1.0.0", + "Newtonsoft.Json": "13.0.4", + "Polly.Core": "8.6.5", + "Semver": "3.0.0", + "StreamJsonRpc": "2.22.23", + "System.IO.Hashing": "10.0.3" + } + }, + "AspNetCore.HealthChecks.NpgSql": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "npc58/AD5zuVxERdhCl2Kb7WnL37mwX42SJcXIwvmEig0/dugOLg3SIwtfvvh3TnvTwR/sk5LYNkkPaBdks61A==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "8.0.11", + "Npgsql": "8.0.3" + } + }, + "AspNetCore.HealthChecks.Uris": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "XYdNlA437KeF8p9qOpZFyNqAN+c0FXt/JjTvzH/Qans0q0O3pPE8KPnn39ucQQjR/Roum1vLTP3kXiUs8VHyuA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "8.0.11", + "Microsoft.Extensions.Http": "8.0.0" + } + }, + "Fractions": { + "type": "Transitive", + "resolved": "7.3.0", + "contentHash": "2bETFWLBc8b7Ut2SVi+bxhGVwiSpknHYGBh2PADyGWONLkTxT7bKyDRhF8ao+XUv90tq8Fl7GTPxSI5bacIRJw==" + }, + "Google.Protobuf": { + "type": "Transitive", + "resolved": "3.33.5", + "contentHash": "XEzLpCTosZb5I6eGSPn7rAES0VfkJkn3Cqydh0W39POdZwkdhPhOmAROTFJF9g0ardst4ulNXRm/q/iXwNu+Qw==" + }, + "Grpc.AspNetCore": { + "type": "Transitive", + "resolved": "2.76.0", + "contentHash": "LyXMmpN2Ba0TE35SOLSKbGqIYtJuhc1UgiaGfoW1X8KJERV70QI5KGW+ckEY7MrXoFWN/uWo4B70siVhbDmCgQ==", + "dependencies": { + "Google.Protobuf": "3.31.1", + "Grpc.AspNetCore.Server.ClientFactory": "2.76.0", + "Grpc.Tools": "2.76.0" + } + }, + "Grpc.AspNetCore.Server": { + "type": "Transitive", + "resolved": "2.76.0", + "contentHash": "diSC/ZeNdSdxHdYSOpYwuSBBDYpuNVtJQFJfiBB0WrYOQ4lVMmdxuUZJcViahQyo8pCvS3Mueo5lqFxwwMF/iw==", + "dependencies": { + "Grpc.Net.Common": "2.76.0" + } + }, + "Grpc.AspNetCore.Server.ClientFactory": { + "type": "Transitive", + "resolved": "2.76.0", + "contentHash": "y5KGO1GO0N2L/hCCMR05mmoK8j+v8rKvZ+9nothAxKx2Tf2CwV8f4TM5K0GkKfDsp4vrc4lm90MU6E+DeN7YIw==", + "dependencies": { + "Grpc.AspNetCore.Server": "2.76.0", + "Grpc.Net.ClientFactory": "2.76.0" + } + }, + "Grpc.Core.Api": { + "type": "Transitive", + "resolved": "2.76.0", + "contentHash": "cSxC2tdnFdXXuBgIn1pjc4YBx7LXTCp4M0qn+SMBS35VWZY+cEQYLWTBDDhdBH1HzU7BV+ncVZlniGQHMpRJKQ==" + }, + "Grpc.Net.Client": { + "type": "Transitive", + "resolved": "2.76.0", + "contentHash": "K1oldmqw2+Gn69nGRzZLhqSiUZwelX1GrBu/cUl9wNf1C0uB61vFS6JcxUUv9P8VoUJhFsmV44JA6lI2EUt4xw==", + "dependencies": { + "Grpc.Net.Common": "2.76.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + } + }, + "Grpc.Net.ClientFactory": { + "type": "Transitive", + "resolved": "2.76.0", + "contentHash": "XI+kO69L9AV8B9N0UQOmH911r6MOEp9huHiavEsY56DJYuzJ9KAxNGy37dpV6CLbgCaN2uKmpOsZ9Pao6bmpVQ==", + "dependencies": { + "Grpc.Net.Client": "2.76.0", + "Microsoft.Extensions.Http": "8.0.0" + } + }, + "Grpc.Net.Common": { + "type": "Transitive", + "resolved": "2.76.0", + "contentHash": "bZpiMVYgvpB44/wBh1RotrkqC7bg2FOasLri2GhR3hMKyzsiTxCoDE49YjPrJeFc4RW0wS8u+EInI09sjxVFRA==", + "dependencies": { + "Grpc.Core.Api": "2.76.0" + } + }, + "Grpc.Tools": { + "type": "Transitive", + "resolved": "2.78.0", + "contentHash": "6jPG2gHon+w2PczW8jjrCRnW/g9eEfCdd7aK6mDooptWtuPsV3ZxAwKKEx7LGEDVoT4c2SViRl8Yu3L1XiWIIg==" + }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.14.1", + "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw==" + }, + "Json.More.Net": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "qtwsyAsL55y2vB2/sK4Pjg3ZyVzD5KKSpV3lOAMHlnjFfsjQ/86eHJfQT9aV1YysVXzF4+xyHOZbh7Iu3YQ7Lg==" + }, + "JsonPatch.Net": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "GIcMMDtzfzVfIpQgey8w7dhzcw6jG5nD4DDAdQCTmHfblkCvN7mI8K03to8YyUhKMl4PTR6D6nLSvWmyOGFNTg==", + "dependencies": { + "JsonPointer.Net": "5.2.0" + } + }, + "JsonPointer.Net": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "qe1F7Tr/p4mgwLPU9P60MbYkp+xnL2uCPnWXGgzfR/AZCunAZIC0RZ32dLGJJEhSuLEfm0YF/1R3u5C7mEVq+w==", + "dependencies": { + "Humanizer.Core": "2.14.1", + "Json.More.Net": "2.1.0" + } + }, + "KubernetesClient": { + "type": "Transitive", + "resolved": "18.0.13", + "contentHash": "X5IuxmydftB148XeULtc7rD5/RvqLuW5SzkIjFovPgJpvV4RAoRqNPruVB7GEFu1Xg+zHVIk88WqdV8JjbgHbA==", + "dependencies": { + "Fractions": "7.3.0", + "YamlDotNet": "16.3.0" + } + }, + "MessagePack": { + "type": "Transitive", + "resolved": "2.5.192", + "contentHash": "Jtle5MaFeIFkdXtxQeL9Tu2Y3HsAQGoSntOzrn6Br/jrl6c8QmG22GEioT5HBtZJR0zw0s46OnKU8ei2M3QifA==", + "dependencies": { + "MessagePack.Annotations": "2.5.192", + "Microsoft.NET.StringTools": "17.6.3" + } + }, + "MessagePack.Annotations": { + "type": "Transitive", + "resolved": "2.5.192", + "contentHash": "jaJuwcgovWIZ8Zysdyf3b7b34/BrADw4v82GaEZymUhDd3ScMPrYd/cttekeDteJJPXseJxp04yTIcxiVUjTWg==" + }, + "Microsoft.Extensions.AI.Abstractions": { + "type": "Transitive", + "resolved": "10.3.0", + "contentHash": "hDjDvUERvUH3HBMs2MDusOcGJBjAHOG5pJIU2x/HZEa4e1UthNKt89cwMi3B+ogJo6skki1XFjfgGN3ksnVqvQ==" + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "10.0.3", + "contentHash": "5dtXBvI8t3z8pF4tB38JYgi/enCL/DwSXxpqShgFz3SHJ7IzqFIMs6Gu5ik8sNZzcO9qQs3xIDpB3vDamkYG+Q==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.3" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "8Rx5sqg04FttxrumyG6bmoRuFRgYzK6IVwF1i0/o0cXfKBdDeVpJejKHtJCMjyg9E/DNMVqpqOGe/tCT5gYvVA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "P09QpTHjqHmCLQOTC+WyLkoRNxek4NIvfWt+TnU0etoDUSRxcltyd6+j/ouRbMdLR0j44GqGO+lhI2M4fAHG4g==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "99Z4rjyXopb1MIazDSPcvwYCUdYNO01Cf1GUs2WUjIFAbkGmwzj2vPa2k+3pheJRV+YgNd2QqRKHAri0oBAU4Q==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.CommandLine": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "or9fOLopMUTJOQVJ3bou4aD6PwvsiKf4kZC4EE5sRRKSkmh+wfk/LekJXRjAX88X+1JA9zHjDo+5fiQ7z3MY/A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "tchMGQ+zVTO40np/Zzg2Li/TIR8bksQgg4UVXZa0OzeFCKWnIYtxE2FVs+eSmjPGCjMS2voZbwN/mUcYfpSTuA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "OhTr0O79dP49734lLTqVveivVX9sDXxbI/8vjELAZTHXqoN90mdpgTAgwicJED42iaHMCcZcK6Bj+8wNyBikaw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "brBM/WP0YAUYh2+QqSYVdK8eQHYQTtTEUJXJ+84Zkdo2buGLja9VSrMIhgoeBUU7JBmcskAib8Lb/N83bvxgYQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "fhdG6UV9lIp70QhNkVyaHciUVq25IPFkczheVJL9bIFvmnJ+Zghaie6dWkDbbVmxZlHl9gj3zTDxMxJs5zNhIA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Json": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "v1SVsowG6YE1YnHVGmLWz57YTRCQRx9pH5ebIESXfm5isI9gA3QaMyg/oMTzPpXYZwSAVDzYItGJKfmV+pqXkQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "iVMtq9eRvzyhx8949EGT0OCYJfXi737SbRVzWXE5GrOgGj5AaZ9eUuxA/BSUfmOMALKn/g8KfFaNQw0eiB3lyA==" + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "vAJHd4yOpmKoK+jBuYV7a3y+Ab9U4ARCc29b6qvMy276RgJFw9LFs0DdsPqOL3ahwzyrX7tM+i4cCxU/RX0qAg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/nYGrpa9/0BZofrVpBbbj+Ns8ZesiPE0V/KxsuHgDgHQopIzN54nRaQGSuvPw16/kI9sW1Zox5yyAPqvf0Jz6A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "REdt95QXHscGdtw/UUgyCW2lF9DJcAOJxmebKW2IkgUjuCAdMODIi2HNOWg5utW98nm8ekgV0Gjqs/sljwwqMw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "NrIMTy7dpqxAvA6kHAYH8cXID/YgeNOy0OqFKpLtkPu5X4WS/basX91UszANzVrMNRAICJ2GOnGiRxJtsRyEQw==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "nCBmCx0Xemlu65ZiWMcXbvfvtznKxf4/YYKF9R28QkqdI9lTikedGqzJ28/xmdGGsxUnsP5/3TQGpiPwVjK0dA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "dMu5kUPSfol1Rqhmr6nWPSmbFjDe9w6bkoKithG17bWTZA0UyKirTatM5mqYUN3mGpNA0MorlusIoVTh6J7o5g==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "mOE3ARusNQR0a5x8YOcnUbfyyXGqoAWQtEc7qFOfNJgruDWQLo39Re+3/Lzj5pLPFuFYj8hN4dgKzaSQDKiOCw==" + }, + "Microsoft.Extensions.Hosting": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "8i7e5IBdiKLNqt/+ciWrS8U95Rv5DClaaj7ulkZbimnCi4uREWd+lXzkp3joofFuIPOlAzV4AckxLTIELv2jdg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.Configuration.CommandLine": "10.0.5", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.5", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.5", + "Microsoft.Extensions.Configuration.Json": "10.0.5", + "Microsoft.Extensions.Configuration.UserSecrets": "10.0.5", + "Microsoft.Extensions.DependencyInjection": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Configuration": "10.0.5", + "Microsoft.Extensions.Logging.Console": "10.0.5", + "Microsoft.Extensions.Logging.Debug": "10.0.5", + "Microsoft.Extensions.Logging.EventLog": "10.0.5", + "Microsoft.Extensions.Logging.EventSource": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "+Wb7KAMVZTomwJkQrjuPTe5KBzGod7N8XeG+ScxRlkPOB4sZLG4ccVwjV4Phk5BCJt7uIMnGHVoN6ZMVploX+g==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "AiFvHYM8nP0wPC7bGPI3NHQlSYSLqjjT7DMJUuuxhd+7pz3O89iu2gdQfgACy5DxsXENiok5i1bMacJL7KR8jA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "+XTMKQyDWg4ODoNHU/BN3BaI1jhGO7VCS+BnzT/4IauiG6y2iPAte7MyD7rHKS+hNP0TkFkjrae8DFjDUxtcxg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "9HOdqlDtPptVcmKAjsQ/Nr5Rxfq6FMYLdhvZh1lVmeKR738qeYecQD7+ldooXf+u2KzzR1kafSphWngIM3C6ug==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Configuration": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "cSgxsDgfP0+gmVRPVoNHI/KIDavIZxh+CxE6tSLPlYTogqccDnjBFI9CgEsiNuMP6+fiuXUwhhlTz36uUEpwbQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Console": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "PMs2gha2v24hvH5o5KQem5aNK4mN0BhhCWlMqsg9tzifWKzjeQi2tyPOP/RaWMVvalOhVLcrmoMYPqbnia/epg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Configuration": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Debug": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/VacEkBQ02A8PBXSa6YpbIXCuisYy6JJr62/+ANJDZE+RMBfZMcXJXLfr/LpyLE6pgdp17Wxlt7e7R9zvkwZ3Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.EventLog": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "0ezhWYJS4/6KrqQel9JL+Tr4n+4EX2TF5EYiaysBWNNEM2c3Gtj1moD39esfgk8OHblSX+UFjtZ3z0c4i9tRvw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "System.Diagnostics.EventLog": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.EventSource": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "vN+aq1hBFXyYvY5Ow9WyeR66drKQxRZmas4lAjh6QWfryPkjTn1uLtX5AFIxyDaZj78v5TG2sELUyvrXpAPQQw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "MDaQMdUplw0AIRhWWmbLA7yQEXaLIHb+9CTroTiNS8OlI0LMXS4LCxtopqauiqGCWlRgJ+xyraVD8t6veRAFbw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "BB9uUW3+6Rxu1R97OB1H/13lUF8P2+H1+eDhpZlK30kDh/6E4EKHBUqTp+ilXQmZLzsRErxON8aBSR6WpUKJdg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/HUHJ0tw/LQvD0DZrz50eQy/3z7PfX7WWEaXnjKTV9/TNdcgFlNTZGo49QhS7PTmhDqMyHRMqAXSBxLh0vso4g==" + }, + "Microsoft.NET.StringTools": { + "type": "Transitive", + "resolved": "17.6.3", + "contentHash": "N0ZIanl1QCgvUumEL1laasU0a7sOE5ZwLZVTn0pAePnfhq8P7SvTjF8Axq+CnavuQkmdQpGNXQ1efZtu5kDFbA==" + }, + "Microsoft.VisualStudio.Threading.Only": { + "type": "Transitive", + "resolved": "17.13.61", + "contentHash": "vl5a2URJYCO5m+aZZtNlAXAMz28e2pUotRuoHD7RnCWOCeoyd8hWp5ZBaLNYq4iEj2oeJx5ZxiSboAjVmB20Qg==", + "dependencies": { + "Microsoft.VisualStudio.Validation": "17.8.8" + } + }, + "Microsoft.VisualStudio.Validation": { + "type": "Transitive", + "resolved": "17.8.8", + "contentHash": "rWXThIpyQd4YIXghNkiv2+VLvzS+MCMKVRDR0GAMlflsdo+YcAN2g2r5U1Ah98OFjQMRexTFtXQQ2LkajxZi3g==" + }, + "ModelContextProtocol": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "W7UX8AQ1qMjXyCDcpP25u/L1W2vIIgfhLX/B2ZtTU1VUyILXdmVbdRjkQesKVPT/wPMpYXIHUcZJTPdsGfKSfQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "10.0.3", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.3", + "ModelContextProtocol.Core": "1.0.0" + } + }, + "ModelContextProtocol.Core": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "QKboiQEq2MJMGeQ029Gy6xqge88abm0Px9lnG7hueOyf+EDCxi5SUATV+Df7GwT+NwWzkEsYG271bUQD+LGhEg==", + "dependencies": { + "Microsoft.Extensions.AI.Abstractions": "10.3.0", + "Microsoft.Extensions.Logging.Abstractions": "10.0.3" + } + }, + "Nerdbank.Streams": { + "type": "Transitive", + "resolved": "2.12.87", + "contentHash": "oDKOeKZ865I5X8qmU3IXMyrAnssYEiYWTobPGdrqubN3RtTzEHIv+D6fwhdcfrdhPJzHjCkK/ORztR/IsnmA6g==", + "dependencies": { + "Microsoft.VisualStudio.Threading.Only": "17.13.61", + "Microsoft.VisualStudio.Validation": "17.8.8" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.4", + "contentHash": "pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "8.0.3", + "contentHash": "6WEmzsQJCZAlUG1pThKg/RmeF6V+I0DmBBBE/8YzpRtEzhyZzKcK7ulMANDm5CkxrALBEC8H+5plxHWtIL7xnA==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + } + }, + "Polly.Core": { + "type": "Transitive", + "resolved": "8.6.5", + "contentHash": "t+sUVrIwvo7UmsgHGgOG9F0GDZSRIm47u2ylH17Gvcv1q5hNEwgD5GoBlFyc0kh/pebmPyrAgvGsR/65ZBaXlg==" + }, + "Semver": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "9jZCicsVgTebqkAujRWtC9J1A5EQVlu0TVKHcgoCuv345ve5DYf4D1MjhKEnQjdRZo6x/vdv6QQrYFs7ilGzLA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "5.0.1" + } + }, + "StreamJsonRpc": { + "type": "Transitive", + "resolved": "2.22.23", + "contentHash": "Ahq6uUFPnU9alny5h4agyX74th3PRq3NQCRNaDOqWcx20WT06mH/wENSk5IbHDc8BmfreQVEIBx5IXLBbsLFIA==", + "dependencies": { + "MessagePack": "2.5.192", + "Microsoft.VisualStudio.Threading.Only": "17.13.61", + "Microsoft.VisualStudio.Validation": "17.8.8", + "Nerdbank.Streams": "2.12.87", + "Newtonsoft.Json": "13.0.3" + } + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "wugvy+pBVzjQEnRs9wMTWwoaeNFX3hsaHeVHFDIvJSWXp7wfmNWu3mxAwBIE6pyW+g6+rHa1Of5fTzb0QVqUTA==" + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "10.0.3", + "contentHash": "La6ICwsdTKhVX+LKN+pvFjQRR3LhLwq3uKdi2knjLzRyPYBSydF4cjXidYxIiTcDD6XVYdsBWQEI8ZxiZ/OdIg==" + }, + "YamlDotNet": { + "type": "Transitive", + "resolved": "16.3.0", + "contentHash": "SgMOdxbz8X65z8hraIs6hOEdnkH6hESTAIUa7viEngHOYaH+6q5XJmwr1+yb9vJpNQ19hCQY69xbFsLtXpobQA==" + } + } + } +} \ No newline at end of file diff --git a/src/GmRelay.Bot/packages.lock.json b/src/GmRelay.Bot/packages.lock.json new file mode 100644 index 0000000..3f68185 --- /dev/null +++ b/src/GmRelay.Bot/packages.lock.json @@ -0,0 +1,683 @@ +{ + "version": 1, + "dependencies": { + "net10.0": { + "Aspire.Npgsql": { + "type": "Direct", + "requested": "[13.2.2, )", + "resolved": "13.2.2", + "contentHash": "nEYgziWN7hksgEQEWy24JypcMCU8gKYcIIyPL05JfdXxUWuPRLotH/KOeuHevAjSEOYkL3dtGakBkJAuPobGmA==", + "dependencies": { + "AspNetCore.HealthChecks.NpgSql": "9.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.HealthChecks": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5", + "Npgsql.DependencyInjection": "10.0.1", + "Npgsql.OpenTelemetry": "10.0.1", + "OpenTelemetry.Extensions.Hosting": "1.15.0" + } + }, + "Dapper": { + "type": "Direct", + "requested": "[2.1.72, )", + "resolved": "2.1.72", + "contentHash": "ns4mGqQd9a/MhP8m6w556vVlZIa0/MfUu03zrxjZC/jlr1uVCsUac8bkdB+Fs98Llbd56rRSo1eZH5VVmeGZyw==" + }, + "Dapper.AOT": { + "type": "Direct", + "requested": "[1.0.48, )", + "resolved": "1.0.48", + "contentHash": "rsLM3yKr4g+YKKox9lhc8D+kz67P7Q9+xdyn1LmCsoYr1kYpJSm+Nt6slo5UrfUrcTiGJ57zUlyO8XUdV7G7iA==" + }, + "dbup-postgresql": { + "type": "Direct", + "requested": "[7.0.1, )", + "resolved": "7.0.1", + "contentHash": "mRnmENWWPuuMZ538gOd1mZnzucx6FQk0anmw3EABjGfcbp24FDb9QdGepYrDiaM8K9s5/gd49+5cmBOlniH/lg==", + "dependencies": { + "Npgsql": "10.0.1", + "dbup-core": "6.1.1" + } + }, + "Microsoft.DotNet.ILCompiler": { + "type": "Direct", + "requested": "[10.0.5, )", + "resolved": "10.0.5", + "contentHash": "yadTZIkStCVsG8nGwvfroSfBApPsgjQbodQyaIfp53dgayE0qhZpywixiCB6lx57JYQ+KVg1m1AFLrj54pxpZg==" + }, + "Microsoft.Extensions.Hosting": { + "type": "Direct", + "requested": "[10.0.5, )", + "resolved": "10.0.5", + "contentHash": "8i7e5IBdiKLNqt/+ciWrS8U95Rv5DClaaj7ulkZbimnCi4uREWd+lXzkp3joofFuIPOlAzV4AckxLTIELv2jdg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.Configuration.CommandLine": "10.0.5", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.5", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.5", + "Microsoft.Extensions.Configuration.Json": "10.0.5", + "Microsoft.Extensions.Configuration.UserSecrets": "10.0.5", + "Microsoft.Extensions.DependencyInjection": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Configuration": "10.0.5", + "Microsoft.Extensions.Logging.Console": "10.0.5", + "Microsoft.Extensions.Logging.Debug": "10.0.5", + "Microsoft.Extensions.Logging.EventLog": "10.0.5", + "Microsoft.Extensions.Logging.EventSource": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[10.0.5, )", + "resolved": "10.0.5", + "contentHash": "A+5ZuQ0f449tM+MQrhf6R9ZX7lYpjk/ODEwLYKrnF6111rtARx8fVsm4YznUnQiKnnXfaXNBqgxmil6RW3L3SA==" + }, + "Npgsql": { + "type": "Direct", + "requested": "[10.0.2, )", + "resolved": "10.0.2", + "contentHash": "q5RfBI+wywJSFUNDE1L4ZbHEHCFTblo8Uf6A6oe4feOUFYiUQXyAf9GBh5qEZpvJaHiEbpBPkQumjEhXCJxdrg==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "10.0.0" + } + }, + "Telegram.Bot": { + "type": "Direct", + "requested": "[22.9.5.3, )", + "resolved": "22.9.5.3", + "contentHash": "7u8rZU9Vx9XEyIm6pB+dAlITsi1v63I+hKo7IEXGiQZnVjzvZgPs9yDCP17/Cwm7lgjCNEqknlbv/yoBnsUYFw==", + "dependencies": { + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "AspNetCore.HealthChecks.NpgSql": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "npc58/AD5zuVxERdhCl2Kb7WnL37mwX42SJcXIwvmEig0/dugOLg3SIwtfvvh3TnvTwR/sk5LYNkkPaBdks61A==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "8.0.11", + "Npgsql": "8.0.3" + } + }, + "dbup-core": { + "type": "Transitive", + "resolved": "6.1.1", + "contentHash": "kgpuyJVEFJHoIj/slnc994Go88aoeZqNDfGHDBr4sh7CsEWwJhOTCt/FJqO4ziUImL5L0NEY0kxxOiNgPKI2Fw==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.AmbientMetadata.Application": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "CNrEjaOCZ8d1HtB0mvpiX4EWxLkee2xy+CsYXxmsEYJSFgw3OmF9pIhP/tCTeYBHhpsKJj5wM63G8IBFGxAcsw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.2", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.2", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.2" + } + }, + "Microsoft.Extensions.Compliance.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "1a4xDAT6fRyP8t419q3WvWMmMslDTvI7OAZLWBhn5rysFG0bl5xFenTswd1xAbT/3u3mx4Xyb5bPx+V+18tJeQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.ObjectPool": "10.0.2" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "8Rx5sqg04FttxrumyG6bmoRuFRgYzK6IVwF1i0/o0cXfKBdDeVpJejKHtJCMjyg9E/DNMVqpqOGe/tCT5gYvVA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "P09QpTHjqHmCLQOTC+WyLkoRNxek4NIvfWt+TnU0etoDUSRxcltyd6+j/ouRbMdLR0j44GqGO+lhI2M4fAHG4g==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "99Z4rjyXopb1MIazDSPcvwYCUdYNO01Cf1GUs2WUjIFAbkGmwzj2vPa2k+3pheJRV+YgNd2QqRKHAri0oBAU4Q==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.CommandLine": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "or9fOLopMUTJOQVJ3bou4aD6PwvsiKf4kZC4EE5sRRKSkmh+wfk/LekJXRjAX88X+1JA9zHjDo+5fiQ7z3MY/A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "tchMGQ+zVTO40np/Zzg2Li/TIR8bksQgg4UVXZa0OzeFCKWnIYtxE2FVs+eSmjPGCjMS2voZbwN/mUcYfpSTuA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "OhTr0O79dP49734lLTqVveivVX9sDXxbI/8vjELAZTHXqoN90mdpgTAgwicJED42iaHMCcZcK6Bj+8wNyBikaw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "brBM/WP0YAUYh2+QqSYVdK8eQHYQTtTEUJXJ+84Zkdo2buGLja9VSrMIhgoeBUU7JBmcskAib8Lb/N83bvxgYQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "fhdG6UV9lIp70QhNkVyaHciUVq25IPFkczheVJL9bIFvmnJ+Zghaie6dWkDbbVmxZlHl9gj3zTDxMxJs5zNhIA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Json": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "v1SVsowG6YE1YnHVGmLWz57YTRCQRx9pH5ebIESXfm5isI9gA3QaMyg/oMTzPpXYZwSAVDzYItGJKfmV+pqXkQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "iVMtq9eRvzyhx8949EGT0OCYJfXi737SbRVzWXE5GrOgGj5AaZ9eUuxA/BSUfmOMALKn/g8KfFaNQw0eiB3lyA==" + }, + "Microsoft.Extensions.DependencyInjection.AutoActivation": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "Z/OI261l7LnxyODKPx0trQyIHFyicCR/akfn64lGOjPcf4FpAZ7ePAGl2HPvQBUBSNfPTF0gWeCfuFmyftMgYA==", + "dependencies": { + "Microsoft.Extensions.Hosting.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "vAJHd4yOpmKoK+jBuYV7a3y+Ab9U4ARCc29b6qvMy276RgJFw9LFs0DdsPqOL3ahwzyrX7tM+i4cCxU/RX0qAg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/nYGrpa9/0BZofrVpBbbj+Ns8ZesiPE0V/KxsuHgDgHQopIzN54nRaQGSuvPw16/kI9sW1Zox5yyAPqvf0Jz6A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "3qMK1D40D10kb5TdBtFJpzz6/WH0NinWs68ZZS8jCFgHMXDiOjGiPOneMmIocCP/wnUUW4Hzf8lMsIE1xIGxDA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "REdt95QXHscGdtw/UUgyCW2lF9DJcAOJxmebKW2IkgUjuCAdMODIi2HNOWg5utW98nm8ekgV0Gjqs/sljwwqMw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "NrIMTy7dpqxAvA6kHAYH8cXID/YgeNOy0OqFKpLtkPu5X4WS/basX91UszANzVrMNRAICJ2GOnGiRxJtsRyEQw==" + }, + "Microsoft.Extensions.Features": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "X7tm2aV2w3lN9roSSGhl19lz4w76HvdiuKNhIv2XOiorYII9XCm66o/z9IJ0+QwkgvEv5gMZDM6rV6uwABHEQQ==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "nCBmCx0Xemlu65ZiWMcXbvfvtznKxf4/YYKF9R28QkqdI9lTikedGqzJ28/xmdGGsxUnsP5/3TQGpiPwVjK0dA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "dMu5kUPSfol1Rqhmr6nWPSmbFjDe9w6bkoKithG17bWTZA0UyKirTatM5mqYUN3mGpNA0MorlusIoVTh6J7o5g==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "mOE3ARusNQR0a5x8YOcnUbfyyXGqoAWQtEc7qFOfNJgruDWQLo39Re+3/Lzj5pLPFuFYj8hN4dgKzaSQDKiOCw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "+Wb7KAMVZTomwJkQrjuPTe5KBzGod7N8XeG+ScxRlkPOB4sZLG4ccVwjV4Phk5BCJt7uIMnGHVoN6ZMVploX+g==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "egUPC0xydb1ugCMcRyJ6zaOGOzx7N4coOVlGeLcIsXhUf1xHHwZeX+ob7JuG0dXExFduHYE/t+4/4y8BLlBKmw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Diagnostics": "10.0.2", + "Microsoft.Extensions.Logging": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2" + } + }, + "Microsoft.Extensions.Http.Diagnostics": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "I0FBgF6yZRwYH9E3KQ2vHm80YZ7YBj+52GDsmOWXPBv/p15b/wUoNupV9kw3LnSNVsWMqlGbiuZgBnHpMwPh+Q==", + "dependencies": { + "Microsoft.Extensions.Http": "10.0.2", + "Microsoft.Extensions.Telemetry": "10.2.0" + } + }, + "Microsoft.Extensions.Http.Resilience": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "Lg+OjBW+ODDbM4Ax4LoERvQ1dqSZ8I2gQc2+B0/WOWl2+PunLJ3xb3x8MtHGfcb/Mp98RoMpwRKm6Aj9mzXwrA==", + "dependencies": { + "Microsoft.Extensions.Http.Diagnostics": "10.2.0", + "Microsoft.Extensions.ObjectPool": "10.0.2", + "Microsoft.Extensions.Resilience": "10.2.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "+XTMKQyDWg4ODoNHU/BN3BaI1jhGO7VCS+BnzT/4IauiG6y2iPAte7MyD7rHKS+hNP0TkFkjrae8DFjDUxtcxg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "9HOdqlDtPptVcmKAjsQ/Nr5Rxfq6FMYLdhvZh1lVmeKR738qeYecQD7+ldooXf+u2KzzR1kafSphWngIM3C6ug==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Configuration": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "cSgxsDgfP0+gmVRPVoNHI/KIDavIZxh+CxE6tSLPlYTogqccDnjBFI9CgEsiNuMP6+fiuXUwhhlTz36uUEpwbQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Console": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "PMs2gha2v24hvH5o5KQem5aNK4mN0BhhCWlMqsg9tzifWKzjeQi2tyPOP/RaWMVvalOhVLcrmoMYPqbnia/epg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Configuration": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Debug": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/VacEkBQ02A8PBXSa6YpbIXCuisYy6JJr62/+ANJDZE+RMBfZMcXJXLfr/LpyLE6pgdp17Wxlt7e7R9zvkwZ3Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.EventLog": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "0ezhWYJS4/6KrqQel9JL+Tr4n+4EX2TF5EYiaysBWNNEM2c3Gtj1moD39esfgk8OHblSX+UFjtZ3z0c4i9tRvw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "System.Diagnostics.EventLog": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.EventSource": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "vN+aq1hBFXyYvY5Ow9WyeR66drKQxRZmas4lAjh6QWfryPkjTn1uLtX5AFIxyDaZj78v5TG2sELUyvrXpAPQQw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "kpCp4m7nwJVBcRKWXYHdVK/W0dkKyyFOjCmKVdO+zKThWvUxP1V+jVEP9FGpqRu4GPl9041SEXu2f+U/l825nQ==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "MDaQMdUplw0AIRhWWmbLA7yQEXaLIHb+9CTroTiNS8OlI0LMXS4LCxtopqauiqGCWlRgJ+xyraVD8t6veRAFbw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "BB9uUW3+6Rxu1R97OB1H/13lUF8P2+H1+eDhpZlK30kDh/6E4EKHBUqTp+ilXQmZLzsRErxON8aBSR6WpUKJdg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/HUHJ0tw/LQvD0DZrz50eQy/3z7PfX7WWEaXnjKTV9/TNdcgFlNTZGo49QhS7PTmhDqMyHRMqAXSBxLh0vso4g==" + }, + "Microsoft.Extensions.Resilience": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "v4WOdAOFxB3AcsUkZWNcHL3mYzs4KAPtHO8rkoQlFKOBoD3KyjjAL+h3tRwSK5i4UpF/yhxsQRY0JxKj4osxxw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics": "10.0.2", + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": "10.2.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.2", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0", + "Polly.Extensions": "8.4.2", + "Polly.RateLimiting": "8.4.2" + } + }, + "Microsoft.Extensions.ServiceDiscovery": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "AHTPfiKodj66xA8RwRkFD4q11V2AvzcuDsujv6ViPkOPtvBEYcPVplHakK56pPzWlX08MDS+TAQXfFXAeP7J5w==", + "dependencies": { + "Microsoft.Extensions.Http": "10.0.2", + "Microsoft.Extensions.ServiceDiscovery.Abstractions": "10.2.0" + } + }, + "Microsoft.Extensions.ServiceDiscovery.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "sANlOvfqfw/yfych4CLlHSKSWzIie6mQG7w83gVur1foNOafyHxcgpoQMvBf+KiB4Tpls6P1/Z77IIQSK8hxFg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.Configuration.Binder": "10.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Features": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2", + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Telemetry": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "ssW5gosYlewNH/ISTyaLD/XfJT4GSjwShOUKv61fpXrqVmHkhuIA/5bBAGStM1XbzJjt9IG2vzfdHTu4zlX9Ew==", + "dependencies": { + "Microsoft.Extensions.AmbientMetadata.Application": "10.2.0", + "Microsoft.Extensions.DependencyInjection.AutoActivation": "10.2.0", + "Microsoft.Extensions.Logging.Configuration": "10.0.2", + "Microsoft.Extensions.ObjectPool": "10.0.2", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0" + } + }, + "Microsoft.Extensions.Telemetry.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "6V4V6NX6RLUYWwV89DeW/4zK5xOycYHWhsfMXSpKVGgMHfXcczmbk6hBeqTnRPzhpATYcOWlmA6hk1jgdxUugA==", + "dependencies": { + "Microsoft.Extensions.Compliance.Abstractions": "10.2.0", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "Microsoft.Extensions.ObjectPool": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2" + } + }, + "Npgsql.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "YHFa4vD27sNIfv6s5q8Zi1fLvKfmK1xcpMv0PUvXOxDFbRmuMRSHwpZTbPvsAlj97q1/o7DfyynLqfqrCm1VnA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Npgsql": "10.0.1" + } + }, + "Npgsql.OpenTelemetry": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "G9fEIBaHggZXWfDSDnKLc0XwKcbuU6i2eXp7zDqpgYxbhCmIN9fRgaSOGyyMNHSo/yY1IB4G4CjW5VO/SKRR0g==", + "dependencies": { + "Npgsql": "10.0.1", + "OpenTelemetry.API": "1.14.0" + } + }, + "OpenTelemetry": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "N0i6WjPoHPbZyms1ugbDIFAJFuGlpeExJMU/+XSL0lQRUkg/D0utFkDoLXf8Z1km5B+xVZ2GyMXXiX8qdeNmPg==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0", + "Microsoft.Extensions.Logging.Configuration": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "1.15.3" + } + }, + "OpenTelemetry.Api": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "fX+fkCysfPut+qCcT3bKqyX4QN9Saf4CgX8HLOHywEVD+Xr7sULtfuypITpoDysjx8R59dn/3mWhgimMH8cm/g==" + }, + "OpenTelemetry.Api.ProviderBuilderExtensions": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "SYn0lqYDwLMWhv/zlNGsQcl2yX++yTumanX46bmOZE/ZDOd1WjPBO2kZaZgKLEZTZk48pavIFGJ6vOvxXgWVFQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0", + "OpenTelemetry.Api": "1.15.3" + } + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "FEXJepcseTGbATiCkUfP7ipoFEYYfl/0UmmUwi0KxCPg9PaUA8ab2P1LGopK+/HExasJ1ZutFhZrN6WvUIR23g==", + "dependencies": { + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Extensions.Hosting": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "u8n/W8yIlqv0BXZmvId1iVaeWXG42tGKdTkuLYg5g57Y/r9CeUNzqtrSHNdG5IoO8iPX79w3v+WsbAHgUQbfeg==", + "dependencies": { + "Microsoft.Extensions.Hosting.Abstractions": "10.0.0", + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Instrumentation.AspNetCore": { + "type": "Transitive", + "resolved": "1.15.2", + "contentHash": "2nPd7r0ug/gd6/CNFL6Rlu+RSQ9WYGSGHAYQ1ssbSqyzKJpqTunfx2I/1O0WB5k+L0cyXbG4XVZpoSoUc3M7wg==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Http": { + "type": "Transitive", + "resolved": "1.15.1", + "contentHash": "vFO4Fj/dXkoVNGo/nhoGpO2zYQmZwr4jTID7oRGo+XlQ8LqksyZjUXQ4p39RfUvTID7IzzL8Qe71tW7CcAFymA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Runtime": { + "type": "Transitive", + "resolved": "1.15.1", + "contentHash": "cpPwlUT5HXcLGPaIgsbSy0W9eFYAPGVbTP1p8/uyQ4Osvf5BJuPpEXE7crL09SmEd44r0DGNKDtsqxaAz0HxQw==", + "dependencies": { + "OpenTelemetry.Api": "[1.15.3, 2.0.0)" + } + }, + "Polly.Core": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "BpE2I6HBYYA5tF0Vn4eoQOGYTYIK1BlF5EXVgkWGn3mqUUjbXAr13J6fZVbp7Q3epRR8yshacBMlsHMhpOiV3g==" + }, + "Polly.Extensions": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "GZ9vRVmR0jV2JtZavt+pGUsQ1O1cuRKG7R7VOZI6ZDy9y6RNPvRvXK1tuS4ffUrv8L0FTea59oEuQzgS0R7zSA==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Polly.Core": "8.4.2" + } + }, + "Polly.RateLimiting": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "ehTImQ/eUyO07VYW2WvwSmU9rRH200SKJ/3jku9rOkyWE0A2JxNFmAVms8dSn49QLSjmjFRRSgfNyOgr/2PSmA==", + "dependencies": { + "Polly.Core": "8.4.2", + "System.Threading.RateLimiting": "8.0.0" + } + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "wugvy+pBVzjQEnRs9wMTWwoaeNFX3hsaHeVHFDIvJSWXp7wfmNWu3mxAwBIE6pyW+g6+rHa1Of5fTzb0QVqUTA==" + }, + "System.Threading.RateLimiting": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "7mu9v0QDv66ar3DpGSZHg9NuNcxDaaAcnMULuZlaTpP9+hwXhrxNGsF5GmLkSHxFdb5bBc1TzeujsRgTrPWi+Q==" + }, + "gmrelay.servicedefaults": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.Http.Resilience": "[10.2.0, )", + "Microsoft.Extensions.ServiceDiscovery": "[10.2.0, )", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.15.3, )", + "OpenTelemetry.Extensions.Hosting": "[1.15.3, )", + "OpenTelemetry.Instrumentation.AspNetCore": "[1.15.2, )", + "OpenTelemetry.Instrumentation.Http": "[1.15.1, )", + "OpenTelemetry.Instrumentation.Runtime": "[1.15.1, )" + } + }, + "gmrelay.shared": { + "type": "Project" + } + }, + "net10.0/win-x64": { + "Microsoft.DotNet.ILCompiler": { + "type": "Direct", + "requested": "[10.0.5, )", + "resolved": "10.0.5", + "contentHash": "yadTZIkStCVsG8nGwvfroSfBApPsgjQbodQyaIfp53dgayE0qhZpywixiCB6lx57JYQ+KVg1m1AFLrj54pxpZg==", + "dependencies": { + "runtime.win-x64.Microsoft.DotNet.ILCompiler": "10.0.5" + } + }, + "runtime.win-x64.Microsoft.DotNet.ILCompiler": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "vblLkpVhSDYOmrEW0jypX7YVtLg7idU1QzUyx45ZdZ2sFUSSf3mYFCr0FW3+KZgXWpN1ve9ZPrxNywvHISF4bA==" + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "wugvy+pBVzjQEnRs9wMTWwoaeNFX3hsaHeVHFDIvJSWXp7wfmNWu3mxAwBIE6pyW+g6+rHa1Of5fTzb0QVqUTA==" + } + } + } +} \ No newline at end of file diff --git a/src/GmRelay.ServiceDefaults/packages.lock.json b/src/GmRelay.ServiceDefaults/packages.lock.json new file mode 100644 index 0000000..65d1c84 --- /dev/null +++ b/src/GmRelay.ServiceDefaults/packages.lock.json @@ -0,0 +1,175 @@ +{ + "version": 1, + "dependencies": { + "net10.0": { + "Microsoft.Extensions.Http.Resilience": { + "type": "Direct", + "requested": "[10.2.0, )", + "resolved": "10.2.0", + "contentHash": "Lg+OjBW+ODDbM4Ax4LoERvQ1dqSZ8I2gQc2+B0/WOWl2+PunLJ3xb3x8MtHGfcb/Mp98RoMpwRKm6Aj9mzXwrA==", + "dependencies": { + "Microsoft.Extensions.Http.Diagnostics": "10.2.0", + "Microsoft.Extensions.Resilience": "10.2.0" + } + }, + "Microsoft.Extensions.ServiceDiscovery": { + "type": "Direct", + "requested": "[10.2.0, )", + "resolved": "10.2.0", + "contentHash": "AHTPfiKodj66xA8RwRkFD4q11V2AvzcuDsujv6ViPkOPtvBEYcPVplHakK56pPzWlX08MDS+TAQXfFXAeP7J5w==", + "dependencies": { + "Microsoft.Extensions.ServiceDiscovery.Abstractions": "10.2.0" + } + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "Direct", + "requested": "[1.15.3, )", + "resolved": "1.15.3", + "contentHash": "FEXJepcseTGbATiCkUfP7ipoFEYYfl/0UmmUwi0KxCPg9PaUA8ab2P1LGopK+/HExasJ1ZutFhZrN6WvUIR23g==", + "dependencies": { + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Extensions.Hosting": { + "type": "Direct", + "requested": "[1.15.3, )", + "resolved": "1.15.3", + "contentHash": "u8n/W8yIlqv0BXZmvId1iVaeWXG42tGKdTkuLYg5g57Y/r9CeUNzqtrSHNdG5IoO8iPX79w3v+WsbAHgUQbfeg==", + "dependencies": { + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Instrumentation.AspNetCore": { + "type": "Direct", + "requested": "[1.15.2, )", + "resolved": "1.15.2", + "contentHash": "2nPd7r0ug/gd6/CNFL6Rlu+RSQ9WYGSGHAYQ1ssbSqyzKJpqTunfx2I/1O0WB5k+L0cyXbG4XVZpoSoUc3M7wg==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Http": { + "type": "Direct", + "requested": "[1.15.1, )", + "resolved": "1.15.1", + "contentHash": "vFO4Fj/dXkoVNGo/nhoGpO2zYQmZwr4jTID7oRGo+XlQ8LqksyZjUXQ4p39RfUvTID7IzzL8Qe71tW7CcAFymA==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Runtime": { + "type": "Direct", + "requested": "[1.15.1, )", + "resolved": "1.15.1", + "contentHash": "cpPwlUT5HXcLGPaIgsbSy0W9eFYAPGVbTP1p8/uyQ4Osvf5BJuPpEXE7crL09SmEd44r0DGNKDtsqxaAz0HxQw==", + "dependencies": { + "OpenTelemetry.Api": "[1.15.3, 2.0.0)" + } + }, + "Microsoft.Extensions.AmbientMetadata.Application": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "CNrEjaOCZ8d1HtB0mvpiX4EWxLkee2xy+CsYXxmsEYJSFgw3OmF9pIhP/tCTeYBHhpsKJj5wM63G8IBFGxAcsw==" + }, + "Microsoft.Extensions.Compliance.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "1a4xDAT6fRyP8t419q3WvWMmMslDTvI7OAZLWBhn5rysFG0bl5xFenTswd1xAbT/3u3mx4Xyb5bPx+V+18tJeQ==" + }, + "Microsoft.Extensions.DependencyInjection.AutoActivation": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "Z/OI261l7LnxyODKPx0trQyIHFyicCR/akfn64lGOjPcf4FpAZ7ePAGl2HPvQBUBSNfPTF0gWeCfuFmyftMgYA==" + }, + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "3qMK1D40D10kb5TdBtFJpzz6/WH0NinWs68ZZS8jCFgHMXDiOjGiPOneMmIocCP/wnUUW4Hzf8lMsIE1xIGxDA==" + }, + "Microsoft.Extensions.Http.Diagnostics": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "I0FBgF6yZRwYH9E3KQ2vHm80YZ7YBj+52GDsmOWXPBv/p15b/wUoNupV9kw3LnSNVsWMqlGbiuZgBnHpMwPh+Q==", + "dependencies": { + "Microsoft.Extensions.Telemetry": "10.2.0" + } + }, + "Microsoft.Extensions.Resilience": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "v4WOdAOFxB3AcsUkZWNcHL3mYzs4KAPtHO8rkoQlFKOBoD3KyjjAL+h3tRwSK5i4UpF/yhxsQRY0JxKj4osxxw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": "10.2.0", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0", + "Polly.Extensions": "8.4.2", + "Polly.RateLimiting": "8.4.2" + } + }, + "Microsoft.Extensions.ServiceDiscovery.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "sANlOvfqfw/yfych4CLlHSKSWzIie6mQG7w83gVur1foNOafyHxcgpoQMvBf+KiB4Tpls6P1/Z77IIQSK8hxFg==" + }, + "Microsoft.Extensions.Telemetry": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "ssW5gosYlewNH/ISTyaLD/XfJT4GSjwShOUKv61fpXrqVmHkhuIA/5bBAGStM1XbzJjt9IG2vzfdHTu4zlX9Ew==", + "dependencies": { + "Microsoft.Extensions.AmbientMetadata.Application": "10.2.0", + "Microsoft.Extensions.DependencyInjection.AutoActivation": "10.2.0", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0" + } + }, + "Microsoft.Extensions.Telemetry.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "6V4V6NX6RLUYWwV89DeW/4zK5xOycYHWhsfMXSpKVGgMHfXcczmbk6hBeqTnRPzhpATYcOWlmA6hk1jgdxUugA==", + "dependencies": { + "Microsoft.Extensions.Compliance.Abstractions": "10.2.0" + } + }, + "OpenTelemetry": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "N0i6WjPoHPbZyms1ugbDIFAJFuGlpeExJMU/+XSL0lQRUkg/D0utFkDoLXf8Z1km5B+xVZ2GyMXXiX8qdeNmPg==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "1.15.3" + } + }, + "OpenTelemetry.Api": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "fX+fkCysfPut+qCcT3bKqyX4QN9Saf4CgX8HLOHywEVD+Xr7sULtfuypITpoDysjx8R59dn/3mWhgimMH8cm/g==" + }, + "OpenTelemetry.Api.ProviderBuilderExtensions": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "SYn0lqYDwLMWhv/zlNGsQcl2yX++yTumanX46bmOZE/ZDOd1WjPBO2kZaZgKLEZTZk48pavIFGJ6vOvxXgWVFQ==", + "dependencies": { + "OpenTelemetry.Api": "1.15.3" + } + }, + "Polly.Core": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "BpE2I6HBYYA5tF0Vn4eoQOGYTYIK1BlF5EXVgkWGn3mqUUjbXAr13J6fZVbp7Q3epRR8yshacBMlsHMhpOiV3g==" + }, + "Polly.Extensions": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "GZ9vRVmR0jV2JtZavt+pGUsQ1O1cuRKG7R7VOZI6ZDy9y6RNPvRvXK1tuS4ffUrv8L0FTea59oEuQzgS0R7zSA==", + "dependencies": { + "Polly.Core": "8.4.2" + } + }, + "Polly.RateLimiting": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "ehTImQ/eUyO07VYW2WvwSmU9rRH200SKJ/3jku9rOkyWE0A2JxNFmAVms8dSn49QLSjmjFRRSgfNyOgr/2PSmA==", + "dependencies": { + "Polly.Core": "8.4.2" + } + } + } + } +} \ No newline at end of file diff --git a/src/GmRelay.Shared/packages.lock.json b/src/GmRelay.Shared/packages.lock.json new file mode 100644 index 0000000..4a91a8c --- /dev/null +++ b/src/GmRelay.Shared/packages.lock.json @@ -0,0 +1,6 @@ +{ + "version": 1, + "dependencies": { + "net10.0": {} + } +} \ No newline at end of file diff --git a/src/GmRelay.Web/packages.lock.json b/src/GmRelay.Web/packages.lock.json new file mode 100644 index 0000000..d634357 --- /dev/null +++ b/src/GmRelay.Web/packages.lock.json @@ -0,0 +1,244 @@ +{ + "version": 1, + "dependencies": { + "net10.0": { + "Aspire.Npgsql": { + "type": "Direct", + "requested": "[13.2.2, )", + "resolved": "13.2.2", + "contentHash": "nEYgziWN7hksgEQEWy24JypcMCU8gKYcIIyPL05JfdXxUWuPRLotH/KOeuHevAjSEOYkL3dtGakBkJAuPobGmA==", + "dependencies": { + "AspNetCore.HealthChecks.NpgSql": "9.0.0", + "Npgsql.DependencyInjection": "10.0.1", + "Npgsql.OpenTelemetry": "10.0.1", + "OpenTelemetry.Extensions.Hosting": "1.15.0" + } + }, + "Dapper": { + "type": "Direct", + "requested": "[2.1.72, )", + "resolved": "2.1.72", + "contentHash": "ns4mGqQd9a/MhP8m6w556vVlZIa0/MfUu03zrxjZC/jlr1uVCsUac8bkdB+Fs98Llbd56rRSo1eZH5VVmeGZyw==" + }, + "Microsoft.AspNetCore.App.Internal.Assets": { + "type": "Direct", + "requested": "[10.0.5, )", + "resolved": "10.0.5", + "contentHash": "Oxw9Ps1/nd6c/EMCAI13AeJFEqXezAvCEOshMjUWmL7LeGirHJNzytR2e/3jINYg0j2TmPvNUowGHf+gp8zDSQ==" + }, + "Npgsql": { + "type": "Direct", + "requested": "[10.0.2, )", + "resolved": "10.0.2", + "contentHash": "q5RfBI+wywJSFUNDE1L4ZbHEHCFTblo8Uf6A6oe4feOUFYiUQXyAf9GBh5qEZpvJaHiEbpBPkQumjEhXCJxdrg==" + }, + "Telegram.Bot": { + "type": "Direct", + "requested": "[22.9.6.1, )", + "resolved": "22.9.6.1", + "contentHash": "I0eaMaETcWIhMn4uu4RGd9e6PLJOjaOG3QAcKPsTcS80H3TF6gqj3UF9NKu4ZY90ul6Y6NiWToHkg/PsvxkotA==" + }, + "AspNetCore.HealthChecks.NpgSql": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "npc58/AD5zuVxERdhCl2Kb7WnL37mwX42SJcXIwvmEig0/dugOLg3SIwtfvvh3TnvTwR/sk5LYNkkPaBdks61A==", + "dependencies": { + "Npgsql": "8.0.3" + } + }, + "Microsoft.Extensions.AmbientMetadata.Application": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "CNrEjaOCZ8d1HtB0mvpiX4EWxLkee2xy+CsYXxmsEYJSFgw3OmF9pIhP/tCTeYBHhpsKJj5wM63G8IBFGxAcsw==" + }, + "Microsoft.Extensions.Compliance.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "1a4xDAT6fRyP8t419q3WvWMmMslDTvI7OAZLWBhn5rysFG0bl5xFenTswd1xAbT/3u3mx4Xyb5bPx+V+18tJeQ==" + }, + "Microsoft.Extensions.DependencyInjection.AutoActivation": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "Z/OI261l7LnxyODKPx0trQyIHFyicCR/akfn64lGOjPcf4FpAZ7ePAGl2HPvQBUBSNfPTF0gWeCfuFmyftMgYA==" + }, + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "3qMK1D40D10kb5TdBtFJpzz6/WH0NinWs68ZZS8jCFgHMXDiOjGiPOneMmIocCP/wnUUW4Hzf8lMsIE1xIGxDA==" + }, + "Microsoft.Extensions.Http.Diagnostics": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "I0FBgF6yZRwYH9E3KQ2vHm80YZ7YBj+52GDsmOWXPBv/p15b/wUoNupV9kw3LnSNVsWMqlGbiuZgBnHpMwPh+Q==", + "dependencies": { + "Microsoft.Extensions.Telemetry": "10.2.0" + } + }, + "Microsoft.Extensions.Http.Resilience": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "Lg+OjBW+ODDbM4Ax4LoERvQ1dqSZ8I2gQc2+B0/WOWl2+PunLJ3xb3x8MtHGfcb/Mp98RoMpwRKm6Aj9mzXwrA==", + "dependencies": { + "Microsoft.Extensions.Http.Diagnostics": "10.2.0", + "Microsoft.Extensions.Resilience": "10.2.0" + } + }, + "Microsoft.Extensions.Resilience": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "v4WOdAOFxB3AcsUkZWNcHL3mYzs4KAPtHO8rkoQlFKOBoD3KyjjAL+h3tRwSK5i4UpF/yhxsQRY0JxKj4osxxw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": "10.2.0", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0", + "Polly.Extensions": "8.4.2", + "Polly.RateLimiting": "8.4.2" + } + }, + "Microsoft.Extensions.ServiceDiscovery": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "AHTPfiKodj66xA8RwRkFD4q11V2AvzcuDsujv6ViPkOPtvBEYcPVplHakK56pPzWlX08MDS+TAQXfFXAeP7J5w==", + "dependencies": { + "Microsoft.Extensions.ServiceDiscovery.Abstractions": "10.2.0" + } + }, + "Microsoft.Extensions.ServiceDiscovery.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "sANlOvfqfw/yfych4CLlHSKSWzIie6mQG7w83gVur1foNOafyHxcgpoQMvBf+KiB4Tpls6P1/Z77IIQSK8hxFg==" + }, + "Microsoft.Extensions.Telemetry": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "ssW5gosYlewNH/ISTyaLD/XfJT4GSjwShOUKv61fpXrqVmHkhuIA/5bBAGStM1XbzJjt9IG2vzfdHTu4zlX9Ew==", + "dependencies": { + "Microsoft.Extensions.AmbientMetadata.Application": "10.2.0", + "Microsoft.Extensions.DependencyInjection.AutoActivation": "10.2.0", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0" + } + }, + "Microsoft.Extensions.Telemetry.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "6V4V6NX6RLUYWwV89DeW/4zK5xOycYHWhsfMXSpKVGgMHfXcczmbk6hBeqTnRPzhpATYcOWlmA6hk1jgdxUugA==", + "dependencies": { + "Microsoft.Extensions.Compliance.Abstractions": "10.2.0" + } + }, + "Npgsql.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "YHFa4vD27sNIfv6s5q8Zi1fLvKfmK1xcpMv0PUvXOxDFbRmuMRSHwpZTbPvsAlj97q1/o7DfyynLqfqrCm1VnA==", + "dependencies": { + "Npgsql": "10.0.1" + } + }, + "Npgsql.OpenTelemetry": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "G9fEIBaHggZXWfDSDnKLc0XwKcbuU6i2eXp7zDqpgYxbhCmIN9fRgaSOGyyMNHSo/yY1IB4G4CjW5VO/SKRR0g==", + "dependencies": { + "Npgsql": "10.0.1", + "OpenTelemetry.API": "1.14.0" + } + }, + "OpenTelemetry": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "N0i6WjPoHPbZyms1ugbDIFAJFuGlpeExJMU/+XSL0lQRUkg/D0utFkDoLXf8Z1km5B+xVZ2GyMXXiX8qdeNmPg==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "1.15.3" + } + }, + "OpenTelemetry.Api": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "fX+fkCysfPut+qCcT3bKqyX4QN9Saf4CgX8HLOHywEVD+Xr7sULtfuypITpoDysjx8R59dn/3mWhgimMH8cm/g==" + }, + "OpenTelemetry.Api.ProviderBuilderExtensions": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "SYn0lqYDwLMWhv/zlNGsQcl2yX++yTumanX46bmOZE/ZDOd1WjPBO2kZaZgKLEZTZk48pavIFGJ6vOvxXgWVFQ==", + "dependencies": { + "OpenTelemetry.Api": "1.15.3" + } + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "FEXJepcseTGbATiCkUfP7ipoFEYYfl/0UmmUwi0KxCPg9PaUA8ab2P1LGopK+/HExasJ1ZutFhZrN6WvUIR23g==", + "dependencies": { + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Extensions.Hosting": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "u8n/W8yIlqv0BXZmvId1iVaeWXG42tGKdTkuLYg5g57Y/r9CeUNzqtrSHNdG5IoO8iPX79w3v+WsbAHgUQbfeg==", + "dependencies": { + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Instrumentation.AspNetCore": { + "type": "Transitive", + "resolved": "1.15.2", + "contentHash": "2nPd7r0ug/gd6/CNFL6Rlu+RSQ9WYGSGHAYQ1ssbSqyzKJpqTunfx2I/1O0WB5k+L0cyXbG4XVZpoSoUc3M7wg==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Http": { + "type": "Transitive", + "resolved": "1.15.1", + "contentHash": "vFO4Fj/dXkoVNGo/nhoGpO2zYQmZwr4jTID7oRGo+XlQ8LqksyZjUXQ4p39RfUvTID7IzzL8Qe71tW7CcAFymA==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Runtime": { + "type": "Transitive", + "resolved": "1.15.1", + "contentHash": "cpPwlUT5HXcLGPaIgsbSy0W9eFYAPGVbTP1p8/uyQ4Osvf5BJuPpEXE7crL09SmEd44r0DGNKDtsqxaAz0HxQw==", + "dependencies": { + "OpenTelemetry.Api": "[1.15.3, 2.0.0)" + } + }, + "Polly.Core": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "BpE2I6HBYYA5tF0Vn4eoQOGYTYIK1BlF5EXVgkWGn3mqUUjbXAr13J6fZVbp7Q3epRR8yshacBMlsHMhpOiV3g==" + }, + "Polly.Extensions": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "GZ9vRVmR0jV2JtZavt+pGUsQ1O1cuRKG7R7VOZI6ZDy9y6RNPvRvXK1tuS4ffUrv8L0FTea59oEuQzgS0R7zSA==", + "dependencies": { + "Polly.Core": "8.4.2" + } + }, + "Polly.RateLimiting": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "ehTImQ/eUyO07VYW2WvwSmU9rRH200SKJ/3jku9rOkyWE0A2JxNFmAVms8dSn49QLSjmjFRRSgfNyOgr/2PSmA==", + "dependencies": { + "Polly.Core": "8.4.2" + } + }, + "gmrelay.servicedefaults": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.Http.Resilience": "[10.2.0, )", + "Microsoft.Extensions.ServiceDiscovery": "[10.2.0, )", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.15.3, )", + "OpenTelemetry.Extensions.Hosting": "[1.15.3, )", + "OpenTelemetry.Instrumentation.AspNetCore": "[1.15.2, )", + "OpenTelemetry.Instrumentation.Http": "[1.15.1, )", + "OpenTelemetry.Instrumentation.Runtime": "[1.15.1, )" + } + }, + "gmrelay.shared": { + "type": "Project" + } + } + } +} \ No newline at end of file diff --git a/tests/GmRelay.Bot.Tests/packages.lock.json b/tests/GmRelay.Bot.Tests/packages.lock.json new file mode 100644 index 0000000..743677d --- /dev/null +++ b/tests/GmRelay.Bot.Tests/packages.lock.json @@ -0,0 +1,765 @@ +{ + "version": 1, + "dependencies": { + "net10.0": { + "coverlet.collector": { + "type": "Direct", + "requested": "[6.0.4, )", + "resolved": "6.0.4", + "contentHash": "lkhqpF8Pu2Y7IiN7OntbsTtdbpR1syMsm2F3IgX6ootA4ffRqWL5jF7XipHuZQTdVuWG/gVAAcf8mjk8Tz0xPg==" + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.14.1, )", + "resolved": "17.14.1", + "contentHash": "HJKqKOE+vshXra2aEHpi2TlxYX7Z9VFYkr+E5rwEvHC8eIXiyO+K9kNm8vmNom3e2rA56WqxU+/N9NJlLGXsJQ==", + "dependencies": { + "Microsoft.CodeCoverage": "17.14.1", + "Microsoft.TestPlatform.TestHost": "17.14.1" + } + }, + "xunit": { + "type": "Direct", + "requested": "[2.9.3, )", + "resolved": "2.9.3", + "contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==", + "dependencies": { + "xunit.analyzers": "1.18.0", + "xunit.assert": "2.9.3", + "xunit.core": "[2.9.3]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[3.1.4, )", + "resolved": "3.1.4", + "contentHash": "5mj99LvCqrq3CNi06xYdyIAXOEh+5b33F2nErCzI5zWiDdLHXiPXEWFSUAF8zlIv0ZWqjZNCwHTQeAPYbF3pCg==" + }, + "Aspire.Npgsql": { + "type": "Transitive", + "resolved": "13.2.2", + "contentHash": "nEYgziWN7hksgEQEWy24JypcMCU8gKYcIIyPL05JfdXxUWuPRLotH/KOeuHevAjSEOYkL3dtGakBkJAuPobGmA==", + "dependencies": { + "AspNetCore.HealthChecks.NpgSql": "9.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.HealthChecks": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5", + "Npgsql.DependencyInjection": "10.0.1", + "Npgsql.OpenTelemetry": "10.0.1", + "OpenTelemetry.Extensions.Hosting": "1.15.0" + } + }, + "AspNetCore.HealthChecks.NpgSql": { + "type": "Transitive", + "resolved": "9.0.0", + "contentHash": "npc58/AD5zuVxERdhCl2Kb7WnL37mwX42SJcXIwvmEig0/dugOLg3SIwtfvvh3TnvTwR/sk5LYNkkPaBdks61A==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "8.0.11", + "Npgsql": "8.0.3" + } + }, + "Dapper": { + "type": "Transitive", + "resolved": "2.1.72", + "contentHash": "ns4mGqQd9a/MhP8m6w556vVlZIa0/MfUu03zrxjZC/jlr1uVCsUac8bkdB+Fs98Llbd56rRSo1eZH5VVmeGZyw==" + }, + "Dapper.AOT": { + "type": "Transitive", + "resolved": "1.0.48", + "contentHash": "rsLM3yKr4g+YKKox9lhc8D+kz67P7Q9+xdyn1LmCsoYr1kYpJSm+Nt6slo5UrfUrcTiGJ57zUlyO8XUdV7G7iA==" + }, + "dbup-core": { + "type": "Transitive", + "resolved": "6.1.1", + "contentHash": "kgpuyJVEFJHoIj/slnc994Go88aoeZqNDfGHDBr4sh7CsEWwJhOTCt/FJqO4ziUImL5L0NEY0kxxOiNgPKI2Fw==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + } + }, + "dbup-postgresql": { + "type": "Transitive", + "resolved": "7.0.1", + "contentHash": "mRnmENWWPuuMZ538gOd1mZnzucx6FQk0anmw3EABjGfcbp24FDb9QdGepYrDiaM8K9s5/gd49+5cmBOlniH/lg==", + "dependencies": { + "Npgsql": "10.0.1", + "dbup-core": "6.1.1" + } + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.14.1", + "contentHash": "pmTrhfFIoplzFVbhVwUquT+77CbGH+h4/3mBpdmIlYtBi9nAB+kKI6dN3A/nV4DFi3wLLx/BlHIPK+MkbQ6Tpg==" + }, + "Microsoft.Extensions.AmbientMetadata.Application": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "CNrEjaOCZ8d1HtB0mvpiX4EWxLkee2xy+CsYXxmsEYJSFgw3OmF9pIhP/tCTeYBHhpsKJj5wM63G8IBFGxAcsw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.2", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.2", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.2" + } + }, + "Microsoft.Extensions.Compliance.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "1a4xDAT6fRyP8t419q3WvWMmMslDTvI7OAZLWBhn5rysFG0bl5xFenTswd1xAbT/3u3mx4Xyb5bPx+V+18tJeQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.ObjectPool": "10.0.2" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "8Rx5sqg04FttxrumyG6bmoRuFRgYzK6IVwF1i0/o0cXfKBdDeVpJejKHtJCMjyg9E/DNMVqpqOGe/tCT5gYvVA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "P09QpTHjqHmCLQOTC+WyLkoRNxek4NIvfWt+TnU0etoDUSRxcltyd6+j/ouRbMdLR0j44GqGO+lhI2M4fAHG4g==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "99Z4rjyXopb1MIazDSPcvwYCUdYNO01Cf1GUs2WUjIFAbkGmwzj2vPa2k+3pheJRV+YgNd2QqRKHAri0oBAU4Q==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.CommandLine": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "or9fOLopMUTJOQVJ3bou4aD6PwvsiKf4kZC4EE5sRRKSkmh+wfk/LekJXRjAX88X+1JA9zHjDo+5fiQ7z3MY/A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "tchMGQ+zVTO40np/Zzg2Li/TIR8bksQgg4UVXZa0OzeFCKWnIYtxE2FVs+eSmjPGCjMS2voZbwN/mUcYfpSTuA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "OhTr0O79dP49734lLTqVveivVX9sDXxbI/8vjELAZTHXqoN90mdpgTAgwicJED42iaHMCcZcK6Bj+8wNyBikaw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "brBM/WP0YAUYh2+QqSYVdK8eQHYQTtTEUJXJ+84Zkdo2buGLja9VSrMIhgoeBUU7JBmcskAib8Lb/N83bvxgYQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "fhdG6UV9lIp70QhNkVyaHciUVq25IPFkczheVJL9bIFvmnJ+Zghaie6dWkDbbVmxZlHl9gj3zTDxMxJs5zNhIA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Json": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "v1SVsowG6YE1YnHVGmLWz57YTRCQRx9pH5ebIESXfm5isI9gA3QaMyg/oMTzPpXYZwSAVDzYItGJKfmV+pqXkQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "iVMtq9eRvzyhx8949EGT0OCYJfXi737SbRVzWXE5GrOgGj5AaZ9eUuxA/BSUfmOMALKn/g8KfFaNQw0eiB3lyA==" + }, + "Microsoft.Extensions.DependencyInjection.AutoActivation": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "Z/OI261l7LnxyODKPx0trQyIHFyicCR/akfn64lGOjPcf4FpAZ7ePAGl2HPvQBUBSNfPTF0gWeCfuFmyftMgYA==", + "dependencies": { + "Microsoft.Extensions.Hosting.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "vAJHd4yOpmKoK+jBuYV7a3y+Ab9U4ARCc29b6qvMy276RgJFw9LFs0DdsPqOL3ahwzyrX7tM+i4cCxU/RX0qAg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/nYGrpa9/0BZofrVpBbbj+Ns8ZesiPE0V/KxsuHgDgHQopIzN54nRaQGSuvPw16/kI9sW1Zox5yyAPqvf0Jz6A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "3qMK1D40D10kb5TdBtFJpzz6/WH0NinWs68ZZS8jCFgHMXDiOjGiPOneMmIocCP/wnUUW4Hzf8lMsIE1xIGxDA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "REdt95QXHscGdtw/UUgyCW2lF9DJcAOJxmebKW2IkgUjuCAdMODIi2HNOWg5utW98nm8ekgV0Gjqs/sljwwqMw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "NrIMTy7dpqxAvA6kHAYH8cXID/YgeNOy0OqFKpLtkPu5X4WS/basX91UszANzVrMNRAICJ2GOnGiRxJtsRyEQw==" + }, + "Microsoft.Extensions.Features": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "X7tm2aV2w3lN9roSSGhl19lz4w76HvdiuKNhIv2XOiorYII9XCm66o/z9IJ0+QwkgvEv5gMZDM6rV6uwABHEQQ==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "nCBmCx0Xemlu65ZiWMcXbvfvtznKxf4/YYKF9R28QkqdI9lTikedGqzJ28/xmdGGsxUnsP5/3TQGpiPwVjK0dA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "dMu5kUPSfol1Rqhmr6nWPSmbFjDe9w6bkoKithG17bWTZA0UyKirTatM5mqYUN3mGpNA0MorlusIoVTh6J7o5g==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "mOE3ARusNQR0a5x8YOcnUbfyyXGqoAWQtEc7qFOfNJgruDWQLo39Re+3/Lzj5pLPFuFYj8hN4dgKzaSQDKiOCw==" + }, + "Microsoft.Extensions.Hosting": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "8i7e5IBdiKLNqt/+ciWrS8U95Rv5DClaaj7ulkZbimnCi4uREWd+lXzkp3joofFuIPOlAzV4AckxLTIELv2jdg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.Configuration.CommandLine": "10.0.5", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.5", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.5", + "Microsoft.Extensions.Configuration.Json": "10.0.5", + "Microsoft.Extensions.Configuration.UserSecrets": "10.0.5", + "Microsoft.Extensions.DependencyInjection": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Physical": "10.0.5", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Configuration": "10.0.5", + "Microsoft.Extensions.Logging.Console": "10.0.5", + "Microsoft.Extensions.Logging.Debug": "10.0.5", + "Microsoft.Extensions.Logging.EventLog": "10.0.5", + "Microsoft.Extensions.Logging.EventSource": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "+Wb7KAMVZTomwJkQrjuPTe5KBzGod7N8XeG+ScxRlkPOB4sZLG4ccVwjV4Phk5BCJt7uIMnGHVoN6ZMVploX+g==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.5", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "egUPC0xydb1ugCMcRyJ6zaOGOzx7N4coOVlGeLcIsXhUf1xHHwZeX+ob7JuG0dXExFduHYE/t+4/4y8BLlBKmw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Diagnostics": "10.0.2", + "Microsoft.Extensions.Logging": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2" + } + }, + "Microsoft.Extensions.Http.Diagnostics": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "I0FBgF6yZRwYH9E3KQ2vHm80YZ7YBj+52GDsmOWXPBv/p15b/wUoNupV9kw3LnSNVsWMqlGbiuZgBnHpMwPh+Q==", + "dependencies": { + "Microsoft.Extensions.Http": "10.0.2", + "Microsoft.Extensions.Telemetry": "10.2.0" + } + }, + "Microsoft.Extensions.Http.Resilience": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "Lg+OjBW+ODDbM4Ax4LoERvQ1dqSZ8I2gQc2+B0/WOWl2+PunLJ3xb3x8MtHGfcb/Mp98RoMpwRKm6Aj9mzXwrA==", + "dependencies": { + "Microsoft.Extensions.Http.Diagnostics": "10.2.0", + "Microsoft.Extensions.ObjectPool": "10.0.2", + "Microsoft.Extensions.Resilience": "10.2.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "+XTMKQyDWg4ODoNHU/BN3BaI1jhGO7VCS+BnzT/4IauiG6y2iPAte7MyD7rHKS+hNP0TkFkjrae8DFjDUxtcxg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "9HOdqlDtPptVcmKAjsQ/Nr5Rxfq6FMYLdhvZh1lVmeKR738qeYecQD7+ldooXf+u2KzzR1kafSphWngIM3C6ug==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Configuration": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "cSgxsDgfP0+gmVRPVoNHI/KIDavIZxh+CxE6tSLPlYTogqccDnjBFI9CgEsiNuMP6+fiuXUwhhlTz36uUEpwbQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.5", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Console": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "PMs2gha2v24hvH5o5KQem5aNK4mN0BhhCWlMqsg9tzifWKzjeQi2tyPOP/RaWMVvalOhVLcrmoMYPqbnia/epg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging.Configuration": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.Debug": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/VacEkBQ02A8PBXSa6YpbIXCuisYy6JJr62/+ANJDZE+RMBfZMcXJXLfr/LpyLE6pgdp17Wxlt7e7R9zvkwZ3Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.EventLog": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "0ezhWYJS4/6KrqQel9JL+Tr4n+4EX2TF5EYiaysBWNNEM2c3Gtj1moD39esfgk8OHblSX+UFjtZ3z0c4i9tRvw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "System.Diagnostics.EventLog": "10.0.5" + } + }, + "Microsoft.Extensions.Logging.EventSource": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "vN+aq1hBFXyYvY5Ow9WyeR66drKQxRZmas4lAjh6QWfryPkjTn1uLtX5AFIxyDaZj78v5TG2sELUyvrXpAPQQw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Logging": "10.0.5", + "Microsoft.Extensions.Logging.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "kpCp4m7nwJVBcRKWXYHdVK/W0dkKyyFOjCmKVdO+zKThWvUxP1V+jVEP9FGpqRu4GPl9041SEXu2f+U/l825nQ==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "MDaQMdUplw0AIRhWWmbLA7yQEXaLIHb+9CTroTiNS8OlI0LMXS4LCxtopqauiqGCWlRgJ+xyraVD8t6veRAFbw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "BB9uUW3+6Rxu1R97OB1H/13lUF8P2+H1+eDhpZlK30kDh/6E4EKHBUqTp+ilXQmZLzsRErxON8aBSR6WpUKJdg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.5", + "Microsoft.Extensions.Configuration.Binder": "10.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5", + "Microsoft.Extensions.Options": "10.0.5", + "Microsoft.Extensions.Primitives": "10.0.5" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "/HUHJ0tw/LQvD0DZrz50eQy/3z7PfX7WWEaXnjKTV9/TNdcgFlNTZGo49QhS7PTmhDqMyHRMqAXSBxLh0vso4g==" + }, + "Microsoft.Extensions.Resilience": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "v4WOdAOFxB3AcsUkZWNcHL3mYzs4KAPtHO8rkoQlFKOBoD3KyjjAL+h3tRwSK5i4UpF/yhxsQRY0JxKj4osxxw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics": "10.0.2", + "Microsoft.Extensions.Diagnostics.ExceptionSummarization": "10.2.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.2", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0", + "Polly.Extensions": "8.4.2", + "Polly.RateLimiting": "8.4.2" + } + }, + "Microsoft.Extensions.ServiceDiscovery": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "AHTPfiKodj66xA8RwRkFD4q11V2AvzcuDsujv6ViPkOPtvBEYcPVplHakK56pPzWlX08MDS+TAQXfFXAeP7J5w==", + "dependencies": { + "Microsoft.Extensions.Http": "10.0.2", + "Microsoft.Extensions.ServiceDiscovery.Abstractions": "10.2.0" + } + }, + "Microsoft.Extensions.ServiceDiscovery.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "sANlOvfqfw/yfych4CLlHSKSWzIie6mQG7w83gVur1foNOafyHxcgpoQMvBf+KiB4Tpls6P1/Z77IIQSK8hxFg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.Configuration.Binder": "10.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Features": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2", + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Telemetry": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "ssW5gosYlewNH/ISTyaLD/XfJT4GSjwShOUKv61fpXrqVmHkhuIA/5bBAGStM1XbzJjt9IG2vzfdHTu4zlX9Ew==", + "dependencies": { + "Microsoft.Extensions.AmbientMetadata.Application": "10.2.0", + "Microsoft.Extensions.DependencyInjection.AutoActivation": "10.2.0", + "Microsoft.Extensions.Logging.Configuration": "10.0.2", + "Microsoft.Extensions.ObjectPool": "10.0.2", + "Microsoft.Extensions.Telemetry.Abstractions": "10.2.0" + } + }, + "Microsoft.Extensions.Telemetry.Abstractions": { + "type": "Transitive", + "resolved": "10.2.0", + "contentHash": "6V4V6NX6RLUYWwV89DeW/4zK5xOycYHWhsfMXSpKVGgMHfXcczmbk6hBeqTnRPzhpATYcOWlmA6hk1jgdxUugA==", + "dependencies": { + "Microsoft.Extensions.Compliance.Abstractions": "10.2.0", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "Microsoft.Extensions.ObjectPool": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2" + } + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.14.1", + "contentHash": "xTP1W6Mi6SWmuxd3a+jj9G9UoC850WGwZUps1Wah9r1ZxgXhdJfj1QqDLJkFjHDCvN42qDL2Ps5KjQYWUU0zcQ==" + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.14.1", + "contentHash": "d78LPzGKkJwsJXAQwsbJJ7LE7D1wB+rAyhHHAaODF+RDSQ0NgMjDFkSA1Djw18VrxO76GlKAjRUhl+H8NL8Z+Q==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.14.1", + "Newtonsoft.Json": "13.0.3" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "q5RfBI+wywJSFUNDE1L4ZbHEHCFTblo8Uf6A6oe4feOUFYiUQXyAf9GBh5qEZpvJaHiEbpBPkQumjEhXCJxdrg==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "10.0.0" + } + }, + "Npgsql.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "YHFa4vD27sNIfv6s5q8Zi1fLvKfmK1xcpMv0PUvXOxDFbRmuMRSHwpZTbPvsAlj97q1/o7DfyynLqfqrCm1VnA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Npgsql": "10.0.1" + } + }, + "Npgsql.OpenTelemetry": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "G9fEIBaHggZXWfDSDnKLc0XwKcbuU6i2eXp7zDqpgYxbhCmIN9fRgaSOGyyMNHSo/yY1IB4G4CjW5VO/SKRR0g==", + "dependencies": { + "Npgsql": "10.0.1", + "OpenTelemetry.API": "1.14.0" + } + }, + "OpenTelemetry": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "N0i6WjPoHPbZyms1ugbDIFAJFuGlpeExJMU/+XSL0lQRUkg/D0utFkDoLXf8Z1km5B+xVZ2GyMXXiX8qdeNmPg==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0", + "Microsoft.Extensions.Logging.Configuration": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "1.15.3" + } + }, + "OpenTelemetry.Api": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "fX+fkCysfPut+qCcT3bKqyX4QN9Saf4CgX8HLOHywEVD+Xr7sULtfuypITpoDysjx8R59dn/3mWhgimMH8cm/g==" + }, + "OpenTelemetry.Api.ProviderBuilderExtensions": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "SYn0lqYDwLMWhv/zlNGsQcl2yX++yTumanX46bmOZE/ZDOd1WjPBO2kZaZgKLEZTZk48pavIFGJ6vOvxXgWVFQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0", + "OpenTelemetry.Api": "1.15.3" + } + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "FEXJepcseTGbATiCkUfP7ipoFEYYfl/0UmmUwi0KxCPg9PaUA8ab2P1LGopK+/HExasJ1ZutFhZrN6WvUIR23g==", + "dependencies": { + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Extensions.Hosting": { + "type": "Transitive", + "resolved": "1.15.3", + "contentHash": "u8n/W8yIlqv0BXZmvId1iVaeWXG42tGKdTkuLYg5g57Y/r9CeUNzqtrSHNdG5IoO8iPX79w3v+WsbAHgUQbfeg==", + "dependencies": { + "Microsoft.Extensions.Hosting.Abstractions": "10.0.0", + "OpenTelemetry": "1.15.3" + } + }, + "OpenTelemetry.Instrumentation.AspNetCore": { + "type": "Transitive", + "resolved": "1.15.2", + "contentHash": "2nPd7r0ug/gd6/CNFL6Rlu+RSQ9WYGSGHAYQ1ssbSqyzKJpqTunfx2I/1O0WB5k+L0cyXbG4XVZpoSoUc3M7wg==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Http": { + "type": "Transitive", + "resolved": "1.15.1", + "contentHash": "vFO4Fj/dXkoVNGo/nhoGpO2zYQmZwr4jTID7oRGo+XlQ8LqksyZjUXQ4p39RfUvTID7IzzL8Qe71tW7CcAFymA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.15.3, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Runtime": { + "type": "Transitive", + "resolved": "1.15.1", + "contentHash": "cpPwlUT5HXcLGPaIgsbSy0W9eFYAPGVbTP1p8/uyQ4Osvf5BJuPpEXE7crL09SmEd44r0DGNKDtsqxaAz0HxQw==", + "dependencies": { + "OpenTelemetry.Api": "[1.15.3, 2.0.0)" + } + }, + "Polly.Core": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "BpE2I6HBYYA5tF0Vn4eoQOGYTYIK1BlF5EXVgkWGn3mqUUjbXAr13J6fZVbp7Q3epRR8yshacBMlsHMhpOiV3g==" + }, + "Polly.Extensions": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "GZ9vRVmR0jV2JtZavt+pGUsQ1O1cuRKG7R7VOZI6ZDy9y6RNPvRvXK1tuS4ffUrv8L0FTea59oEuQzgS0R7zSA==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Polly.Core": "8.4.2" + } + }, + "Polly.RateLimiting": { + "type": "Transitive", + "resolved": "8.4.2", + "contentHash": "ehTImQ/eUyO07VYW2WvwSmU9rRH200SKJ/3jku9rOkyWE0A2JxNFmAVms8dSn49QLSjmjFRRSgfNyOgr/2PSmA==", + "dependencies": { + "Polly.Core": "8.4.2", + "System.Threading.RateLimiting": "8.0.0" + } + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "10.0.5", + "contentHash": "wugvy+pBVzjQEnRs9wMTWwoaeNFX3hsaHeVHFDIvJSWXp7wfmNWu3mxAwBIE6pyW+g6+rHa1Of5fTzb0QVqUTA==" + }, + "System.Threading.RateLimiting": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "7mu9v0QDv66ar3DpGSZHg9NuNcxDaaAcnMULuZlaTpP9+hwXhrxNGsF5GmLkSHxFdb5bBc1TzeujsRgTrPWi+Q==" + }, + "Telegram.Bot": { + "type": "Transitive", + "resolved": "22.9.6.1", + "contentHash": "I0eaMaETcWIhMn4uu4RGd9e6PLJOjaOG3QAcKPsTcS80H3TF6gqj3UF9NKu4ZY90ul6Y6NiWToHkg/PsvxkotA==", + "dependencies": { + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "1.18.0", + "contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA==" + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==", + "dependencies": { + "xunit.extensibility.core": "[2.9.3]", + "xunit.extensibility.execution": "[2.9.3]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "kf3si0YTn2a8J8eZNb+zFpwfoyvIrQ7ivNk5ZYA5yuYk1bEtMe4DxJ2CF/qsRgmEnDr7MnW1mxylBaHTZ4qErA==", + "dependencies": { + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "yMb6vMESlSrE3Wfj7V6cjQ3S4TXdXpRqYeNEI3zsX31uTsGMJjEw6oD5F5u1cHnMptjhEECnmZSsPxB6ChZHDQ==", + "dependencies": { + "xunit.extensibility.core": "[2.9.3]" + } + }, + "gmrelay.bot": { + "type": "Project", + "dependencies": { + "Aspire.Npgsql": "[13.2.2, )", + "Dapper": "[2.1.72, )", + "Dapper.AOT": "[1.0.48, )", + "GmRelay.ServiceDefaults": "[1.14.0, )", + "GmRelay.Shared": "[1.14.0, )", + "Microsoft.Extensions.Hosting": "[10.0.5, )", + "Npgsql": "[10.0.2, )", + "Telegram.Bot": "[22.9.5.3, )", + "dbup-postgresql": "[7.0.1, )" + } + }, + "gmrelay.servicedefaults": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.Http.Resilience": "[10.2.0, )", + "Microsoft.Extensions.ServiceDiscovery": "[10.2.0, )", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.15.3, )", + "OpenTelemetry.Extensions.Hosting": "[1.15.3, )", + "OpenTelemetry.Instrumentation.AspNetCore": "[1.15.2, )", + "OpenTelemetry.Instrumentation.Http": "[1.15.1, )", + "OpenTelemetry.Instrumentation.Runtime": "[1.15.1, )" + } + }, + "gmrelay.shared": { + "type": "Project" + }, + "gmrelay.web": { + "type": "Project", + "dependencies": { + "Aspire.Npgsql": "[13.2.2, )", + "Dapper": "[2.1.72, )", + "GmRelay.ServiceDefaults": "[1.14.0, )", + "GmRelay.Shared": "[1.14.0, )", + "Npgsql": "[10.0.2, )", + "Telegram.Bot": "[22.9.6.1, )" + } + } + } + } +} \ No newline at end of file From e3fdac15b54ae5cc7b1d624ff8288084d5e1807c Mon Sep 17 00:00:00 2001 From: Toutsu Date: Tue, 12 May 2026 12:31:20 +0300 Subject: [PATCH 4/4] ci: satisfy trivy dockerfile checks Run runtime images as the built-in non-root .NET app user and install Web runtime OS dependencies with --no-install-recommends. --- src/GmRelay.Bot/Dockerfile | 2 ++ src/GmRelay.Web/Dockerfile | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/GmRelay.Bot/Dockerfile b/src/GmRelay.Bot/Dockerfile index 820392c..fe2b961 100644 --- a/src/GmRelay.Bot/Dockerfile +++ b/src/GmRelay.Bot/Dockerfile @@ -33,5 +33,7 @@ WORKDIR /app # Копируем только AOT-результаты из билда COPY --from=build /app/publish . +USER $APP_UID + # Запуск скомпилированного AOT бинарного файла напрямую ENTRYPOINT ["./GmRelay.Bot"] diff --git a/src/GmRelay.Web/Dockerfile b/src/GmRelay.Web/Dockerfile index 7a6f163..e73a6f1 100644 --- a/src/GmRelay.Web/Dockerfile +++ b/src/GmRelay.Web/Dockerfile @@ -18,8 +18,9 @@ RUN dotnet publish "GmRelay.Web.csproj" -c Release -o /app/publish /p:UseAppHost # Stage 2: Runtime FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble AS final WORKDIR /app -RUN apt-get update && apt-get install -y libgssapi-krb5-2 && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y --no-install-recommends libgssapi-krb5-2 && rm -rf /var/lib/apt/lists/* COPY --from=build /app/publish . ENV ASPNETCORE_URLS=http://+:8080 EXPOSE 8080 +USER $APP_UID ENTRYPOINT ["dotnet", "GmRelay.Web.dll"]