Skip to content
CAI
Software that uses CAICheck a score

DavidEggenberger/ModularMonolith.SaaS.Template

41.6

Weak · 20 September 2026

4.3k

lines of production code

C#

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is a modular monolithic SaaS template built on ASP.NET Core and Blazor, designed to manage multi-tenant identity and subscription lifecycles. It provides core capabilities for user authentication via social providers, tenant membership management, and billing integration with Stripe for checkout and portal sessions. The architecture enforces strict multi-tenancy and transactional consistency across isolated feature modules while supporting real-time notifications and email delivery.

How it got here

2023 — Modular monolith SaaS template initial release

18 changes.

This period focused on establishing the foundational architecture of a modular monolithic SaaS template using ASP.NET Core and Blazor, featuring isolated modules for tenant identity and subscriptions. Key developments included implementing multi-tenancy, integrating Stripe for billing, and centralizing shared infrastructure such as authentication policies and database transaction management. The work also involved upgrading the stack to .NET 9 and standardizing the UI with Tailwind CSS.

2024–2025 — Core infrastructure and multi-tenant foundation

28 changes.

This period established the application's foundational architecture by implementing a shared kernel, command/query dispatching, and integration messaging infrastructure. It simultaneously built the core domain models and persistence layers for multi-tenant identity management and Stripe-based subscription handling, laying the groundwork for the Blazor client and landing pages.

Features

Added SendGrid-based email sending capability

The application now includes a new email sender feature that integrates with SendGrid. This adds a configurable SendGrid API key option, an IEmailSender interface, and a SendGridEmailSender implementation that handles sending emails with disabled click tracking. The service is registered via dependency injection using the new Registrator class, allowing the system to send password recovery and other transactional emails through SendGrid.

Source/Shared/Features/EmailSender · high confidence

Added SignalR notification infrastructure

Introduced a new SignalR-based notification system within the shared features layer. This includes a \NotificationHub\ for real-time communication, a \NotificationHubService\ to send targeted notifications to specific users, and a \UserIdProvider\ to resolve user identities from authentication claims. The feature is wired up via dependency injection and endpoint mapping in the \Registrator\ class, enabling the application to push notifications to connected clients.

Source/Shared/Features/SignalR · high confidence

Added Stripe subscription domain model and status enum

Introduced the StripeSubscription entity and StripeSubscriptionStatus enum to model subscription data within the Stripe integration module. The new entity tracks subscription identifiers, expiration dates, plan types, and status, while the enum defines the possible states (Active, Trialing, Paused). This change establishes the core domain structure for managing Stripe subscriptions in the system.

Source/Modules/Subscriptions/Features/DomainFeatures/StripeSubscriptions · high confidence

Added StripeCustomer entity with EF Core configuration

Introduced the StripeCustomer domain entity to track the mapping between internal user IDs and Stripe portal customer IDs. The change includes the entity definition and its Entity Framework Core configuration, establishing the persistence model for this subscription-related data.

Source/Modules/Subscriptions/Features/DomainFeatures/StripeCustomers · high confidence

Added configuration and validation for social identity providers

The TenantIdentity module now includes a dedicated configuration class to manage credentials for Google, Microsoft, and LinkedIn social login providers. A corresponding validator ensures that the Google Client ID, Microsoft Client ID, and Google Client Secret are present and non-empty at startup, failing configuration if any are missing.

Source/Modules/TenantIdentity/Features/Infrastructure/Configuration · high confidence

Added integration messaging infrastructure and subscription event

This change introduces the core interfaces and dispatcher for the application's integration messaging system, enabling services to publish events and send requests to other bounded contexts. It includes the \IIntegrationEventHandler\, \IIntegrationRequestHandler\, and \IIntegrationMessageDispatcher\ interfaces, along with a concrete \IntegrationMessageDispatcher\ implementation that resolves handlers via dependency injection to handle events and requests. Additionally, a new \TenantSubscriptionPlanUpdatedEvent\ is defined within the Subscriptions module to signal when a tenant's subscription plan changes, serving as the first concrete integration event in this new messaging framework.

