Skip to content
CAI
Software that uses CAICheck a score

kgrzybek/modular-monolith-with-ddd

55.2

Weak · 22 September 2026

23.5k

lines of production code

C#

primary language

5

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is a modular monolith application for managing meetings, groups, and payments, built on a Domain-Driven Design architecture. It provides comprehensive APIs for creating and managing meetings, handling user registrations and authentication, and processing subscription payments and fee collections. The system enforces strict access controls, event-driven consistency via outbox/inbox patterns, and automated background processing for subscriptions and internal commands.

How it got here

2019 — Modular monolith implementation

74 changes.

The project established a modular monolith architecture with distinct modules for Administration, Meetings, Payments, and UserAccess, each containing domain, application, and infrastructure layers. This period focused on implementing core domain models, application commands/queries, and API endpoints while introducing architectural tests to enforce module isolation and clean code standards.

2020 — Domain-driven architecture and payment features

99 changes.

This period focused on establishing a modular, event-sourced architecture across the Payments, Meetings, and Administration modules, introducing command/query handlers, outbox/inbox processing, and background job scheduling. It also implemented core business capabilities for subscription management, pricing, and meeting interactions, supported by comprehensive integration and unit tests.

2021–2024 — User and registration infrastructure

4 changes.

This period focused on establishing the core application and data layers for user management and registration workflows. The team implemented the Nuke build system to streamline development and CI processes, while simultaneously introducing database schemas and application modules to support user accounts, admin creation, and email-based registration confirmation.

Features

Ability to set expiration date for meeting groups

Users can now set an expiration date for a meeting group. This change introduces a new command and handler that allow the system to update a meeting group's expiration date via the application layer, persisting the change through the meeting group repository.

src/Modules/Meetings/Application/MeetingGroups/SetMeetingGroupExpirationDate · high confidence

Add API endpoints for managing meeting group proposals

A new controller and request model have been added to expose three endpoints for meeting group proposals: a GET endpoint to retrieve the current member's proposals, a paginated GET endpoint to list all proposals, and a POST endpoint to create a new proposal with name, description, and location details.

src/API/CompanyName.MyMeetings.API/Modules/Meetings/MeetingGroupProposals · high confidence

Add DatabaseMigrator tool for automated database schema migrations

A new DatabaseMigrator application has been introduced to handle database schema updates. The tool accepts a connection string and a path to SQL scripts, then uses the DbUp library to apply pending migrations to the target database. It logs all migration activity to the console and to JSON files in a 'logs\\migration-logs' directory, and tracks the migration state in an 'MigrationsJournal' table. A .dockerignore file was also added to optimize Docker builds for this component.

src/Database/DatabaseMigrator · high confidence

Add ability to enable or disable commenting on meetings

Users can now enable or disable commenting on a meeting. This change introduces commands to enable and disable commenting, a query to retrieve the current configuration, and an event handler that automatically creates a default commenting configuration when a new meeting is created.

src/Modules/Meetings/Application/MeetingCommentingConfigurations · high confidence

Add ability to propose a new meeting group

Users can now submit a proposal to create a new meeting group by providing a name, description, city, and country code. This change introduces the command, handler, and validator for the 'Propose Meeting Group' feature within the Meetings module.

src/Modules/Meetings/Application/MeetingGroupProposals/ProposeMeetingGroup · high confidence

Add admin user creation capability

Users can now create an admin user account through the application layer. This change introduces a new command and its internal handler to process admin user registration, including password hashing and repository integration.

src/Modules/UserAccess/Application/Users/AddAdminUser · high confidence

Add application layer for accepting meeting group proposals

Users can now accept a meeting group proposal through a new command and handler that process the acceptance, trigger a domain event, and publish an integration event to the event bus. The change introduces the command, the command handler that updates the proposal status, a notification for the accepted state, and a handler that forwards the acceptance to the external event bus, alongside an integration event handler that schedules a verification request for new proposals.

src/Modules/Administration/Application/MeetingGroupProposals/AcceptMeetingGroupProposal · high confidence

Add command and handler for verifying meeting group proposals

Users can now submit a request to verify a meeting group proposal. This change introduces a new command and its corresponding handler, which creates a new meeting group proposal in a 'to verify' state, storing details such as name, description, location, and the proposing user's ID.

src/Modules/Administration/Application/MeetingGroupProposals/RequestMeetingGroupProposalVerification · high confidence

Add database mapping and repository implementations for meeting commenting and group proposals

The Meetings module's infrastructure layer now includes Entity Framework Core configuration classes and repository implementations for the new \MeetingCommentingConfiguration\ and \MeetingGroupProposal\ aggregates. Specifically, \MeetingCommentingConfigurationEntityTypeConfiguration\ and \MeetingCommentingConfigurationRepository\ are introduced to handle the storage and retrieval of commenting settings per meeting. Similarly, \MeetingGroupProposalEntityTypeConfiguration\ and \MeetingGroupProposalRepository\ are added to manage the persistence of meeting group proposals. These changes are reflected in the \MeetingsContext\ which registers the new entity sets, and the \MeetingsModule\ which wires up the command/query execution pipeline for these features.

src/Modules/Meetings/Infrastructure · high confidence

Add database structure for registrations, payments, and user management

The database schema is expanded with new tables and views to support user registration, payment processing, and role-based access control. New tables include UserRegistrations, Payers, SubscriptionDetails, and Permissions, alongside corresponding views (v\_UserRegistrations, v\_UserPermissions) and schema definitions for the registrations, payments, and users domains. This change introduces the foundational data structures required for managing user accounts, processing payments, and enforcing permissions.

src/Database/CompanyName.MyMeetings.Database/Structure · high confidence

Add email history retrieval capability

Users can now retrieve a list of all sent emails, including the sender, recipient, subject, content, and date. This is implemented via a new query and handler that fetch email records from the database, supporting the storage and retrieval of email history for the registration process.

src/Modules/UserAccess/Application/Emails · medium confidence

Add endpoint to retrieve all countries

A new API endpoint is introduced at /api/meetings/countries to return a list of all countries. This allows clients to fetch the complete list of countries, supporting pagination via page and perPage parameters.

src/API/CompanyName.MyMeetings.API/Modules/Meetings/Countries · high confidence

Add endpoint to retrieve authenticated user's permissions

A new query and handler have been introduced to fetch the list of permissions for the currently authenticated user. The implementation queries the 'users.v\_UserPermissions' view to return a list of user permissions, which can be used by the GUI to determine available actions or access levels.

src/Modules/UserAccess/Application/Authorization/GetAuthenticatedUserPermissions · high confidence

Add meeting comment functionality

Users can now interact with meeting comments by adding, replying to, editing, and removing them, as well as liking and unliking comments. The update also introduces the ability to view who liked a specific comment and retrieve a list of all comments for a meeting.

src/Modules/Meetings/Application/MeetingComments · high confidence

Add meeting comment management endpoints

The API now exposes endpoints for managing meeting comments, allowing users to add, edit, delete, reply to, and like/unlike comments on meetings. These new controller actions map to the corresponding use cases for creating, modifying, and removing comments and their associated interactions.

src/API/CompanyName.MyMeetings.API/Modules/Meetings/MeetingComments · high confidence

Add meeting fee and payment creation workflows

The Payments module now includes new application-layer components to handle the creation of meeting fees and their associated payments. This introduces command and command handler classes for creating a meeting fee (including payer, meeting, value, and currency) and for creating a payment linked to a specific fee. Additionally, an integration event handler automatically schedules the creation of a meeting fee when a user is added as an attendee to a meeting, provided a fee value is specified.

src/Modules/Payments/Application/MeetingFees/CreateMeetingFee · high confidence

Add meeting management commands and queries

The application layer for the Meetings module now includes a comprehensive set of commands and queries to manage meetings and attendees. Users can now create, cancel, and modify meeting details, as well as add, remove, or change the role of attendees. The update also introduces queries to retrieve meeting details, a list of meetings for authenticated members, and attendee information, alongside handlers for processing fee payments and sending email notifications when a member is added to a meeting.

src/Modules/Meetings/Application/Meetings · high confidence

Add member retrieval and creation capabilities in the Administration module

Users can now retrieve member details and create new members through the Administration module. The diff introduces a new CreateMember command and handler for member creation, and a GetMember query with its handler and DTO for fetching member data (Id, Login, Email, FirstName, LastName, Name) from the database.

src/Modules/Administration/Application/Members/GetMember · medium confidence

Add outbox processing for publishing domain events

