Conversation
…ansport in AppHost
There was a problem hiding this comment.
Note
Copilot was unable to run its full agentic suite in this review.
Pull request overview
Introduces dynamic module discovery + per-module Contracts projects, adds a generated Kiota API client + enum serialization coverage, and enhances local/dev infrastructure via .NET Aspire AppHost and operational hardening.
Changes:
- Added
IAppModule/AppModuleLoader-based module discovery and updated Wolverine/architecture tests accordingly - Introduced per-module
*.Contractsprojects and wired references across modules and tests - Added Kiota-generated
APITemplate.ApiClient, enum string serialization tests, and a new Aspire AppHost for local orchestration
Reviewed changes
Copilot reviewed 79 out of 126 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/APITemplate.Tests/Unit/Identity/Mocks/RedisConnectionMultiplexerMockBuilder.cs | Updates Redis exception construction for test compatibility |
| tests/APITemplate.Tests/Unit/Identity/CreateUserCommandHandlerTests.cs | Aligns tests with Ensure* lifecycle naming |
| tests/APITemplate.Tests/Unit/Handlers/UserRequestHandlersTests.cs | Updates tests for new LoadAsync-before/handler signatures |
| tests/APITemplate.Tests/Unit/Clients/ApiClientEnumSerializationTests.cs | Adds Kiota enum string (de)serialization coverage + adapter mocking |
| tests/APITemplate.Tests/Unit/Architecture/ModuleDiscoveryTests.cs | Adds unit tests for module discovery behavior |
| tests/APITemplate.Tests/Unit/Architecture/ModuleBoundaryArchitectureTests.cs | Excludes *.Contracts from inter-module reference detection |
| tests/APITemplate.Tests/Unit/Architecture/HandlerConventionTests.cs | Enforces handler conventions (sealed + no public Validate* lifecycle methods) |
| tests/APITemplate.Tests/APITemplate.Tests.csproj | Adds Kiota deps + references to Contracts and ApiClient projects |
| src/Modules/Webhooks/WebhooksAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/Webhooks/Webhooks.csproj | Adds reference to Webhooks.Contracts |
| src/Modules/Reviews/ReviewsAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/Reviews/Reviews.csproj | Adds references to Reviews/ProductCatalog contracts |
| src/Modules/ProductCatalog/ProductCatalogAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/ProductCatalog/ProductCatalog.csproj | Adds references to ProductCatalog/Reviews contracts |
| src/Modules/ProductCatalog/Features/Product/GetProducts/ProductFilterCriteria.cs | Adds max-price exclusivity option for filtering |
| src/Modules/ProductCatalog/Features/Product/GetProducts/ProductFilter.cs | Adds PriceLessThanMax flag to API filter model |
| src/Modules/Notifications/Services/EmailRetryService.cs | Releases email claim on cancellation with best-effort persistence |
| src/Modules/Notifications/NotificationsAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/Notifications/Notifications.csproj | Adds references to Notifications/Identity contracts |
| src/Modules/Notifications/Domain/FailedEmail.cs | Adds ReleaseClaim() domain helper |
| src/Modules/Identity/IdentityAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/Identity/Identity.csproj | Adds reference to Identity.Contracts |
| src/Modules/Identity/Directory/Features/User/UpdateUser/UpdateUserCommand.cs | Renames ValidateAsync → LoadAsync and changes handler signature to accept loaded entity |
| src/Modules/Identity/Directory/Features/User/SetUserActive/SetUserActiveCommand.cs | Renames ValidateAsync → LoadAsync and changes handler signature to accept loaded entity |
| src/Modules/Identity/Directory/Features/User/DeleteUser/DeleteUserCommand.cs | Renames ValidateAsync → LoadAsync and changes handler signature to accept loaded entity |
| src/Modules/Identity/Directory/Features/User/CreateUser/CreateUserCommand.cs | Renames ValidateAsync → EnsureUniqueAsync and marks as Wolverine before-phase |
| src/Modules/Identity/Directory/Features/User/AssignRoles/AssignUserRolesCommandHandler.cs | Changes handler signature to accept loaded AppUser instead of ErrorOr wrapper |
| src/Modules/FileStorage/FileStorageAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/FileStorage/FileStorage.csproj | Adds reference to FileStorage.Contracts |
| src/Modules/Chatting/ChattingAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/BackgroundJobs/BackgroundJobsAppModule.cs | Adds module entrypoint for discovery/registration |
| src/Modules/BackgroundJobs/BackgroundJobs.csproj | Adds references to multiple Contracts for cross-module orchestration |
| src/Contracts/Webhooks.Contracts/Webhooks.Contracts.csproj | Introduces Webhooks contracts project |
| src/Contracts/Webhooks.Contracts/Commands/SendWebhookCallbackCommand.cs | Adds cross-module webhook delivery command contract |
| src/Contracts/Reviews.Contracts/Reviews.Contracts.csproj | Introduces Reviews contracts project |
| src/Contracts/Reviews.Contracts/Queries/ProductReviewResponse.cs | Adds Reviews read model contract for cross-module querying |
| src/Contracts/Reviews.Contracts/Queries/GetProductReviewsByProductIdsQuery.cs | Adds batch query contract for reviews |
| src/Contracts/ProductCatalog.Contracts/Queries/ValidateProductExistsQuery.cs | Adds product existence validation query contract |
| src/Contracts/ProductCatalog.Contracts/ProductCatalog.Contracts.csproj | Introduces ProductCatalog contracts project |
| src/Contracts/ProductCatalog.Contracts/Events/ProductsBatchSoftDeletedNotification.cs | Adds cross-module soft-delete batch notification contract |
| src/Contracts/ProductCatalog.Contracts/Commands/CleanupOrphanedProductDataCommand.cs | Adds cleanup command contract for background jobs orchestration |
| src/Contracts/Notifications.Contracts/Notifications.Contracts.csproj | Introduces Notifications contracts project |
| src/Contracts/Notifications.Contracts/Commands/RetryFailedEmailsCommand.cs | Adds retry command contract |
| src/Contracts/Notifications.Contracts/Commands/DeadLetterExpiredEmailsCommand.cs | Adds dead-lettering command contract |
| src/Contracts/Identity.Contracts/Identity.Contracts.csproj | Introduces Identity contracts project |
| src/Contracts/Identity.Contracts/Events/SoftDeleteEvents.cs | Adds tenant soft-delete notification contract |
| src/Contracts/Identity.Contracts/Events/EmailEvents.cs | Adds identity-related email trigger notification contracts |
| src/Contracts/Identity.Contracts/Commands/CleanupExpiredInvitationsCommand.cs | Adds cleanup command contract |
| src/Contracts/Identity.Contracts/Commands/CleanupExpiredBffSessionsCommand.cs | Adds cleanup command contract |
| src/Contracts/FileStorage.Contracts/FileStorage.Contracts.csproj | Introduces FileStorage contracts project |
| src/Contracts/FileStorage.Contracts/Commands/SweepOrphanBlobsCommand.cs | Adds orphan blob sweep command contract |
| src/Contracts/BackgroundJobs.Contracts/BackgroundJobs.Contracts.csproj | Introduces BackgroundJobs contracts project |
| src/Clients/APITemplate.ApiClient/Generated/kiota-lock.json | Adds Kiota lock file for reproducible client generation |
| src/Clients/APITemplate.ApiClient/Generated/Response.cs | Adds generated Kiota compatibility response type |
| src/Clients/APITemplate.ApiClient/Generated/Models/UserResponse.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/UpdateUserRequest.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/TenantInvitationResponse.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/SubmitJobRequest.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/ProvisioningStatus.cs | Adds generated Kiota enum |
| src/Clients/APITemplate.ApiClient/Generated/Models/ProductsResponse.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/ProductResponse.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/PagedUserResponse.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/PagedTenantInvitationResponse.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/JobStatusResponse.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/JobStatus.cs | Adds generated Kiota enum |
| src/Clients/APITemplate.ApiClient/Generated/Models/InvitationStatus.cs | Adds generated Kiota enum |
| src/Clients/APITemplate.ApiClient/Generated/Models/CreateUserRequest.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/CreateTenantInvitationRequest.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/CreateProductRequest.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/AssignUserRolesRequest.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Models/ApiProblemDetails.cs | Adds generated Kiota error model/exception |
| src/Clients/APITemplate.ApiClient/Generated/Models/AcceptInvitationRequest.cs | Adds generated Kiota model |
| src/Clients/APITemplate.ApiClient/Generated/Health/Ready/ReadyResponse.cs | Adds generated Kiota health endpoint support |
| src/Clients/APITemplate.ApiClient/Generated/Health/Ready/ReadyRequestBuilder.cs | Adds generated Kiota request builder |
| src/Clients/APITemplate.ApiClient/Generated/Health/Ready/ReadyGetResponse.cs | Adds generated Kiota response type |
| src/Clients/APITemplate.ApiClient/Generated/Health/Live/LiveResponse.cs | Adds generated Kiota health endpoint support |
| src/Clients/APITemplate.ApiClient/Generated/Health/Live/LiveRequestBuilder.cs | Adds generated Kiota request builder |
| src/Clients/APITemplate.ApiClient/Generated/Health/Live/LiveGetResponse.cs | Adds generated Kiota response type |
| src/Clients/APITemplate.ApiClient/Generated/Health/HealthResponse.cs | Adds generated Kiota health endpoint support |
| src/Clients/APITemplate.ApiClient/Generated/Health/HealthRequestBuilder.cs | Adds generated Kiota request builder |
| src/Clients/APITemplate.ApiClient/Generated/Health/HealthGetResponse.cs | Adds generated Kiota response type |
| src/Clients/APITemplate.ApiClient/Generated/GetResponse.cs | Adds generated Kiota response model |
| src/Clients/APITemplate.ApiClient/Generated/ApiClient.cs | Adds generated Kiota root client |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/V1RequestBuilder.cs | Adds generated Kiota API version builder |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Users/UsersRequestBuilder.cs | Adds generated Kiota users endpoints |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Users/Me/MeRequestBuilder.cs | Adds generated Kiota /me endpoint |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Users/Item/Roles/RolesRequestBuilder.cs | Adds generated Kiota roles endpoint |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Users/Item/Deactivate/DeactivateRequestBuilder.cs | Adds generated Kiota deactivate endpoint |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Users/Item/Activate/ActivateRequestBuilder.cs | Adds generated Kiota activate endpoint |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/TenantInvitations/TenantInvitationsRequestBuilder.cs | Adds generated Kiota tenant invitations endpoints |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/TenantInvitations/Accept/AcceptRequestBuilder.cs | Adds generated Kiota invitation accept endpoint |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Products/ProductsRequestBuilder.cs | Adds generated Kiota products endpoints |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Products/Item/ProductsItemRequestBuilder.cs | Adds generated Kiota product-by-id endpoint |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Jobs/JobsRequestBuilder.cs | Adds generated Kiota jobs endpoints |
| src/Clients/APITemplate.ApiClient/Generated/Api/V1/Jobs/Item/JobsItemRequestBuilder.cs | Adds generated Kiota job-by-id endpoint |
| src/Clients/APITemplate.ApiClient/Generated/Api/ApiRequestBuilder.cs | Adds generated Kiota API root builder |
| src/Clients/APITemplate.ApiClient/Extensions/ServiceCollectionExtensions.cs | Adds DI registration helpers for Kiota ApiClient |
| src/Clients/APITemplate.ApiClient/ApiClientOptions.cs | Adds options for Kiota client configuration |
| src/Clients/APITemplate.ApiClient/APITemplate.ApiClient.csproj | Introduces ApiClient project packaging + deps |
| src/BuildingBlocks/BuildingBlocks.Messaging/Pipeline/ErrorOrUnwrapFrame.cs | Adds generated middleware frame to unwrap ErrorOr results |
| src/BuildingBlocks/BuildingBlocks.Messaging/Pipeline/ErrorOrRailwayPolicy.cs | Adds Wolverine handler policy to insert ErrorOr unwrap/short-circuit |
| src/BuildingBlocks/BuildingBlocks.Application/Modules/IAppModule.cs | Adds module abstraction for discovery/registration |
| src/BuildingBlocks/BuildingBlocks.Application/Modules/AppModuleLoader.cs | Adds runtime module discovery via DependencyContext |
| src/BuildingBlocks/BuildingBlocks.Application/BuildingBlocks.Application.csproj | Adds DependencyModel dependency for module discovery |
| src/APITemplate/Api/appsettings.Development.json5 | Adds dev defaults (connection string, observability flags, keycloak password verification) |
| src/APITemplate/Api/WolverineModuleDiscovery.cs | Switches Wolverine scanning to dynamic module discovery |
| src/APITemplate/Api/Program.cs | Adds ErrorOrRailwayPolicy + updates GraphQL registration signature |
| src/APITemplate/Api/Extensions/MvcConventionsServiceCollectionExtensions.cs | Configures enum string serialization for MVC + minimal endpoints |
| src/APITemplate/Api/Extensions/GraphQLServiceCollectionExtensions.cs | Makes introspection configurable (not only env-based) |
| src/APITemplate/Api/Dockerfile | Runs final container stage as non-root user |
| src/APITemplate/Api/APITemplate.csproj | Adds OpenApi versioning + Wolverine runtime compilation |
| src/APITemplate.AppHost/appsettings.json5 | Adds AppHost logging defaults |
| src/APITemplate.AppHost/appsettings.Development.json5 | Adds AppHost dev logging defaults |
| src/APITemplate.AppHost/Properties/launchSettings.json | Adds AppHost launch profile |
| src/APITemplate.AppHost/Program.cs | Adds Aspire orchestration for local dev dependencies |
| src/APITemplate.AppHost/APITemplate.AppHost.csproj | Introduces AppHost project + Aspire packages |
| aspire.config.json | Registers AppHost path for Aspire tooling |
| TODO.md | Adds Aspire enhancement backlog items |
| Directory.Build.props | Suppresses additional analyzer warnings |
| BUG_DIAGNOSTIC_REPORT.md | Adds diagnostic report documentation |
| APITemplate.slnx | Adds new projects (Contracts, ApiClient, AppHost) to solution |
| .gitignore | Ignores *.binlog artifacts |
| .config/dotnet-tools.json | Adds Kiota tool to the repo tool manifest |
Suppressed comments (4)
src/Contracts/Webhooks.Contracts/Webhooks.Contracts.csproj:1
- SDK-style projects require a TargetFramework (or TargetFrameworks). As written, this project (and the other newly added
*.Contracts.csprojfiles with the same structure) will fail to build. Add a<PropertyGroup>with aTargetFramework(matching the repo, e.g.,net10.0) and (optionally) alignNullable/ImplicitUsingswith the rest of the solution.
tests/APITemplate.Tests/Unit/Clients/ApiClientEnumSerializationTests.cs:1 - These tests mutate Kiota’s global singleton registries in the test class constructor. Because xUnit runs tests in parallel by default, this can cause cross-test interference and race conditions (including with other test classes). Prefer one-time initialization in a non-parallelized test collection/fixture, and consider restoring any previous factory registrations after the tests complete to keep global state isolated.
src/Modules/Notifications/Services/EmailRetryService.cs:1 - The cancellation cleanup intentionally suppresses persistence failures, but swallowing the exception entirely makes it difficult to detect claim leaks in production. Consider at least logging the suppressed exception (e.g., at Debug/Warning) so operators can diagnose when cleanup fails, while still avoiding throwing during cancellation handling.
tests/APITemplate.Tests/Unit/Handlers/UserRequestHandlersTests.cs:1 - This variable is now the result of
LoadAsync, but it is still namedvalidation. Rename to something likeloadResult(consistent with other updated tests in this file) to avoid confusion about what the value represents.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| { | ||
| _context = chain.FindVariable(typeof(MessageContext)); | ||
| yield return _beforeResult; | ||
| yield return _context; |
Comment on lines
+32
to
+44
| services.AddHttpClient<ApiClient>( | ||
| (sp, httpClient) => | ||
| { | ||
| ApiClientOptions options = sp.GetRequiredService< | ||
| IOptions<ApiClientOptions> | ||
| >().Value; | ||
| if (options.BaseUrl is not null) | ||
| { | ||
| httpClient.BaseAddress = options.BaseUrl; | ||
| } | ||
| httpClient.Timeout = options.Timeout; | ||
| } | ||
| ); |
Comment on lines
+59
to
+64
| IHttpClientFactory httpClientFactory = sp.GetRequiredService<IHttpClientFactory>(); | ||
| HttpClient httpClient = httpClientFactory.CreateClient(nameof(ApiClient)); | ||
| IAuthenticationProvider authProvider = sp.GetRequiredService<IAuthenticationProvider>(); | ||
| ApiClientOptions options = sp.GetRequiredService<IOptions<ApiClientOptions>>().Value; | ||
|
|
||
| HttpClientRequestAdapter adapter = new(authProvider, httpClient: httpClient); |
| IResourceBuilder<ContainerResource> dragonfly = builder | ||
| .AddContainer("dragonfly", "docker.dragonflydb.io/dragonflydb/dragonfly", "v1.27.1") | ||
| .WithArgs("dragonfly", "--maxmemory", "512mb", "--proactor_threads", "2", "--cache_mode=true") | ||
| .WithHttpEndpoint(targetPort: 6379, port: 6379, name: "redis"); |
Comment on lines
+33
to
+36
| List<MethodCall> beforeCalls = chain | ||
| .Middleware.OfType<MethodCall>() | ||
| .Where(call => ClosesErrorOr(call.ReturnVariable?.VariableType)) | ||
| .ToList(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Popis zmien