Source/Modules/Subscriptions/Public, Source/Shared/Features/Messaging/IntegrationMessages · high confidence

Added query to retrieve subscription details for a tenant

A new query handler, GetSubscriptionForTenant, has been introduced to allow fetching subscription information for a specific tenant. This query leverages the existing Query base class and returns a StripeSubscription object, enabling the application to retrieve subscription data based on a provided TenantId.

Source/Modules/Subscriptions/Features/DomainFeatures/StripeSubscriptions/Application/Queries · high confidence

Handle tenant subscription plan updates via integration events

The system now automatically synchronizes tenant subscription plans when external subscription events occur. A new integration event handler listens for TenantSubscriptionPlanUpdatedEvent messages and updates the corresponding tenant's subscription plan type in the database, ensuring the tenant's state remains consistent with the subscription module.

Source/Modules/TenantIdentity/Features/DomainFeatures/Tenants/Application/IntegrationMessageHandlers · high confidence

Initial database migration for Tenant Identity module

Adds the initial Entity Framework Core migration (20241103150530\_initial) for the Tenant Identity module, establishing the 'Identity' schema in SQL Server. This migration creates the foundational tables for ASP.NET Core Identity (ApplicationUser, Role, and their claims, logins, tokens, and roles) alongside the custom Tenant entity, enabling the application to initialize its database structure for tenant-based identity management.

Source/Modules/TenantIdentity/Features/Migrations · high confidence

Initial database schema and automated migration setup

The application now includes an initial SQL migration script that creates the core Identity and Tenant schemas, including tables for users, roles, claims, logins, tokens, tenants, and memberships. Database initialization is handled by DbUp, which automatically creates the database if it does not exist and applies the embedded SQL scripts to ensure the schema is up to date.

Source/Shared/Features/EFCore/DbUp · high confidence

Initial landing pages module with sign-in and sign-up modals

This change introduces the core structure for the Landing Pages module, including the main application layout, routing, and initial pages (Home, About, Pricing). It adds a navigation bar with a 'Sign in' button that triggers a sign-up modal via Blazored.Modal. The module includes placeholder components for Sign-In and Sign-Up modals, with the Sign-Up modal currently containing a static UI for social login providers (Google, Microsoft, LinkedIn) and account creation, though the modal opening logic in the layout is wired to show the Sign-Up modal. The module startup registers the Blazored.Modal service.

Source/Modules/LandingPages · high confidence

Initial release of Modular Monolith SaaS template

Introduces a starter template for building modular monolithic SaaS applications using ASP.NET Core, Blazor, and EF Core with SQL Server. The solution establishes a modular architecture where subdomains (such as TenantIdentity and Subscriptions) are organized into isolated modules, supported by shared infrastructure components in Shared.Kernel, Shared.Features, and Shared.Client. It includes a Web.Server to host controllers and the Blazor WebAssembly client, along with Docker Compose configuration for local SQL Server infrastructure and TailwindCSS integration for styling.

(repo-wide) · high confidence

Introduces shared client authentication, HTTP handling, and UI building blocks

The Shared.Client project now provides foundational components for the Blazor WebAssembly application. Authentication is handled by a new HostAuthenticationStateProvider that fetches user claims and manages sign-in/sign-out navigation, supported by an AuthorizedHandler that injects antiforgery tokens into outgoing requests. HTTP interactions are standardized through HttpClientService and AuthorizedHttpClientService, which automatically handle API routing and display server ProblemDetails in a new ErrorModal. The layout system includes a MainLayout with a responsive sidebar and a NavMenu, while reusable UI elements like DeletionModal and ErrorModal are added to handle user confirmations and error reporting.

Source/Shared/Client · high confidence

Introduction of Application User entity with tenant and session state tracking