The Payments module now includes infrastructure components to process an outbox for publishing domain events. A new \ProcessOutboxCommand\ and its handler query the \payments.OutboxMessages\ table for unprocessed messages, deserialize them into domain event notifications, and publish them via the mediator. A Quartz job (\ProcessOutboxJob\) triggers this command, and an Autofac module (\OutboxModule\) registers the SQL outbox accessor and a domain notifications mapper that validates all \IDomainEventNotification\ implementations are mapped to a string name.

src/Modules/Payments/Infrastructure/Configuration/Processing/Outbox · high confidence

Add price list item management and querying

Users can now create, update, activate, and deactivate price list items, as well as retrieve their values. This adds the application layer commands and queries needed to manage price list items in the payments module.

src/Modules/Payments/Application/PriceListItems · high confidence

Add query to retrieve meeting group details

Introduced a new application layer implementation for fetching meeting group details. The change adds a \GetMeetingGroupDetailsQuery\ and its corresponding handler, which queries the \v\_MeetingGroups\ view to retrieve a group's name, description, location, and member count. This provides the backend support for displaying detailed information about a specific meeting group.

src/Modules/Administration/Application/MeetingGroupProposals/GetMeetingGroupProposal, src/Modules/Meetings/Application/MeetingGroupProposals/GetMeetingGroupProposal, src/Modules/Meetings/Application/MeetingGroups/GetMeetingGroupDetails · high confidence

Add scheduled processing for internal commands with retry logic

The Payments module now supports processing internal commands via a scheduled job (ProcessInternalCommandsJob) that executes the ProcessInternalCommandsCommand handler. This handler retrieves pending internal commands from the database, deserializes them, and executes them using the CommandsExecutor. Importantly, each command execution is wrapped in a Polly-based retry policy (1s, 2s, 3s delays) to handle transient failures, and any errors are recorded in the database for later inspection.

src/Modules/Payments/Infrastructure/Configuration/Processing/InternalCommands · high confidence

Add subscription expiration capability

Users can now expire subscriptions through a new internal command and handler. The \ExpireSubscriptionCommand\ and its handler load the specific subscription aggregate, call the \Expire()\ method on it, and persist the changes, effectively implementing the business logic for subscription expiration.

src/Modules/Payments/Application/Subscriptions/ExpireSubscription · high confidence

Add user creation capability via a new command and handler

A new CreateUser command and its corresponding handler have been introduced in the UserAccess module. The command carries user details (ID, login, email, name, password), and the handler persists the new user via the repository, enabling the application to create users.

src/Modules/UserAccess/Application/Users/CreateUser · medium confidence

Added Docker support for the Database service and DatabaseMigrator

The Database area now includes Docker configuration files (Dockerfile, .dockerignore) and shell scripts (entrypoint.sh, entrypoint\_DatabaseMigrator.sh, wait-for-it.sh) to containerize the SQL Server instance and the database migration tool. This enables running the database environment via Docker, including automated startup, database creation, and migration execution.

src/Database · high confidence

Added GetAuthenticatedUser query and handler

Introduced a new application layer component for retrieving the authenticated user's details. The diff adds a \GetAuthenticatedUserQuery\ and its corresponding \GetAuthenticatedUserQueryHandler\. The handler executes a SQL query against the \users.v\_Users\ view to fetch user attributes (Id, IsActive, Login, Email, Name) for the currently authenticated user, mapping the result to a \UserDto\.

src/Modules/UserAccess/Application/Users/GetAuthenticatedUser · high confidence

Added GetUser query to retrieve user details

A new application layer implementation for retrieving a user's profile has been introduced. This includes a GetUserQuery to define the request, a GetUserQueryHandler that executes a SQL query against the users table, and a UserDto to map the results. This provides the backend logic required to fetch user information by ID.

src/Modules/UserAccess/Application/Users/GetUser · high confidence

Added InboxMessage class for message tracking

A new InboxMessage class has been introduced in the BuildingBlocks.Infrastructure.Inbox namespace. This class defines the structure for tracking messages, including properties for an ID, occurrence timestamp, type, and data payload. This provides the foundational data model for the inbox infrastructure.

src/BuildingBlocks/Infrastructure/Inbox · high confidence

Added Swagger documentation and UI configuration for the MyMeetings API

The API project now includes a new \SwaggerExtensions\ class that configures Swagger for API documentation. This adds the Swagger middleware to the application pipeline, enabling the Swagger UI and JSON documentation endpoint at \/swagger/v1/swagger.json\. The configuration includes API metadata, XML comment inclusion, and Bearer token security scheme setup.

src/API/CompanyName.MyMeetings.API/Configuration/Extensions · high confidence

Added ability to mark meeting fees and payments as paid

Users can now mark meeting fees and meeting fee payments as paid. This change introduces new application commands and handlers for both \MarkMeetingFeeAsPaid\ and \MarkMeetingFeePaymentAsPaid\. When a fee or payment is marked as paid, the system updates the aggregate state and publishes integration events to notify downstream systems of the status change.

src/Modules/Payments/Application/MeetingFees/MarkMeetingFeeAsPaid · high confidence

Added ability to retrieve and project meeting fee details

Users can now retrieve a list of fees associated with a specific meeting. This is enabled by a new query and handler that fetch meeting fee data (ID, payer, currency, value, status) from the database, alongside a projector that updates fee status in the database when domain events (created, paid, expired, canceled) occur.

src/Modules/Payments/Application/MeetingFees/GetMeetingFees · high confidence

Added application-layer pagination support and developer tooling

The application layer now supports paginated queries via the new IPagedQuery interface and PagedQueryHelper, which calculate offset and next-page values and append SQL pagination statements. Additionally, the project includes HTTP request examples for authentication and user registration, an .editorconfig for code style rules, a global.json pinning the .NET SDK to version 8.0.0, and a Dockerfile with an entrypoint script for containerized deployment.

src · high confidence

Added command and handler to mark subscription renewal payments as paid

Users can now process the payment for a subscription renewal. This change introduces a new command, handler, and notification flow that marks a subscription renewal payment as paid and subsequently schedules the renewal of the subscription.

src/Modules/Payments/Application/Subscriptions/MarkSubscriptionRenewalPaymentAsPaid · high confidence

Added commands to create and edit meeting groups

The application layer now includes new commands and handlers for creating new meeting groups and editing their general attributes (name, description, city, and country). Users can now initiate the creation of a meeting group from a proposal and update the group's core details through dedicated command handlers.

src/Modules/Meetings/Application/MeetingGroups/CreateNewMeetingGroup · high confidence

Added commands to join and leave meeting groups

Users can now join or leave a meeting group through the application layer. The diff introduces four new files: the command objects (JoinToGroupCommand, LeaveMeetingGroupCommand) and their corresponding handlers (JoinToGroupCommandHandler, LeaveMeetingGroupCommandHandler). The handlers interact with the domain models to execute the join and leave actions.

src/Modules/Meetings/Application/MeetingGroups/JoinToGroup, src/Modules/Meetings/Application/MeetingGroups/LeaveMeetingGroup · high confidence

Added core infrastructure building blocks

The infrastructure layer now includes a bidirectional dictionary, a unit of work implementation that dispatches domain events before saving changes, a service provider wrapper for Autofac, a SQL connection factory, and EF Core value converters for strongly typed IDs.

src/BuildingBlocks/Infrastructure · high confidence

Added domain event and database mappings for internal commands

Introduced a new MemberCreatedDomainEvent to track member creation within the Meetings module. Additionally, added Entity Framework Core configuration classes for the InternalCommand entity across the Meetings, Payments, and UserAccess modules, mapping each to its respective database schema (meetings, payments, users).

(repo-wide) · high confidence

Added domain events for meeting group proposals

Introduced new domain events to track the lifecycle of meeting group proposals. Specifically, the system now emits a \MeetingGroupProposedDomainEvent\ containing proposal details (name, description, location, user, and date) and a \MeetingGroupProposalAcceptedDomainEvent\ to signal when a proposal is accepted. These events enable downstream processes to react to proposal creation and acceptance states.

src/Modules/Meetings/Domain/MeetingGroupProposals/Events · high confidence

Added domain events for subscription renewal payments

New domain events, SubscriptionRenewalPaymentCreatedDomainEvent and SubscriptionRenewalPaymentPaidDomainEvent, have been introduced to the Payments module. These events capture key lifecycle states for subscription renewal payments, enabling downstream processes to react to creation and payment status changes.

src/Modules/Payments/Domain/SubscriptionRenewalPayments/Events · high confidence

Added email notification for new meeting groups

A new command and handler have been introduced to automatically send an email to the creator when a new meeting group is created. The handler queries the database for the group's name and location, then uses the email sender to notify the creator.

src/Modules/Meetings/Application/MeetingGroups/SendMeetingGroupCreatedEmail · high confidence

Added endpoint to retrieve all countries

A new query and handler have been introduced to fetch a complete list of countries. Users can now retrieve all available countries via the GetAllCountriesQuery, which returns a list of CountryDto objects containing each country's code and name.

src/Modules/Meetings/Application/Countries · high confidence

Added endpoints to disable or enable meeting commenting

Users can now disable or enable commenting on meetings via new API endpoints. The controller exposes two PATCH routes: one to disable commenting and another to enable it, each requiring specific permissions (DisableMeetingCommenting and EnableMeetingCommenting respectively).

src/API/CompanyName.MyMeetings.API/Modules/Meetings/MeetingCommentingConfiguration · high confidence

Added execution context accessor and invalid command exception

The application layer now includes an IExecutionContextAccessor interface to expose the current user ID, correlation ID, and availability status, alongside a new InvalidCommandException class that carries a list of validation errors.

src/BuildingBlocks/Application · high confidence

Added inbox message processing infrastructure for the Payments module

The Payments module now includes the infrastructure components required to process inbox messages. This includes the \InboxMessageDto\ data transfer object, a \ProcessInboxCommand\ and its handler which queries the \payments.InboxMessages\ table for unprocessed messages, deserializes them, and publishes them via MediatR. A \ProcessInboxJob\ is also added to trigger this processing, likely on a recurring schedule.

src/Modules/Payments/Infrastructure/Configuration/Processing/Inbox · high confidence

Added infrastructure for tracking member comment likes

The application now supports a 'like' feature for meeting comments. This change introduces the database mapping and repository layer for the \MeetingMemberCommentLike\ entity, enabling the system to track which members have liked specific comments. The implementation includes an Entity Framework Core configuration defining the \meetings.MeetingMemberCommentLikes\ table structure and a repository that handles adding, retrieving, counting, and removing like records.

src/Modules/Meetings/Infrastructure/Domain/MeetingMemberCommentLikes · high confidence

Added integration event handling for meeting group proposals

The application layer now includes handlers for meeting group proposal events. A new integration event handler processes accepted proposals by scheduling the corresponding command, while a domain notification and its handler publish an integration event to the events bus when a proposal is created, ensuring external systems are notified of new proposals.

src/Modules/Meetings/Application/MeetingGroupProposals · high confidence

Added integration events for meetings module

New integration events have been introduced to expose key meetings module state changes to other parts of the system. Specifically, the system now publishes \MeetingAttendeeAddedIntegrationEvent\ to signal when an attendee is added to a meeting (including fee details), \MeetingGroupProposedIntegrationEvent\ to broadcast new meeting group proposals with location and user details, and \MemberCreatedIntegrationEvent\ to notify when a new member is created.

src/Modules/Meetings/IntegrationEvents · high confidence

Added member creation workflow via command and integration event handlers

The Meetings module now includes the application layer components for creating a new member. This includes the CreateMemberCommand and its handler, which persists member details to the repository, and a notification handler for member creation events. Additionally, a new integration event handler is introduced to listen for NewUserRegisteredIntegrationEvent, which triggers the member creation process by scheduling the corresponding command.

src/Modules/Meetings/Application/Members/CreateMember · medium confidence

Added query to retrieve all meeting groups

Introduced a new application-layer query, GetAllMeetingGroupsQuery, which fetches meeting group details (Id, Name, Description, LocationCountryCode, and LocationCity) from the database via a SQL query against the v\_MeetingGroups view. This enables clients to retrieve a list of all meeting groups.

src/Modules/Meetings/Application/MeetingGroups/GetAllMeetingGroups · high confidence

Added query to retrieve user permissions

A new query and handler have been added to the UserAccess module, allowing the system to fetch a list of a user's permissions by querying the v\_UserPermissions view. This introduces a new capability for retrieving user permission codes via the GetUserPermissionsQuery.

src/Modules/UserAccess/Application/Authorization/GetUserPermissions · high confidence

Added subscription creation confirmation email

A new command and handler have been introduced to automatically send a confirmation email to users when a subscription is successfully created. The system now utilizes an email sender to notify users that their subscription has been paid and activated.

src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail · high confidence

Added subscription creation workflow with email confirmation and integration events

The Payments module now handles the creation of subscriptions via a new command and handler that persist the subscription to the aggregate store. Upon successful creation, a notification triggers two side effects: an email confirmation is enqueued for the payer, and an integration event is published to the events bus to notify other systems about the subscription's expiration date.

src/Modules/Payments/Application/Subscriptions/CreateSubscription · high confidence

Added subscription payments query and projection

Users can now retrieve a list of subscription payments for a given payer. This is enabled by a new GetSubscriptionPayments query and handler that fetches payment details from the database, and a corresponding projector that updates the subscription payments table when domain events (such as initial or renewal payments being created or paid) are published.

src/Modules/Payments/Application/Subscriptions/GetSubscriptionPayments · high confidence

Added subscription renewal command and notification handling

Users can now renew their subscriptions through a new command handler that processes renewal requests and updates the subscription state. The system also sends an email confirmation to the payer after a successful renewal, and publishes an integration event to notify other services of the expiration date change.

src/Modules/Payments/Application/Subscriptions/RenewSubscription · high confidence

Added subscription renewal purchase capability

Users can now purchase a subscription renewal. This change introduces a new command and handler that allow a user to buy a renewal for an existing subscription, validating that the subscription exists before creating the renewal payment.

src/Modules/Payments/Application/Subscriptions/BuySubscriptionRenewal · high confidence

Added user registration and confirmation workflow

The Registrations module now supports a new user registration flow. Users can register a new account, which triggers an email with a confirmation link. Upon clicking the link, the registration is confirmed, which then triggers the creation of the actual user account. This includes the necessary domain models, command handlers, and infrastructure wiring to manage the registration lifecycle.

src/Modules/Registrations · high confidence

Administration module exposes endpoints for managing meeting group proposals

The Administration module now includes a new API for handling meeting group proposals. Users can retrieve a list of pending proposals via a GET request to /api/administration/meetingGroupProposals and approve a specific proposal using a PATCH request to /api/administration/meetingGroupProposals/{id}/accept. Both endpoints require the 'AcceptMeetingGroupProposal' permission.

src/API/CompanyName.MyMeetings.API/Modules/Administration · high confidence

Administration module infrastructure layer initialization

The Administration module's infrastructure layer has been initialized with a new \AdministrationContext\ for Entity Framework Core, a \MediatorModule\ for MediatR integration, and dedicated processing pipelines for internal commands, inbox messages, and outbox messages. The module also registers an \EventsBus\ to handle integration events and configures a Quartz-based scheduler to periodically process these queued messages.

src/Modules/Administration/Infrastructure · high confidence

Automated expiration of subscriptions and subscription payments

The Payments module now includes background commands to automatically expire subscriptions and subscription payments. The new ExpireSubscriptionsCommand queries the database for subscriptions past their expiration date and schedules individual expiration commands. Similarly, the ExpireSubscriptionPaymentsCommand identifies pending subscription payments that are about to expire and schedules their expiration. These recurring commands enable automatic lifecycle management for subscriptions and their associated payments.

src/Modules/Payments/Application/Subscriptions/ExpireSubscriptions · high confidence

Automated payer creation on user registration

The system now automatically creates a payer profile for a user when they register. This is handled by a new integration event handler that listens for the 'NewUserRegistered' event and schedules a command to create the payer, ensuring the payment module is initialized for every new user.

src/Modules/Payments/Application/Payers/CreatePayer · high confidence

Automated subscription expiration date updates for meeting groups

A new workflow now automatically updates the expiration date of member subscriptions and propagates this change to all associated meeting groups. When a member's subscription is updated (triggered by a payment integration event), the system schedules commands to update each relevant meeting group's expiration date, ensuring that all groups linked to the member's subscription are kept in sync.

src/Modules/Meetings/Application/MemberSubscriptions · high confidence

Domain events for meeting group lifecycle and membership changes

The Meetings module now exposes specific domain events to track key changes to meeting groups and their members. New events include MeetingGroupCreatedDomainEvent for group creation, NewMeetingGroupMemberJoinedDomainEvent for new members, and MeetingGroupMemberLeftGroupDomainEvent for departures. Additional events cover updates to general attributes (name, description, location) via MeetingGroupGeneralAttributesEditedDomainEvent, payment information updates via MeetingGroupPaymentInfoUpdatedDomainEvent, and attendee decision changes via MeetingAttendeeChangedDecisionDomainEvent and MeetingNotAttendeeChangedDecisionDomainEvent.