The system now includes an Application User entity that extends the standard identity user model to support multi-tenant environments and session awareness. Users can now be associated with specific tenants via a selected tenant ID and a collection of tenant memberships. Additionally, the entity tracks online status based on the number of open tabs, allowing the application to reflect real-time user presence. The entity also supports profile picture storage and includes configuration for database mapping.

Source/Modules/TenantIdentity/Features/DomainFeatures/Users · high confidence

Introduction of Shared Kernel building blocks and DI registration

The Shared Kernel now provides foundational interfaces for integration scenarios, specifically IIntegrationEvent and IIntegrationRequest, alongside a Registrator class that simplifies dependency injection setup via the AddSharedKernel extension method. This change establishes the structural basis for handling integration messages and centralizes the registration of shared kernel services within the application's startup configuration.

Source/Shared/Kernel/BuildingBlocks · high confidence

Introduction of SubscriptionsDbContext for EF Core persistence

A new SubscriptionsDbContext has been added to the Subscriptions module's EF Core infrastructure layer. This context inherits from BaseDbContext and exposes DbSet properties for StripeCustomer and StripeSubscription entities, enabling database persistence for these specific domain models.

Source/Modules/Subscriptions/Features/Infrastructure/EFCore · high confidence

Introduction of SubscriptionsModule for dependency injection

A new SubscriptionsModule class has been added to the application's module system. This component acts as a container for subscription-related dependencies, specifically holding instances of SubscriptionsConfiguration and SubscriptionsDbContext. It implements the IModule interface and exposes the assembly containing the subscription features, enabling the application to properly register and resolve these services during startup.

Source/Modules/Subscriptions/Features · high confidence

Introduction of Tenant Identity Module

A new TenantIdentityModule has been added to the application, serving as the entry point for the tenant identity feature set. This module initializes and exposes the TenantIdentityDbContext and TenantIdentityConfiguration, enabling the system to manage tenant-specific identity data and database interactions.

Source/Modules/TenantIdentity/Features · high confidence

Introduction of a generic query dispatcher and handler infrastructure

The application now includes a new shared messaging layer for handling queries, featuring a generic \IQueryDispatcher\ and \QueryDispatcher\ implementation that routes requests to specific \IQueryHandler\ instances via dependency injection. This change introduces the base \Query\<T\>\ class and handler interfaces, establishing a standardized pattern for executing read operations within the system.

Source/Shared/Features/Messaging/Queries · high confidence

Introduction of a new command dispatching infrastructure

The application now includes a dedicated command handling system within the Shared features layer. This change introduces base \Command\ classes, strongly-typed \ICommandHandler\ interfaces, and a \CommandDispatcher\ that resolves and executes handlers via dependency injection. This provides a standardized mechanism for processing commands across the application.

Source/Shared/Features/Messaging/Commands · high confidence

New Stripe integration endpoints for checkout, portal, and post-payment handling

This change introduces three new API controllers in the Subscriptions module to manage Stripe interactions. The StripeSessionController provides endpoints to initiate Stripe Checkout sessions for new subscriptions and create Billing Portal sessions for existing customers, both requiring TenantAdmin authorization. The StripeSuccessController handles the post-payment redirect flow by verifying the Stripe session, retrieving the associated customer, and automatically signing the user in. The StripeSubscriptionsController is added as a scaffold for retrieving subscription details, though its implementation is currently incomplete.

Source/Modules/Subscriptions/Web/Server/Controllers · high confidence

New Tenant Identity database context with schema and query capabilities

A new TenantIdentityDbContext has been introduced to manage the tenant identity module's data persistence. It inherits from ASP.NET Core Identity's IdentityDbContext to handle ApplicationUser and IdentityRole entities, while also introducing DbSet properties for Tenant, TenantInvitation, and TenantMembership. The context is configured to use SQL Server, applying a default schema of 'Identity' and mapping specific tables (e.g., Role, RoleClaim) to explicit names. It includes a migration history table named 'MigrationHistory\_TenantIdentity' and registers an ExecutionContextInterceptor for execution context propagation. Additionally, it provides specific query methods such as GetAllTenantsForUser, GetUserByIdAsync, GetTenantByIdAsync, and GetTenantExtendedByIdAsync to retrieve tenant and user data with necessary includes.