src/Modules/Meetings/Domain/MeetingGroups/Events · high confidence

Email notifications for new meeting groups

When a new meeting group is created, the system now automatically triggers an email notification. This is implemented by a new \MeetingGroupCreatedNotification\ class and a corresponding \MeetingGroupCreatedSendEmailHandler\ that schedules the email to be sent to the group creator.

src/Modules/Meetings/Application/MeetingGroups · high confidence

Initial database schema and permissions setup

The database initialization scripts now include a complete schema definition for the MyMeetings application, creating schemas and tables for administration, meetings, payments, users, and registrations. Additionally, the seed script populates default test users and defines a comprehensive set of permissions for the 'Member' and 'Administrator' roles, enabling the application's GUI to function with the correct access controls.

src/Database/CompanyName.MyMeetings.Database/Scripts · high confidence

Initial project scaffolding and documentation

The repository was initialized with core project files including a comprehensive .gitignore, a detailed README.md documenting the Modular Monolith with DDD architecture, an Azure Pipelines CI configuration, Nuke build scripts (build.sh, build.ps1, build.cmd) for cross-platform builds, a docker-compose.yml for local development with SQL Server, and a script to run integration tests against a Dockerized database.

(repo-wide) · high confidence

Initialize Payments module infrastructure and configuration

The Payments module's infrastructure layer has been initialized with a new configuration structure under src/Modules/Payments/Infrastructure/Configuration. This includes a custom Autofac constructor finder, assembly resolution helpers, and dedicated Autofac modules for authentication (resolving the current payer context), logging, database access, event bus integration, and outbox processing. The PaymentsStartup class now orchestrates the full dependency injection setup, including Quartz scheduler initialization and event projector execution, while the PaymentsModule exposes the public API for executing commands and queries via MediatR.

src/Modules/Payments/Infrastructure/Configuration · medium confidence

Introduce MeetingGroup domain model and business rules

The Meetings module now includes a new domain model for MeetingGroups, featuring a MeetingGroup aggregate root that manages group creation, member joining/leaving, and meeting organization. This includes a MeetingGroupRepository interface, value objects for location and member roles, and specific business rules to enforce that only active, paying groups can host meetings, that hosts must be group members, and that members cannot be added twice or leave if not currently active.

src/Modules/Meetings/Domain/MeetingGroups · high confidence

Introduce MeetingGroupProposal domain model and time abstraction

Added the MeetingGroupProposal aggregate root, its associated value objects (MeetingGroupProposalId, MeetingGroupProposalStatus), and a repository interface to support proposing new meeting groups. The domain enforces that a proposal can only be accepted once via a business rule, and introduces a SystemClock abstraction to decouple time-dependent logic from the system clock, facilitating testability.

src/Modules/Meetings/Domain/MeetingGroupProposals · high confidence

Introduce MemberSubscription domain model and repository interface

Added the core domain model for member subscriptions, including the \MemberSubscription\ entity, its value object \MemberSubscriptionId\, and the \IMemberSubscriptionRepository\ interface. The \MemberSubscription\ class manages subscription details and triggers a \MemberSubscriptionExpirationDateChangedDomainEvent\ when the expiration date is updated, enabling the system to track and react to changes in a member's subscription status.

src/Modules/Meetings/Domain/Members/MemberSubscriptions · high confidence

Introduce Price List Items domain model with configurable pricing strategies

The Payments module now includes a new PriceListItems domain layer, introducing the PriceList and PriceListItem aggregates to manage country-specific subscription pricing. PriceList acts as a container that delegates price lookups to pluggable IPricingStrategy implementations, such as DirectValueFromPriceListPricingStrategy and DiscountedValueFromPriceListPricingStrategy. This change enables the system to calculate subscription costs based on country, period, and category, supporting both direct and discounted pricing models.

src/Modules/Payments/Domain/PriceListItems · high confidence

Introduce SubscriptionPayment domain model

Added new domain classes for subscription payments, including the SubscriptionPayment aggregate root, its ID, a snapshot for state representation, and a status value object. This introduces the core data structures for managing subscription payment lifecycles, supporting states such as waiting for payment, paid, and expired.

src/Modules/Payments/Domain/SubscriptionPayments · high confidence

Introduce database persistence for Meeting and MeetingGroup aggregates

The Meetings module now includes Entity Framework Core configuration and repository implementations for the Meeting and MeetingGroup aggregates. This adds the necessary infrastructure to persist meeting details, attendee status, and group membership to the database, enabling the application to store and retrieve meeting data.

src/Modules/Meetings/Infrastructure/Domain/Meetings · high confidence

Introduce domain model and events for the Meetings module

The Meetings module now includes a complete domain model for managing meetings, including the \Meeting\ aggregate root, \MeetingAttendee\, \MeetingNotAttendee\, and \MeetingWaitlistMember\ entities. These classes define the core state and behaviors for meeting creation, attendance, and waitlisting. The change also introduces a set of domain events (e.g., \MeetingCreatedDomainEvent\, \MeetingAttendeeAddedDomainEvent\) to track state changes within the system. Additionally, value objects such as \MoneyValue\, \MeetingLimits\, and \Term\ are added to support the domain logic.

src/Modules/Meetings/Domain/Meetings · high confidence

Introduce domain models and events for meeting fees and payments

Added new domain entities and events for the Payments module, including \MeetingFee\ and \MeetingFeePayment\ aggregates with their respective IDs, snapshots, and status value objects. This introduces domain events for creating, paying, expiring, and canceling meeting fees and payments, enabling the tracking of fee lifecycle states (WaitingForPayment, Paid, Expired, Canceled).

src/Modules/Payments/Domain/MeetingFees · high confidence

Introduce domain models and events for meeting group proposals and members

The Administration module now includes domain models for managing meeting group proposals and members. This adds the \MeetingGroupProposal\ aggregate root, which supports verification workflows including accepting or rejecting proposals with associated domain and integration events. Additionally, a \Member\ entity and its repository interface are introduced to track member details and creation events.

src/Modules/Administration/Domain · high confidence

Introduce domain models and interfaces for the Meetings module

The Meetings module now includes core domain definitions: the Member aggregate root with its associated MemberId value object, along with supporting interfaces (IMemberContext, IMemberRepository) and data classes (MeetingGroupMemberData). These changes establish the foundational structure for managing meeting participants and their group associations within the domain layer.

src/Modules/Meetings/Domain/Members · high confidence

Introduce email sending abstraction

Added a new EmailMessage struct and an IEmailSender interface in the application building blocks, providing a structured way to represent email content and define a contract for sending emails.

src/BuildingBlocks/Application/Emails · high confidence

Introduce endpoints for managing meeting fee payments

Users can now initiate and confirm payments for meeting fees through new API endpoints. The system exposes a POST to /api/payments/meetingFeePayments to create a payment and a PUT to /api/payments/meetingFeePayments/{id}/purchased to mark a payment as paid, both requiring the PaymentsPermissions.RegisterPayment permission.

src/API/CompanyName.MyMeetings.API/Modules/Payments/MeetingFees · high confidence

Introduce in-memory event bus for integration events

Added a new in-memory implementation of the event bus infrastructure, including the IEventsBus interface, IIntegrationEventHandler, and the InMemoryEventBus and InMemoryEventBusClient classes. This provides a lightweight, synchronous event publishing and subscription mechanism for integration events, supporting the MediatR INotification pattern with unique IDs and timestamps.

src/BuildingBlocks/Infrastructure/EventBus · high confidence

Introduce internal command mapping infrastructure

A new internal commands subsystem has been added to the infrastructure layer, providing a mechanism to map between command types and their string representations. This includes an \InternalCommand\ model class for storing command data, an \IInternalCommandsMapper\ interface, and a concrete \InternalCommandsMapper\ implementation that uses a bidirectional dictionary to resolve type-to-name and name-to-type mappings.

src/BuildingBlocks/Infrastructure/InternalCommands · high confidence

Introduce meeting comment and like domain models

Added domain models and business rules for meeting comments and comment likes. Users can now add, edit, remove, and reply to comments on meetings, with enforcement of permissions (e.g., only the author or group organizer can remove a comment). The system also supports liking and unliking comments, with rules preventing duplicate likes from the same member. These changes introduce new domain events for comment lifecycle and like status changes.

src/Modules/Meetings/Domain/MeetingComments · high confidence

Introduce meeting commenting configuration domain model

Added the domain model for managing whether commenting is enabled or disabled for a meeting. This includes the \MeetingCommentingConfiguration\ aggregate root, its associated ID and repository interface, and three domain events (\Created\, \Enabled\, \Disabled\). Business rules enforce that only the meeting group organizer can enable or disable commenting.

src/Modules/Meetings/Domain/MeetingCommentingConfigurations · high confidence

Introduce meeting module configuration and permissions

The Meetings module is now registered in the application's dependency injection container via a new Autofac module, and a comprehensive set of permissions for meeting and comment operations has been defined, enabling access control for features like creating meetings, managing attendees, and handling comments.

src/API/CompanyName.MyMeetings.API/Modules/Meetings · medium confidence

Introduce member data transfer and query helpers for the Meetings module

The Meetings module now includes application-layer support for retrieving member information. A new MemberContext class provides access to the current user's ID via an execution context accessor. A MemberDto data transfer object exposes member details (Id, Name, Email, Login). Additionally, a MembersQueryHelper class implements SQL queries using Dapper to fetch individual member data and meeting group membership status from the database views.

src/Modules/Meetings/Application/Members · high confidence

Introduce outbox message infrastructure and domain event abstractions

The application layer now includes a new outbox implementation, featuring the \OutboxMessage\ class and \IOutbox\ interface to manage message persistence and saving. Additionally, new abstractions for domain events have been added, including \IDomainEventNotification\ and \DomainNotificationBase\, alongside a new \ISqlConnectionFactory\ interface for database connection management.

src/BuildingBlocks/Application/Outbox · high confidence

Introduce outbox pattern for reliable event publishing

Added OutboxAccessor and OutboxMessageEntityTypeConfiguration to the Meetings module infrastructure. The OutboxAccessor implements the IOutbox interface to capture outgoing messages, while the entity configuration maps OutboxMessage to the 'meetings.OutboxMessages' table. This enables reliable event publishing by storing messages locally before they are dispatched, ensuring at-least-once delivery semantics.

src/Modules/Meetings/Infrastructure/Outbox, src/Modules/UserAccess/Infrastructure/Outbox · high confidence

Introduce subscription renewal payment tracking and validation

A new SubscriptionRenewalPayment aggregate has been added to the payments module, enabling the system to track and manage payments for subscription renewals. This includes a domain model that validates whether the price offer matches the price in the price list, and tracks the payment status (WaitingForPayment, Paid, Expired). This change integrates price list items with subscription workflows, ensuring that renewal payments are correctly associated with the corresponding subscription and period.

src/Modules/Payments/Domain/SubscriptionRenewalPayments · medium confidence

Introduce user authentication capability

Users can now authenticate by providing their login and password. This change introduces the application-layer components for the authentication flow, including the command and handler that query the database for user details, verify the password hash, and return an authentication result containing user claims.

src/Modules/UserAccess/Application/Authentication · high confidence

Introduces Payer and User domain models with domain events

The Payments module now includes new domain models for Payer and User, each with their own ID types (PayerId, UserId) and context interfaces (IPayerContext, IUserContext). A PayerCreatedDomainEvent is introduced to capture payer creation details, and the Payer aggregate root uses event-sourcing-style logic to apply state from this event. These changes lay the groundwork for tracking payer and user identities within the payments domain.

src/Modules/Payments/Domain/Payers · high confidence

Introduces application-layer contracts for commands and queries

The Administration module now exposes a set of application-layer contracts that define how commands and queries are structured and executed. New interfaces (ICommand, ICommand\<TResult\>, IQuery, IRecurringCommand) and base classes (CommandBase, QueryBase) provide a consistent way to handle requests with or without results, including support for recurring commands. The IAdministrationModule interface defines methods for executing commands and queries, enabling the application layer to interact with the MediatR-based command/query pipeline.

src/Modules/Administration/Application/Contracts · medium confidence

Introduces application-layer contracts for the Meetings module

The Meetings module now includes a new set of application contracts that define how commands and queries are structured and executed. Specifically, it adds interfaces for ICommand, ICommand\<TResult\>, IQuery, and IRecurringCommand, along with base classes CommandBase and QueryBase that provide a consistent Id property. These contracts enable the module to execute commands and queries through a unified interface, supporting both standard and recurring command patterns.

src/Modules/Meetings/Application/Contracts · high confidence

Introduces base classes and interfaces for command and query patterns in the Payments module

The Payments module now includes foundational contracts for the application layer, specifically defining base classes (CommandBase, QueryBase) and interfaces (ICommand, IQuery, IRecurringCommand, IPaymentsModule) that standardize how commands and queries are structured and executed within the module. This provides a consistent mechanism for executing commands and queries via the IPaymentsModule interface, supporting both generic and non-generic command/query patterns.

src/Modules/Payments/Application/Contracts · high confidence

Introduces command and query handler interfaces for the UserAccess module

The UserAccess module now defines core abstractions for its application layer. New interfaces for command and query handlers (ICommandHandler, IQueryHandler) and their corresponding base classes (InternalCommandBase) have been added to the Configuration/Commands and Configuration/Queries directories. These changes establish the structural foundation for handling commands and queries within the module, aligning with the broader refactoring of the UserAccess module's configuration code.

src/Modules/UserAccess/Application/Configuration · medium confidence

Introduces core domain model for user access

The UserAccess module now includes the foundational domain classes for user management. This adds the User entity with support for Administrator and Member roles, a corresponding UserId value object, and a UserCreatedDomainEvent to track creation. An IUserRepository interface is also introduced to define data access contracts for the new user aggregate.

src/Modules/UserAccess/Domain · high confidence

Introduces foundational domain building blocks

The domain layer now includes core abstractions for domain-driven design: an abstract Entity class that manages domain events and business rule validation, a ValueObject base class with deep equality and hashing, and supporting interfaces and exceptions (IBusinessRule, IDomainEvent, BusinessRuleValidationException). These classes provide the structural foundation for implementing domain models and enforcing business constraints.

src/BuildingBlocks/Domain · high confidence

Introduces foundational domain primitives and infrastructure for the Payments module

The Payments module now includes core domain building blocks: an abstract AggregateRoot with event sourcing support, a generic AggregateId, and an IAggregateStore interface for persistence. Additionally, a MoneyValue value object enforces business rules, including a new constraint that prevents negative monetary values and ensures currency consistency during subtraction.

src/Modules/Payments/Domain/SeedWork · high confidence

Introduces new application-layer contracts for the User Access module

The User Access module now includes a set of new interfaces and base classes in the application layer to support command and query patterns. Specifically, \ICommand\, \ICommand\<TResult\>\, \IQuery\<TResult\>\, and \IRecurringCommand\ interfaces are added, along with corresponding \CommandBase\ and \QueryBase\ abstract classes that provide a consistent \Id\ property. Additionally, \IUserAccessModule\ defines the execution methods for commands and queries, while \CustomClaimTypes\ and \Roles\ classes define constant values for claims and role names.

src/Modules/UserAccess/Application/Contracts · high confidence

New API endpoints for meeting management

The Meetings module now exposes a comprehensive set of RESTful endpoints for managing meetings, including creating, editing, and retrieving meeting details, as well as managing attendees, waitlists, and host roles. This includes new request models for operations such as adding or removing attendees, setting attendee or host roles, and updating meeting attributes, all wired through the new MeetingsController.

src/API/CompanyName.MyMeetings.API/Modules/Meetings/Meetings · high confidence

New BuySubscription command and handler for subscription purchases

Users can now initiate the purchase of a subscription through a new BuySubscription command. This change introduces the command class and its handler, which validates the subscription type, country code, value, and currency, then creates a new SubscriptionPayment aggregate via the price list.

src/Modules/Payments/Application/Subscriptions/BuySubscription · high confidence

New Meeting Groups API endpoints

The API now exposes a new set of endpoints for managing meeting groups, allowing users to retrieve, edit, join, and leave meeting groups. The \MeetingGroupsController\ introduces routes for listing authenticated member groups, fetching group details, updating group attributes (name, description, location), and managing group membership (join/leave).

src/API/CompanyName.MyMeetings.API/Modules/Meetings/MeetingGroups · high confidence

New UserAccess API endpoints for user registration and profile access

The UserAccess module now exposes several new API endpoints: a GET endpoint at /api/userAccess/authenticatedUser to retrieve the current user's profile, a GET endpoint at /api/userAccess/authenticatedUser/permissions to fetch user permissions for the GUI, a GET endpoint at /api/userAccess/emails to retrieve all emails, and POST/PATCH endpoints at /userAccess/UserRegistrations for registering new users and confirming their registration. These changes introduce new controller classes (AuthenticatedUserController, EmailsController, UserRegistrationsController) and request models (RegisterNewUserRequest) that interact with the underlying application modules.