Source/Modules/TenantIdentity/Features/Infrastructure/EFCore · high confidence

New claims principal and string utility extensions

The shared kernel now includes new extension methods for ClaimsPrincipal to simplify extracting user identity, tenant information, and roles from authentication claims, along with a corresponding exception class for missing claims. Additionally, a string extension method has been added to convert string representations directly to Guids.

Source/Shared/Kernel/Extensions · high confidence

New domain kernel interfaces and shared enums introduced

The DomainKernel now exposes a set of standard domain interfaces (IApplicationUser, IAuditable, IConcurrent, IIdentifiable, ITenantIdentifiable, IUserIdentifiable) and shared enums (SubscriptionPlanType, TenantRole) to support consistent entity modeling and tenant/user identification across the application.

Source/Shared/Kernel/DomainKernel · high confidence

New integration event handler and query for Stripe customer lookup

This change introduces a new integration event handler that automatically creates a Stripe customer record when a tenant admin is created, and adds a new query to retrieve a Stripe customer by their Stripe Portal ID. The event handler listens for the TenantAdminCreatedEvent, checks if a Stripe customer already exists for the user, and creates one via the Stripe API if not. The new query allows fetching Stripe customer details using the Stripe Portal Customer ID.

Source/Modules/Subscriptions/Features/DomainFeatures/StripeCustomers/Application · high confidence

New public DTOs and integration events for tenant identity operations

The TenantIdentity module now exposes a set of public Data Transfer Objects (DTOs) and integration events to support tenant management and user identity operations. This includes DTOs for creating tenants, inviting users, changing member roles, and revoking invitations, as well as detailed tenant information DTOs (TenantDTO, TenantExtendedDTO) and membership/invitation structures. Additionally, integration events (TenantAdminCreatedEvent, TenantAdminEmailUpdatedEvent) are now available to signal tenant administration changes, and a BFFUserInfoDTO is provided for backend-for-frontend user identity data.

Source/Modules/TenantIdentity/Public · high confidence

New queries to retrieve executing user details and claims

Added two new application queries, GetExecutingUser and GetClaimsForExecutingUser, which allow the system to fetch the current user's profile data and a comprehensive set of security claims (including user identity, email, picture, tenant subscription plan, tenant name, tenant ID, and user role) in a single request.

Source/Modules/TenantIdentity/Features/DomainFeatures/Users/Application/Queries · high confidence

New queries to retrieve tenant details and user memberships

Added two new application queries for the Tenant module: GetTenant, which retrieves a specific tenant by ID, and GetAllTenantMembershipsOfUser, which returns the list of all tenants associated with the currently executing user. These queries expose tenant data and user-tenant relationships via DTOs, enabling clients to fetch tenant information and determine a user's organizational affiliations.

Source/Modules/TenantIdentity/Features/DomainFeatures/Tenants/Application/Queries · high confidence

New shared infrastructure for execution context, validation, and module configuration

This change introduces a new set of shared components in the \Shared.Features.Misc\ area to standardize cross-cutting concerns. It adds an \IExecutionContext\ interface and a \ServerExecutionContext\ middleware that automatically populates request context (user ID, tenant ID, role, plan) from the HTTP context. It also provides a \ValidationService\ that uses FluentValidation to validate models, a \BaseController\ and \ServerExecutionBase\ that inject these services (along with command/query/integration message dispatchers), and a module registration system (\IModuleStartup\, \Registrator\) to simplify adding new feature modules. Additionally, it includes a base \Entity\ class with tenant/audit fields and an \EnsureCallerRole\ method, as well as configuration registration helpers.