src/API/CompanyName.MyMeetings.API/Modules/UserAccess · medium confidence

New command and query handler interfaces for the Administration module

The Administration module's application layer now includes new interfaces for handling commands and queries, specifically ICommandHandler, ICommandsScheduler, InternalCommandBase, and IQueryHandler. These interfaces define the structure for processing commands and queries within the module, likely supporting a more modular or testable architecture for command and query handling.

src/Modules/Administration/Application/Configuration, src/Modules/Meetings/Application/Configuration, src/Modules/Payments/Application/Configuration/Commands · medium confidence

New domain event dispatching infrastructure

Added a new domain event dispatching system in the Building Blocks infrastructure layer. This includes the \DomainEventsDispatcher\ which publishes MediatR notifications and serializes events into an outbox for reliable delivery, a \DomainEventsAccessor\ to retrieve and clear pending domain events from the DbContext, and a \DomainNotificationsMapper\ to map event types to names. Additionally, a \UnitOfWorkCommandHandlerDecorator\ was introduced to automatically commit database transactions after command handlers execute.

src/BuildingBlocks/Infrastructure/DomainEventsDispatching · high confidence

New domain events for PriceListItem lifecycle

The Payments module now exposes specific domain events to track PriceListItem state changes. New event classes have been added to the domain layer: PriceListItemCreatedDomainEvent, PriceListItemActivatedDomainEvent, PriceListItemDeactivatedDomainEvent, and PriceListItemAttributesChangedDomainEvent. These events capture details such as price, currency, and item status, enabling subscribers to react to these specific lifecycle transitions.

src/Modules/Payments/Domain/PriceListItems/Events · high confidence

New domain events for subscription lifecycle

The Payments module now introduces three new domain events to track subscription status changes: \SubscriptionCreatedDomainEvent\ (carrying payment, subscription, and payer details), \SubscriptionExpiredDomainEvent\ (carrying subscription ID and status), and \SubscriptionRenewedDomainEvent\ (carrying expiration date, payer ID, period code, and status). These events enable downstream systems to react to new, expired, and renewed subscription states.

src/Modules/Payments/Domain/Subscriptions/Events · high confidence

New domain events for subscription payment lifecycle

The Payments module introduces three new domain events to track the state of subscription payments: SubscriptionPaymentCreatedDomainEvent, SubscriptionPaymentPaidDomainEvent, and SubscriptionPaymentExpiredDomainEvent. These events expose key details such as the payment ID, payer ID, subscription period code, country code, status, value, and currency, enabling downstream systems to react to the creation, successful payment, or expiration of a subscription payment.

src/Modules/Payments/Domain/SubscriptionPayments/Events · high confidence

New endpoints for purchasing and renewing subscriptions

The API now exposes new endpoints for subscription management. Users can purchase a new subscription via a POST to /api/payments/subscriptions, providing subscription type, country, value, and currency. Additionally, users can renew an existing subscription via a POST to /api/payments/subscriptions/{subscriptionId}/renewals. A separate endpoint at /api/payments/subscriptionPayments allows users to register a payment for a subscription using a payment ID.

src/API/CompanyName.MyMeetings.API/Modules/Payments/Subscriptions · high confidence

New integration events for meeting fees and subscription updates

The Payments module now exposes two new integration events: MeetingFeePaid, which carries the payer and meeting identifiers, and SubscriptionExpirationDateChanged, which carries the payer and new expiration date. These events enable downstream systems to react to fee payments and subscription status changes.

src/Modules/Payments/IntegrationEvents · high confidence

New payment endpoints for subscription renewals and price list management

The Payments module now exposes new API endpoints for managing subscription renewals and price list items. Users can confirm renewal payments via a dedicated controller at /api/payments/subscriptionRenewals, and the system enforces specific permissions for actions like buying or renewing subscriptions, creating or activating price list items, and retrieving subscription details. The module is also registered in the application's dependency injection container.

src/API/CompanyName.MyMeetings.API/Modules/Payments · high confidence

New queries to retrieve meeting group proposals

Added application-layer queries to fetch meeting group proposals: an administrative view for all proposals, a paginated list for general access, and a member-specific list filtered by the current user. These new query handlers expose proposal data via SQL views, enabling the UI to display proposal details such as name, location, description, and status.

src/Modules/Administration/Application/MeetingGroupProposals/GetMeetingGroupProposals, src/Modules/Meetings/Application/MeetingGroupProposals/GetAllMeetingGroupProposals, src/Modules/Meetings/Application/MeetingGroupProposals/GetMemberMeetingGroupProposals · high confidence

Payments module subscribes to and processes integration events

The Payments module now registers an Autofac module that configures the IEventsBus dependency, defaulting to an InMemoryEventBus client. Additionally, the module subscribes to specific integration events (MeetingGroupProposalAccepted, NewUserRegistered, and MeetingAttendeeAdded) and processes them by inserting records into the payments.InboxMessages database table.

src/Modules/Payments/Infrastructure/Configuration/EventsBus · high confidence

Scheduled jobs for expiring subscriptions and payments

The Payments module now includes Quartz-based scheduled jobs to automatically expire subscriptions and subscription payments. New files \ExpireSubscriptionPaymentsJob\ and \ExpireSubscriptionsJob\ are registered via \QuartzModule\ and configured in \QuartzStartup\ to run on a cron schedule, ensuring these expiration processes are handled automatically by the background scheduler.

src/Modules/Payments/Infrastructure/Configuration/Quartz · high confidence

Send subscription renewal confirmation email

Users will now receive an email notification confirming that their subscription has been successfully renewed. This new command and handler in the Payments module trigger an email via the existing email service, ensuring customers are informed about their active subscription status.

src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail · medium confidence

Architecture

Centralized infrastructure configuration for the Meetings module

The Meetings module's infrastructure configuration has been refactored into a dedicated \Configuration\ directory, introducing a structured composition root. This includes an \AllConstructorFinder\ for dependency injection, an \Assemblies\ helper, and specialized Autofac modules for authentication, data access, email, event bus, logging, and mediation. The change also introduces a \Processing\ subsystem that handles recurring background tasks, including an inbox processor for incoming integration events, an internal command scheduler with retry logic, and an outbox processor for domain events, all orchestrated by a central \MeetingsStartup\ class.

src/Modules/Meetings/Infrastructure/Configuration · high confidence

UserAccess module infrastructure configuration and processing pipeline

The UserAccess module's infrastructure configuration has been reorganized into the \src/Modules/UserAccess/Infrastructure/Configuration\ directory, introducing a structured pipeline for command processing, event handling, and dependency injection. This includes a new Mediator module for command and notification handling, along with dedicated modules for data access, email, event bus, and logging. A key addition is the \Processing\ subdirectory, which implements a recurring command scheduler for handling internal commands, inbox/outbox message processing, and domain event dispatching. The \AllConstructorFinder\ utility and \Assemblies\ helper are introduced to support Autofac's reflection-based registration. This change provides a more modular and maintainable foundation for the UserAccess module's internal operations.

src/Modules/UserAccess/Infrastructure/Configuration · high confidence

Behavioural changes

Accepting a meeting group proposal now automatically creates a new meeting group

When a user accepts a meeting group proposal, the system now automatically schedules the creation of a new meeting group. This is implemented by a new command handler that processes the acceptance and triggers a background command to create the associated group, ensuring the workflow progresses without manual intervention.

src/Modules/Meetings/Application/MeetingGroupProposals/AcceptMeetingGroupProposal · high confidence

Add command to mark subscription payments as paid

Users can now have a subscription payment marked as paid, which triggers a notification that schedules the creation of a new subscription. This is implemented via a new command, handler, and notification flow within the Payments module.

src/Modules/Payments/Application/Subscriptions/MarkSubscriptionPaymentAsPaid · high confidence

Add database project and country seed data

The database project is now built using MSBuild (sqlproj), organizing all database objects into a structured directory layout (Structure/). A new seed script (0001\_SeedCountries.sql) populates the countries table with a comprehensive list of countries and their ISO codes, enabling country selection features in the application.

src/Database/CompanyName.MyMeetings.Database · high confidence

Add query to retrieve authenticated member's meeting groups

A new query handler and associated DTOs have been added to fetch the list of meeting groups for the authenticated member. The implementation queries the 'meetings.v\_MemberMeetingGroups' view, filtering by the current user's ID and active status, returning group details such as name, description, location, and role code.