Source/Shared/Features/Misc · high confidence

New tenant identity web module with authentication and tenant management

This change introduces the TenantIdentity web module, providing the server-side controllers and client-side components for user authentication and tenant administration. It adds ASP.NET Core Identity integration with support for external login providers (Google, LinkedIn, Microsoft Account) and cookie-based authentication. The module exposes API endpoints for managing tenants (create, delete, list), handling tenant membership (add, update, remove members), and performing identity operations such as logging in via external providers, selecting a tenant, and logging out. Client-side Blazor components handle the login display and redirection to the authentication flow.

Source/Modules/TenantIdentity/Web · high confidence

New tenant management commands for membership and lifecycle

This change introduces five new application-layer commands within the TenantIdentity module to manage tenant creation, deletion, and member roles. Users can now create a new tenant with an initial admin, delete a tenant (restricted to admins), add new members with specific roles, remove existing members, and update a member's role. These commands implement the backend logic for the full tenant membership lifecycle.

Source/Modules/TenantIdentity/Features/DomainFeatures/Tenants/Application/Commands · high confidence

New user management commands for creation, tenant selection, and profile updates

The application now exposes specific command handlers for managing user identities within the TenantIdentity module. Users can create new accounts with associated external login information, switch their active tenant context, and update their profile details such as username and profile picture. These changes implement the core application-layer logic for these operations using the shared command infrastructure.

Source/Modules/TenantIdentity/Features/DomainFeatures/Users/Application/Commands · high confidence

Stripe billing portal and checkout session creation

Users can now initiate Stripe billing portal sessions to manage their subscriptions and create checkout sessions to subscribe to specific plans. This change introduces command handlers that look up the user's Stripe customer ID and, for checkout, map the requested subscription plan to the corresponding Stripe price ID, trial period, and redirect URLs to facilitate the payment flow.

Source/Modules/Subscriptions/Features/Infrastructure/StripePayments · high confidence

Stripe subscription configuration and validation

The application now includes a dedicated configuration class for Stripe subscription settings, exposing properties for the API key, endpoint secret, and specific price IDs for Professional and Enterprise plans. This configuration defines the mapping between internal subscription plan types and their corresponding Stripe price identifiers, including a 14-day trial period for both tiers. A corresponding validator ensures that the Professional Plan Price ID is provided, preventing runtime errors when resolving subscription types.

Source/Modules/Subscriptions/Features/Infrastructure/Configuration · high confidence

Stripe subscription lifecycle command handlers

Added command handlers for managing Stripe subscription states: creating trialing subscriptions (which persist the subscription and dispatch a TenantSubscriptionPlanUpdatedEvent), pausing active subscriptions, and updating subscription periods (refreshing expiration dates and ensuring active status).

Source/Modules/Subscriptions/Features/DomainFeatures/StripeSubscriptions/Application/Commands · high confidence

Stripe webhook handler for subscription lifecycle events

A new StripeWebhook controller has been added to handle incoming Stripe events, specifically processing CheckoutSessionCompleted and InvoicePaid events to create trialing subscriptions and update subscription periods via internal commands. The handler verifies the Stripe signature and dispatches the appropriate domain commands, though InvoicePaymentFailed events are currently received but not yet processed.

Source/Modules/Subscriptions/Web/Server/WebHooks · high confidence

Subscriptions module server initialization

The Subscriptions module now includes a dedicated server startup class that registers the SubscriptionsDbContext, applies configuration validation for subscription settings, and initializes the Stripe API key from the application configuration.

Source/Modules/Subscriptions/Web/Server · high confidence

Tenant management domain model and EF configuration introduced

The TenantIdentity module now includes the core domain entities for tenant management: Tenant, TenantMembership, and TenantInvitation. These classes encapsulate the business logic for creating tenants, adding/removing members, changing member roles, inviting users, and updating subscription plans, while enforcing that only admins can perform membership modifications. Entity Framework Core configuration classes are also provided to map these entities to the corresponding database tables.

Source/Modules/TenantIdentity/Features/DomainFeatures/Tenants/Domain · high confidence

Behavioural changes

Blazor hybrid client-server rendering with shared UI infrastructure

The application now uses a Blazor hybrid model where authenticated users are served a WebAssembly client (ClientApp) and unauthenticated users see a Server-rendered LandingPages app, all hosted via a shared Razor layout (\_Host.cshtml). This change introduces a new client-side project structure with its own entry point and dependency registration, alongside a comprehensive set of server-side building blocks including API versioning, antiforgery token handling, structured exception handling, security headers, and Swagger documentation. The visual layer has been standardized using Tailwind CSS for consistent styling across both client and server components.

Source/Web · high confidence

Centralized authentication policy registration in shared kernel

The shared kernel now provides a centralized \AuthRegistrator\ service extension that configures ASP.NET Core authorization policies. This change introduces specific policies for tenant membership (requiring tenant ID and user/admin roles), tenant administration (requiring tenant ID and admin role), and subscription plans (Professional and Enterprise), ensuring consistent access control enforcement across the application.

Source/Shared/Kernel · high confidence

Centralized authentication, endpoint, and system constants

The shared kernel now provides a unified set of constants for core system configuration. This includes authentication details (claim types, policies, subscription plans, and tenant roles), API endpoint paths for user identity operations and Stripe subscriptions, the SignalR notification hub name, and the Tailwind CSS output path. These constants replace scattered string literals, ensuring consistent configuration across the application.

Source/Shared/Kernel/Constants · high confidence

Centralized messaging infrastructure with module-specific handler registration

The messaging subsystem now includes a dedicated \Registrator\ class that centralizes the registration of core dispatchers (commands, queries, and integration messages) and provides a mechanism to automatically discover and register handlers for specific modules. This change introduces support for integration messages and establishes a convention-based approach for wiring up command and query handlers within module assemblies, replacing previous ad-hoc or domain-event-centric patterns.

Source/Shared/Features/Messaging · high confidence

Centralized shared feature registration and middleware pipeline

The shared features module now provides a unified entry point for registering core infrastructure services and applying middleware. The new \Registrator\ class consolidates the setup of Server Execution Context, Messaging, EF Core, Email Sender, and SignalR into single \AddSharedFeatures\ and \UseSharedFeaturesMiddleware\ extension methods, simplifying application initialization. Additionally, new exception types (\CrossTenantUpdateException\, \EntityNotTenantIdentifiableException\) have been added to the EF Core multi-tenancy layer to handle specific tenant-related errors.

Source/Shared/Features · high confidence

Custom user claims principal factory for tenant identity

The system now uses a custom \UserClaimsPrincipalFactory\ to generate authentication claims for users. This factory retrieves specific claims by dispatching a \GetClaimsForExecutingUser\ query, ensuring that the resulting \ClaimsPrincipal\ includes the correct username and role information defined in the tenant identity module.

Source/Modules/TenantIdentity/Features/Infrastructure · high confidence

EF Core database access now wrapped in a single request-scoped transaction

The EF Core integration in Shared.Features.EFCore has been refactored to ensure that all database operations within a single HTTP request are executed inside one transaction. A new TransactionScopeMiddleware intercepts requests and wraps the entire pipeline in a TransactionScope, while the BaseDbContext and its associated interceptors (ExecutionContextInterceptor, MultiTenancyEntityConfiguration) handle tenant isolation, audit fields, and authorization checks within that scope. This change guarantees atomicity for multi-step writes and simplifies error handling by rolling back all changes if any part of the request fails.

Source/Shared/Features/EFCore · high confidence

Dependencies

Upgrade to .NET 9 and update core dependencies