src/Modules/Meetings/Application/MeetingGroups/GetAuthenticationMemberMeetingGroups · high confidence

Add subscription details retrieval and projection

Users can now retrieve their authenticated subscription details via a new query handler that queries the database for the current payer's subscription status, period, and expiration date. Additionally, a new projector handles domain events to update or insert subscription details in the database, ensuring the stored state reflects subscription creation, renewal, and expiration events.

src/Modules/Payments/Application/Subscriptions/GetSubscriptionDetails · high confidence

Add validation rules for subscription pricing

Two new business rules were added to the Payments module to enforce subscription pricing integrity. The first, PriceForSubscriptionMustBeDefinedRule, ensures that a price is defined for a specific country, category, and subscription period. The second, PriceOfferMustMatchPriceInPriceListRule, validates that a price offer matches the price listed in the price list.

src/Modules/Payments/Domain/SubscriptionPayments/Rules · high confidence

Added query to retrieve payer details

A new query and handler have been added to the Payments module, allowing the system to fetch a payer's details (ID, login, email, name, and contact information) via a SQL query. This introduces a new way to access payer data within the application layer.

src/Modules/Payments/Application/Payers/GetPayer · high confidence

Adopts Nuke build tool for automated build and test workflows

The project has migrated its build system to Nuke, a .NET-based build automation tool. This change introduces a new \build\ directory containing C\# scripts that define targets for restoring, compiling, and running unit, architecture, and integration tests. The build process now includes automated setup of a SQL Server container, database migration execution, and environment variable configuration for integration tests, streamlining the local and CI development experience.

build · high confidence

Automatic member profile creation for new users

A new integration event handler has been added to automatically create a member profile when a new user registers. This handler listens for the NewUserRegisteredIntegrationEvent and schedules a command to create the corresponding member record, ensuring that new users are immediately associated with the system's internal member structure.

src/Modules/Administration/Application/Members · high confidence

Centralize Mediator configuration in the Payments module

The MediatorModule class has been added to the Payments module's infrastructure layer to centralize the registration of MediatR handlers, validators, and pipeline behaviors. This change consolidates the dependency injection setup for the Mediator pattern, ensuring that all request handlers, notification handlers, and validation logic for the Payments module are registered in a single, maintainable location.

src/Modules/Payments/Infrastructure/Configuration/Mediation · high confidence

Centralized command processing with validation, logging, and unit-of-work management

The Payments module now routes all commands through a new processing pipeline in the infrastructure layer. This pipeline enforces input validation, wraps command execution in a unit of work (ensuring database transactions and outbox consistency), and adds structured logging with correlation IDs. Internal commands are tracked for processing status, and domain events are dispatched as part of the commit process.

src/Modules/Payments/Infrastructure/Configuration/Processing · high confidence

Database schema updated with new tables and views for meetings, comments, and registrations

The database schema has been updated to support new features for meeting management and user interactions. A new \MeetingMemberCommentLikes\ table and a \LikesCount\ column on \MeetingComments\ enable users to like comments. The \MeetingCommentingConfigurations\ table allows controlling whether commenting is enabled for specific meetings. Additionally, missing tables for the \registrations\ module (OutboxMessages, InternalCommands, InboxMessages) have been added to support the registration process. Several database views have also been introduced to facilitate data retrieval for meetings, attendees, and member groups.

src/Database/CompanyName.MyMeetings.Database/Scripts/Migrations · high confidence

Email configuration for the Payments module

The Payments module now includes an Autofac module that registers the email sender, allowing the module to send emails using the configured email settings.

src/Modules/Payments/Infrastructure/Configuration/Email · high confidence

Emails are now persisted in the database

The email sending mechanism has been updated so that all outgoing emails are saved to the database before being processed. This ensures that email content is retained for audit or debugging purposes, and the system logs each sent message with details like sender, recipient, subject, and content.

src/BuildingBlocks/Infrastructure/Emails · high confidence

Enforce meeting attendance and limit constraints via new domain rules

The Meetings module now enforces several new business rules to validate meeting state and participant limits. Attendees can only be added during the RSVP term, and members cannot be added as attendees or waitlist participants more than once. The system also prevents changing attendee or guest limits to values that are negative, smaller than active attendees, or less than or equal to the respective other limit. Additionally, meetings cannot be modified after they have started, and only active attendees or organizers can perform specific role changes or removals, ensuring data integrity and correct workflow progression.

src/Modules/Meetings/Domain/Meetings/Rules · high confidence

Enforces endpoint authorization via startup validation

The API now includes a startup-time check that scans all controller action methods and throws an error if any public endpoint lacks a HasPermissionAttribute or NoPermissionRequiredAttribute. This ensures that every API endpoint is explicitly authorized or marked as public, preventing accidental exposure of unprotected routes.

src/API/CompanyName.MyMeetings.API/Configuration/Authorization · high confidence

Extracted payer email retrieval into a dedicated provider class

The logic for retrieving a payer's email address has been extracted from the existing GetPayerEmail handler into a new static class named PayerEmailProvider. This provider encapsulates the SQL query and Dapper execution, meaning the application now uses this dedicated component to fetch payer emails from the database.

src/Modules/Payments/Application/Payers/GetPayerEmail · high confidence

Introduce UserAccessContext and Mediator-based command/query execution in the UserAccess module

The UserAccess module now includes a new EF Core DbContext (UserAccessContext) that maps Users, OutboxMessages, and InternalCommands, and a new UserAccessModule that routes commands and queries through MediatR via an Autofac composition root. This change shifts the module's infrastructure to use a Mediator pattern for command/query execution, replacing any previous direct execution paths.

src/Modules/UserAccess/Infrastructure · medium confidence

Introduce database mapping and persistence for meeting comments

The system now supports persisting meeting comments. A new entity type configuration maps the \MeetingComment\ domain model to the \meetings.MeetingComments\ table, defining columns for the comment text, author, reply chain, removal status, and timestamps. A corresponding repository implements the \IMeetingCommentRepository\ interface, providing methods to add new comments and retrieve them by ID.

src/Modules/Meetings/Infrastructure/Domain/MeetingComments · high confidence

Introduce database mapping and repository implementations for the Meetings module

Added Entity Framework Core entity type configurations and repository implementations for the 'Members' and 'MemberSubscriptions' domain aggregates. This includes the 'Members' and 'MemberSubscriptions' database table mappings, as well as the 'MemberRepository' and 'MemberSubscriptionRepository' classes that handle data access for these entities.

src/Modules/Meetings/Infrastructure/Domain/Members · high confidence

Introduce event-sourced aggregate store for the Payments module

The Payments module now uses an event-sourced architecture backed by a SQL-based stream store. This introduces a new \SqlStreamAggregateStore\ that persists domain events to a stream, enabling the loading and saving of aggregates via event replay. The change includes a domain event type mapping to link event names to their corresponding domain event classes, a checkpoint store to track subscription positions for event processing, and an outbox accessor to reliably publish domain events. Users benefit from improved consistency and auditability of payment-related events, such as subscription, price list, and meeting fee changes, which are now tracked and replayed through the new infrastructure.

src/Modules/Payments/Infrastructure/AggregateStore · medium confidence

Introduce structured error handling and request correlation for the API

The API now includes a CorrelationMiddleware to generate and propagate a CorrelationId for every request, improving traceability. Additionally, the application registers custom ProblemDetails mappings for BusinessRuleValidationException and InvalidCommandException, ensuring that validation failures return standardized HTTP 409 Conflict and 400 Bad Request responses respectively, rather than generic error pages.

src/API/CompanyName.MyMeetings.API · high confidence

Introduce subscription lifecycle management

The Payments module now supports managing subscription lifecycles. Users can create new subscriptions, renew existing ones, and handle expiration. The system tracks subscription periods (monthly or half-yearly) and statuses (active or expired), automatically calculating expiration dates based on the selected period.

src/Modules/Payments/Domain/Subscriptions · medium confidence

New Price List Items and Payer endpoints

The Payments module now exposes REST endpoints for managing price list items and retrieving authenticated payer subscription details. Users can create, retrieve, update, activate, and deactivate price list items via the new PriceListItemsController, while the PayersController provides an endpoint to fetch the current authenticated user's subscription status.

src/API/CompanyName.MyMeetings.API/Modules/Payments/PriceListItems · medium confidence

Payments module introduces projection infrastructure for event handling

The Payments module now includes a new projection system to handle domain events. This change adds an IProjector interface and a ProjectorBase abstract class within the Application/Configuration/Projections directory, establishing the foundation for processing events into the outbox.

src/Modules/Payments/Application/Configuration/Projections · medium confidence

Payments module registers data access and event sourcing infrastructure

The Payments module now explicitly registers its data access and event sourcing infrastructure via Autofac. This includes configuring the SQL connection factory, the MS SQL Stream Store for event streams, the SQL aggregate store, and the SQL-based checkpoint store. Additionally, it registers all types ending in 'Projector' from the application layer and 'Repository' types from the infrastructure layer, along with a singleton SubscriptionsManager.

src/Modules/Payments/Infrastructure/Configuration/DataAccess · medium confidence

User access domain configuration and repository moved to infrastructure

The UserAccess module's domain configuration and repository implementation have been moved to the Infrastructure layer. Specifically, the \UserEntityTypeConfiguration\ class now defines how the \User\ entity maps to the database schema, including table names, column mappings, and the \UserRoles\ relationship. Additionally, the \UserRepository\ class has been added to the infrastructure layer to handle the persistence of \User\ entities via the \UserAccessContext\.

src/Modules/UserAccess/Infrastructure/Domain · high confidence

Test coverage

Add architecture tests for the Payments domain; Add architecture tests for the Payments module application layer; Added architectural tests for the Meetings module's application layer; Added architecture and integration tests for module isolation and end-to-end workflows; Added architecture test base class for the Administration module; Added architecture tests for the Meetings module; Added architecture tests for the Meetings module's domain layer; Added architecture tests for the Payments module's seed work; Added architecture tests for the UserAccess application layer; Added assembly-level configuration for integration tests; Added integration test for user creation; Added integration test helper for environment variables; Added integration test infrastructure for the Payments module; Added integration tests for Meeting Group Proposals; Added integration tests for MeetingGroupProposal functionality; Added integration tests for creating new meeting groups; Added integration tests for meeting comment likes and country seeding; Added integration tests for meeting comment operations; Added integration tests for meeting commenting configuration; Added integration tests for meeting creation; Added integration tests for subscription lifecycle and payments; Added integration tests for the Administration module's member creation flow; Added integration tests for the Payers module; Added test assembly configuration for integration tests; Added test helper utilities for domain events and rule validation; Added test infrastructure for UserAccess integration tests; Added test utilities for validating domain events and business rules; Added unit tests and test helpers for the Payments module; Added unit tests for Administration domain models; Added unit tests for PagedQueryHelper; Added unit tests for PriceListItem domain logic; Added unit tests for subscription lifecycle and date calculations; Added unit tests for subscription payment flows; Added unit tests for the Meetings module domain logic.

Dependencies

Upgrade to .NET 8 and modernize build infrastructure

The project has been upgraded to .NET 8.0, with the build system now utilizing Nuke for the build script and MSBuild.Sdk.SqlProj for database projects. This change introduces a centralized package management approach via Directory.Packages.props, updating key libraries such as Autofac, MediatR, and Microsoft.EntityFrameworkCore to their latest compatible versions, while also adding explicit references for IdentityServer4 and System.Data.SqlClient across the solution.

(dependencies) · medium confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 64 → 55 (-8.9)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 58 → 47 (-11.4)
  • Architecture 87 → 87 (+0.3)
  • Maturity 68 → 68 (+0.0)
  • Readiness 67 → 63 (-3.8)
  • Security 76 → 51 (-25.1)
  • Domain Modelling 65 → 90 (+24.3)
  • Event-Driven 100 → 100 (+0.0)
  • Event Sourcing 84 (new)

Resolved (35)

  • Build did not complete in the analyzer
  • Context is a duplicate title and the decision restates the architecture name with no rationale; consequences are boilerplate list (single-process monolith, autonomy, Bounded Contexts, tactical patterns) without trade-offs (docs/architecture-decision-log/0002-use_modular-monolith-system-architecture.md)
  • Context is thin and the body only states that ADRs are created for advanced monolith projects without explaining why or what problems they solve; consequences mention recording old decisions but do not state whether new ones must be recorded on a regular basis (docs/architecture-decision-log/0001-record-architecture-decisions.md)
  • Decision "Solution 1." and consequences are both present but the Context section only states one client (FrontEnd SPA) without explaining why an API host is needed or what alternatives were considered (docs/architecture-decision-log/0005-create-one-rest-api-module.md)
  • Duplicated block (10 lines × 2) (src/Modules/UserAccess/Infrastructure/Configuration/Quartz/QuartzStartup.cs)
  • Duplicated block (11 lines × 2) (src/Modules/Meetings/Infrastructure/Configuration/Quartz/QuartzStartup.cs)
  • Duplicated block (12 lines × 2) (src/Modules/Meetings/Infrastructure/Configuration/Processing/Outbox/OutboxModule.cs)
  • Duplicated block (12 lines × 2) (src/Modules/UserAccess/Infrastructure/Configuration/Processing/Outbox/OutboxModule.cs)
  • Duplicated block (13 lines × 5) (src/Modules/Meetings/Infrastructure/Configuration/Mediation/MediatorModule.cs)
  • Duplicated block (14 lines × 2) (src/Modules/UserAccess/Application/Authentication/Authenticate/PasswordManager.cs)
  • Duplicated block (14 lines × 4) (src/Modules/Meetings/Infrastructure/Configuration/Processing/ProcessingModule.cs)
  • Duplicated block (16 lines × 2) (src/Modules/UserAccess/Application/Authentication/Authenticate/PasswordManager.cs)
  • Duplicated block (16 lines × 5) (src/Modules/Meetings/Infrastructure/Configuration/Quartz/SerilogLogProvider.cs)
  • Duplicated block (19 lines × 2) (src/Modules/UserAccess/Application/Authentication/Authenticate/PasswordManager.cs)
  • Duplicated block (19 lines × 5) (src/Modules/Meetings/Infrastructure/Configuration/Processing/LoggingCommandHandlerDecorator.cs)
  • Duplicated block (19 lines × 5) (src/Modules/Meetings/Infrastructure/Configuration/Processing/LoggingCommandHandlerWithResultDecorator.cs)
  • Duplicated block (19 lines × 5) (src/Modules/Meetings/Infrastructure/Configuration/Processing/Outbox/OutboxModule.cs)
  • Duplicated block (27 lines × 5) (src/Modules/Meetings/Infrastructure/Configuration/Mediation/MediatorModule.cs)
  • Duplicated block (6 lines × 2) (src/Modules/Meetings/Infrastructure/Configuration/Quartz/QuartzStartup.cs)
  • Duplicated block (7 lines × 2) (src/Modules/UserAccess/Infrastructure/Configuration/Quartz/QuartzStartup.cs)
  • …and 15 more

New (193)

  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • AnalyzerSeverityNone (src/.editorconfig)
  • CommentedOutCode (src/Modules/Registrations/Tests/UnitTests/UserRegistrations/UserRegistrationTests.cs)
  • CommentedOutCode (src/Modules/Registrations/Tests/UnitTests/UserRegistrations/UserRegistrationTests.cs)
  • Consequences are mostly positive but the decision "Solution 1." and context are both restated verbatim with no real rationale; the visible text gives no signal of trade-offs (docs/architecture-decision-log/0005-create-one-rest-api-module.md)
  • Context is a duplicate title and the decision restates the architecture name with no rationale; consequences are boilerplate list (single-process monolith, autonomy, Bounded Contexts, tactical patterns) without any trade-offs (docs/architecture-decision-log/0002-use_modular-monolith-system-architecture.md)
  • Context is thin and the body only states that ADRs are created for advanced monolith projects but does not explain why ADL plus ADR structure (Status/Context/Decision/Consequences) is needed (docs/architecture-decision-log/0001-record-architecture-decisions.md)
  • Documentation: no installation or build instructions (README.md)
  • Documentation: written for insiders (docs/architecture-decision-log/0017-implement-archictecture-tests.md)
  • Duplicated block (10 lines × 2) (src/Modules/Administration/Infrastructure/Configuration/AdministrationStartup.cs)
  • Duplicated block (10 lines × 2) (src/Modules/Administration/Infrastructure/Domain/Members/MemberEntityTypeConfiguration.cs)
  • Duplicated block (10–11 lines × 2) (src/Modules/Administration/Infrastructure/Configuration/AdministrationStartup.cs)
  • …and 173 more

API surface

  • Unchanged — 51 HTTP endpoints

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

kgrzybek/modular-monolith-with-ddd was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 22 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 91c8ef24b4cb6ef558c95d8267fa07d68c7059f8 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-821afab8930d.