The application has been upgraded to target .NET 9.0 across all modules and shared libraries. This update includes upgrading the Blazor, ASP.NET Core, and Entity Framework Core packages to version 9.0.0, alongside updates to supporting libraries such as Stripe.net (47.2.0-beta.3), FluentValidation (11.11.0), and Azure.Identity (1.13.1).

(dependencies) · high 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

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 43 → 42 (-1.9)
  • Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 53 → 53 (-0.3)
  • Architecture 70 → 70 (+0.2)
  • Maturity 67 → 64 (-2.8)
  • Readiness 30 → 29 (-0.3)
  • Security 87 → 83 (-4.1)
  • Event-Driven 100 → 100 (+0.0)
  • Accessibility 45 → 39 (-5.6)

Resolved (14)

  • Change coupling: BaseController.cs ↔ ServerExecutionBase.cs (Source/Shared/Features/Misc/BaseController.cs)
  • Change coupling: BaseDbContext.cs ↔ DbContextRegistrator.cs (Source/Shared/Features/EFCore/BaseDbContext.cs)
  • Change coupling: GetStripeCustomerByStripePortalId.cs ↔ CreateTrialingSubscription.cs (Source/Modules/Subscriptions/Features/DomainFeatures/StripeCustomers/Application/Queries/GetStripeCustomerByStripePortalId.cs)
  • Change coupling: Program.cs ↔ Startup.cs (Source/Web/Client/Program.cs)
  • Duplicated block (11 lines × 2) (Source/Shared/Client/BuildingBlocks/Http/AuthorizedHttpClientService.cs)
  • Duplicated block (15 lines × 2) (Source/Shared/Client/BuildingBlocks/Http/AuthorizedHttpClientService.cs)
  • Duplicated block (15 lines × 2) (Source/Shared/Client/BuildingBlocks/Http/AuthorizedHttpClientService.cs)
  • Low cohesion: ExceptionHandler (LCOM4 4) (Source/Web/Server/BuildingBlocks/ExceptionHandling/ExceptionHandler.cs)
  • No exposed public API
  • Outdated: Blazored.Modal
  • Scanner failed to run — not a clean result
  • Small-team knowledge concentration
  • XML-doc coverage: Modules.TenantIdentity.Web.Client (Source/Modules/TenantIdentity/Web/Client/Modules.TenantIdentity.Web.Client.csproj)
  • redundant comment (Source/Modules/LandingPages/Server/LandingPagesLayout.razor.cs)

New (30)

  • Boundary-crossing change coupling: TenantsController.cs ↔ IIntegrationEventHandler.cs (Source/Modules/TenantIdentity/Web/Server/Controllers/TenantsController.cs)
  • Change coupling: BaseController.cs ↔ ServerExecutionContext.cs (Source/Shared/Features/Misc/BaseController.cs)
  • Change coupling: IIntegrationEventHandler.cs ↔ BaseController.cs (Source/Shared/Features/Messaging/IntegrationMessages/IIntegrationEventHandler.cs)
  • Documentation: no contributor guidance (README.md)
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no usage examples (README.md)
  • Duplicated block (12 lines × 2) (Source/Shared/Client/BuildingBlocks/Http/AuthorizedHttpClientService.cs)
  • Duplicated block (15 lines × 4) (Source/Shared/Client/BuildingBlocks/Http/AuthorizedHttpClientService.cs)
  • Duplicated block (16 lines × 2) (Source/Shared/Client/BuildingBlocks/Http/AuthorizedHttpClientService.cs)
  • Duplicated block (20 lines × 2) (Source/Shared/Client/BuildingBlocks/Http/AuthorizedHttpClientService.cs)
  • End-of-life runtime: .NET net9.0
  • High IaC: WD-COMPOSE-0002 (docker-compose.infrastructure.yml)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Medium: security finding (details withheld)
  • …and 10 more

API surface

  • Unchanged — 16 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

DavidEggenberger/ModularMonolith.SaaS.Template 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 20 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 8022841468a04c0d34b0fba20ec33346b5e386d5 — 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-28e75b8e3254.