AditiKraft/Krafter
58.7
Adequate · 21 September 2026
9.7k
lines of production code
C#
primary language
4
measurements over time
What this system is
AditiKraft.Krafter is a multi-tenant SaaS platform built on .NET 10 that provides backend APIs and a Blazor WebAssembly frontend for managing users, roles, and tenant configurations. It supports both distributed and single-host deployment models, utilizing PostgreSQL for persistence and Aspire for local development orchestration. The system enforces strict tenant isolation through URL routing, real-time SignalR scoping, and permission-based authorization, while handling authentication via JWT and Google OAuth.
How it got here
2025 — Architecture modernization and cleanup
22 changes.
The project underwent a comprehensive architectural overhaul, migrating the build system to Fallout and upgrading to .NET 10 while replacing legacy components with modern standards like .NET Aspire and Refit. This period involved the removal of extensive legacy backend and frontend code, including old authentication, tenant management, and Blazor WebAssembly infrastructure, to streamline the codebase and improve consistency.
2026 — Aditi Kraft rebrand and multi-tenant architecture
49 changes.
The project underwent a comprehensive rebranding to Aditi Kraft, standardizing namespaces, UI components, and branding assets across the backend and Blazor WebAssembly client. This period established a robust multi-tenant architecture with single-tenant mode support, introducing separate database contexts, tenant-aware URL routing, and isolated SignalR hubs. The work also consolidated the infrastructure by migrating to PostgreSQL, integrating Aspire for local development, and implementing a unified authentication system with coordinated token refresh.
Features
Auth UI feature files added with Google OAuth and login logic
The Auth feature folder now contains the core UI components for authentication: Login.razor and Login.razor.cs implement the email/password login form and Google OAuth initiation, preserving the ReturnUrl query parameter and handling post-login redirects. GoogleCallback.razor and GoogleCallback.razor.cs handle the Google OAuth callback, extracting the authorization code and state to complete the login flow and navigate to the original destination. IAuthApi.cs defines the REST API contracts for token creation, refresh, Google authentication, logout, and current token retrieval. An Agents.md guide documents the auth implementation patterns, including the use of IAuthenticationService, token refresh coordination, and Google redirect URI configuration.
src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Auth · high confidence
Initial Web Client scaffolding with theme, role selection, and tenant-aware routing
The \AditiKraft.Krafter.UI.Web.Client\ project is introduced, providing the core Blazor WebAssembly shell. Users can now manage their visual preferences via a new Appearance page that supports theme switching, right-to-left layout, and WCAG-compliant colors. The client includes reusable role-selection components (single and multi-select dropdowns) for role management. Authentication and tenant context are handled through a new routing structure that seeds tenant data on initialization, loads public API URLs dynamically, and coordinates token refresh across browser API handlers.
src/UI/AditiKraft.Krafter.UI.Web.Client · high confidence
Introduce .NET Aspire solution files and modern C\# coding standards
The project now uses .NET Aspire solution files (\.slnx\) to define the workspace structure for both split-host and single-host deployment variants, replacing the legacy \.sln\ format. Additionally, a comprehensive \.editorconfig\ has been added to enforce modern C\# conventions (C\# 9-12), including file-scoped namespaces, Allman-style braces, and explicit type usage to improve AI agent assistance and code consistency.
(repo-wide) · high confidence
Introduces SignalR hub connection with tenant-aware authentication and token refresh
The client now establishes a WebSocket-based SignalR connection to the RealtimeHub, scoped to the current tenant via the URL query parameter. The connection automatically attaches the cached access token and proactively refreshes it if expired before sending requests; if the refresh fails, the user is logged out. The service is active only for WebAssembly form factors and supports automatic reconnection with a short backoff strategy.
src/UI/AditiKraft.Krafter.UI.Web.Client/Infrastructure/SignalR · high confidence
New Aspire-backed database migration service
A new standalone application has been added to handle database migrations using the Aspire service defaults. This service initializes and runs migrations for the Tenant, Background Jobs, and Application databases as a background host service, ensuring the schema is up-to-date before the application stops.
src/AditiKraft.Krafter.Backend.Migrator · high confidence
New Page Not Found UI with Radzen components
The application now displays a dedicated 'Page Not Found' view when users navigate to non-existent routes. This page features a centered layout with a 'search\_off' icon, a clear heading, and a descriptive message, all styled using Radzen components. It includes a primary 'Go Home' button that navigates the user back to the root URL, improving the user experience for broken or mistyped links.
src/UI/AditiKraft.Krafter.UI.Web.Client/Features · high confidence
New Roles management UI with permission-aware save controls
The Roles feature now includes a dedicated UI for managing roles, including a list view and a create/update dialog. A key behavioral change is that existing roles cannot be saved until their permissions have loaded successfully; the Save button and permission selector remain disabled during loading or if the permission load fails, with a retry option provided. This prevents accidental clearing of existing permissions. The UI uses grouped permissions from the PermissionCatalog and integrates with the existing API for role CRUD operations.
src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Roles · high confidence
New Users feature with full CRUD and password management
The Users feature now provides a complete set of client-side capabilities for managing user accounts. Administrators can view, create, update, and delete users via a dedicated list page and dialog, with role assignment handled through a multi-select dropdown. The feature also introduces dedicated pages for account security, allowing users to change their own passwords, request a password reset via email, and complete the reset flow using a token.
src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Users · high confidence
New tenant management interface with single-tenancy guard
The Tenants feature now includes a dedicated UI for managing tenants, consisting of a list page (Tenants.razor) and a create/update dialog (CreateOrUpdateTenant.razor). The list page displays tenant details, allows filtering, sorting, and paging, and provides action buttons for editing and deleting tenants based on user permissions. The dialog handles creating and updating tenant records, including validation for expiry dates and handling of local time zones. A key behavioral change is that the tenant management interface is automatically hidden (redirecting to /not-found) when the application is running in single-tenancy mode, as detected by TenantSettings.TenancyMode.
src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Tenants · high confidence
Removals
Removal of Aspire AppHost orchestration configuration
The distributed application host configuration file (Program.cs) has been removed from the Krafter.Aspire.AppHost project. This change eliminates the local definition and orchestration of the development environment, including the PostgreSQL database, Garnet cache, and the Krafter UI Web and Backend services that were previously managed by this host.
aspire/Krafter.Aspire.AppHost · high confidence
Removal of SignalR real-time infrastructure and Menu model
The SignalR real-time communication capabilities have been removed from the web client, specifically deleting the SignalRService which handled hub connections and message sending, along with the SignalRMethods constants class. Additionally, the Menu model class, which defined the structure for menu items including properties like Name, Icon, Path, and Children, has been deleted from the Models directory.
src/UI/Krafter.UI.Web.Client/Infrastructure/SignalR, src/UI/Krafter.UI.Web.Client/Models · high confidence
Removal of Web Application entry point and configuration
The Program.cs entry point and appsettings.Development.json configuration files for the Krafter.UI.Web project have been deleted. This removes the server-side Blazor hosting layer, including the JWT authentication middleware, token refresh logic, and API client registration that previously managed the web application's startup and runtime behavior.
src/UI/Krafter.UI.Web · high confidence
Removal of authentication token and refresh token logic
The authentication feature in this location has been stripped of its core token management capabilities. The login handler (Login.cs) and the refresh token handler (RefreshToken.cs) have been deleted, removing the ability to generate JWTs, validate refresh tokens, and issue new access tokens. Additionally, the supporting shared types—ITokenService, TokenResponse, and UserRefreshToken—have been removed, meaning the application no longer maintains or processes authentication tokens within this module.
src/Backend/Features/Auth · high confidence
Removal of legacy Roles and Users management UI components
The Roles and Users feature pages, including the role list, role creation/editing dialog, user creation/editing dialog, and password management forms (change, forgot, and reset), have been removed from the client application. This cleanup eliminates the previous Blazor-based UI implementations for these areas, which relied on the legacy KrafterClient for API integration.
src/UI/Krafter.UI.Web.Client/Features/Users · high confidence
Removal of legacy authentication and appearance UI components
The Appearance page for theme selection and the entire Auth feature set—including the Login page, Google OAuth callback handling, and the AuthenticationService implementation—have been removed from the client application. This deletion eliminates the previous manual token management, Google login flow, and theme switching UI, indicating these capabilities are no longer supported or have been replaced by a different implementation elsewhere in the system.
src/UI/Krafter.UI.Web.Client/Features/Auth · high confidence
Removal of legacy client-side components and shared utilities
The \src/UI/Krafter.UI.Web.Client/Common\ directory has been cleared of its previous implementation, removing a broad set of UI components (including \LoadingIndicator\, \Logo\, \DeleteDialog\, \DebouncedSearchInput\, \MainLayout\, \NavigationItem\, \Notifications\, and \TopRight\), supporting models and constants (such as \GetRequestInput\, \Response\, \KrafterClaims\, \EntityKind\, and route/role constants), and utility extensions (including \ClaimsPrincipalExtensions\ and \MathExtensions\). This cleanup eliminates the local definitions for branding, layout, dialogs, search, and permission handling that were previously maintained in this shared location.
src/UI/Krafter.UI.Web.Client/Common · high confidence
Removal of server-side authentication and API service implementations
The server-side implementations for authentication state persistence, token management, and API communication have been removed from the \Krafter.UI.Web/Services\ directory. Specifically, \PersistingServerAuthenticationStateProvider\, \ServerAuthenticationHandler\, \ServerSideApiService\, \KrafterLocalStorageServiceServer\, \FormFactorServer\, and \TenantInfo\ (implied by context of other deletions) are no longer present. This eliminates the server-side logic that previously handled JWT token caching in cookies, persisted authentication state to the client via \PersistentComponentState\, and managed API calls using \HttpClient\ with bearer token injection. Users relying on server-side rendering or hybrid authentication flows in this specific service layer will no longer have these server-side helpers available.
src/UI/Krafter.UI.Web/Services · high confidence
Removal of user management shared components
The shared user management components located in \src/Backend/Features/Users/\_Shared\ have been removed. This includes the \CreateUserRequest\ model, the \IUserService\ interface, and the \UserService\ implementation. Consequently, the logic for creating and updating users, including permission checks and tenant email synchronization, is no longer available in this location.
_src/Backend/Features/Users/\Shared · high confidence
Removed client-side API service implementation and interface
The \ClientSideApiService\ class and the \IApiService\ interface have been deleted from the \src/UI/Krafter.UI.Web.Client/Infrastructure/Api\ directory. This removes the manual HTTP client implementation used for handling token creation, refresh, external authentication, user permissions, and logout operations on the client side, aligning with the broader migration to Refit for API integration.
src/UI/Krafter.UI.Web.Client/Infrastructure/Api · high confidence
Removed legacy Blazor Web Client infrastructure and code
The entire source code for the \Krafter.UI.Web.Client\ project has been deleted, removing the Blazor WebAssembly application, its authentication state providers, HTTP handlers, tenant configuration logic, and UI routing components.
src/UI/Krafter.UI.Web.Client · high confidence
Removed legacy Blazor tenant management components
The tenant management UI components in the web client have been removed. This includes the \Tenants.razor\ page (which displayed the tenant list and action buttons), the \CreateOrUpdateTenant.razor\ dialog (used for creating and editing tenant details like name, identifier, and admin email), and supporting files such as \TenantValidator.cs\ and \TablesToCopy.cs\. These files are no longer part of the application.
src/UI/Krafter.UI.Web.Client/Features/Tenants · high confidence
Removed legacy role, user, and tenant management features
The legacy implementations for managing roles, users, and tenants have been removed from the backend. This includes the deletion of the \CreateOrUpdateRole\, \DeleteRole\, and \UpdateRolePermissions\ handlers, as well as the \CreateOrUpdateUser\ and \CreateOrUpdate\ tenant handlers. Additionally, the \Get\ tenant query handler, the \SeedBasicData\ route, and the \DataSeedService\ responsible for initializing default roles, users, and permissions are no longer present. These changes eliminate the previous direct API endpoints and service logic for these core identity and multi-tenancy operations.
src/Backend/Features/Tenants · high confidence
Architecture
Backend service registration and middleware pipeline consolidated into Web layer
The backend's service registration, middleware configuration, and endpoint mapping have been unified into the new \AditiKraft.Krafter.Backend.Web\ namespace. A new \HostingExtensions\ class now centrally registers all backend services (including database, authentication, multi-tenancy, SignalR, and background jobs) and configures the middleware pipeline (exception handling, multi-tenancy, and auth). This consolidation supports both standalone backend hosting and combined UI/backend hosting scenarios. Additionally, the route registration interface and application service auto-registration logic have been moved and renamed to reflect this new organizational structure.
src/AditiKraft.Krafter.Backend/Web · high confidence
Behavioural changes
Apply Aditi Kraft brand styling to the web client
The web client now uses the Aditi Kraft brand identity, featuring a new CSS theme in app.css that defines a specific color palette (blues, grays, and semantic colors) and typography for both light and dark modes, mapped to the Radzen component library. Additionally, a complete set of brand assets has been added, including animated SVG loading indicators and horizontal/vertical logos in multiple sizes and color variants, ensuring consistent visual branding across the interface.
src/UI/AditiKraft.Krafter.UI.Web.Client/wwwroot · high confidence
Auth feature files migrated to new namespace and structure
The authentication feature files (Login, RefreshToken, ExternalLogin) have been moved from the legacy 'Backend' namespace to 'AditiKraft.Krafter.Backend.Features.Auth' and updated to use the new 'ApplicationUser' and 'ApplicationRole' types instead of the previous 'KrafterUser' and 'KrafterRole'. The ExternalLogin handler now correctly assigns the 'Basic' role to new external users and uses the centralized 'AppUrls' configuration for Google redirect URIs, replacing the previous direct configuration access.
src/AditiKraft.Krafter.Backend/Features/Auth · high confidence
Auth service refactors to use new domain models and response types
The authentication logic in the backend has been updated to align with the new application domain structure. The TokenService now operates on the ApplicationUser model instead of the previous KrafterUser, and database interactions use the new ApplicationDbContext. Additionally, the service's public API has changed: the GenerateTokensAndUpdateUser method now returns a generic Response wrapper for success and unauthorized cases, and JWT claims are generated using the new AppClaimTypes constants.
src/AditiKraft.Krafter.Backend/Features/Auth/Common · high confidence
Authorization handler refactored to support concurrent tenant-scoped checks
The permission authorization logic has been restructured to resolve concurrency issues when handling multiple simultaneous authorization requests. The handler now explicitly manages tenant context via a dedicated tenant getter service and creates isolated service scopes for each check, ensuring that concurrent Blazor authorization flows do not share DbContext instances incorrectly. Additionally, the code has been migrated to the new AditiKraft.Krafter namespace structure, and the policy extension method now utilizes the updated AppClaimTypes and PermissionDefinition classes for policy name generation.
src/AditiKraft.Krafter.Backend/Web/Authorization · high confidence
Backend API configuration refactored with /api prefix, PostgreSQL-only database, and Scalar documentation
The backend web configuration has been reorganized under the new namespace and folder structure. API endpoints are now prefixed with /api, enforced via the new RouteConfiguration. Database connectivity is simplified to use only PostgreSQL (Npgsql) and relies on the 'appDb' connection string, removing previous MySQL support and the multi-database switch. CORS handling is now centralized in a new CorsConfiguration class that supports root UI origins and optional tenant subdomains. API documentation has switched from Swagger UI to Scalar, using the OpenAPI library instead of the legacy SwaggerGen.
src/AditiKraft.Krafter.Backend/Web/Configuration · high confidence
Backend service initialization and configuration structure
The backend application now initializes via a new Program.cs entry point that configures forwarded headers for proxy support, integrates Aspire service defaults, and sets up CORS, Swagger, and the multi-tenant middleware pipeline. Configuration is standardized through appsettings files defining SMTP, database connection strings, JWT security settings, and URL structures for root UI, API base URLs, and tenant base domains. The project also introduces a centralized error handling model with specific exception types (Forbidden, Unauthorized, NotFound, Conflict) and provides an Agents.md guide detailing the Vertical Slice Architecture conventions for organizing features, handlers, routes, and entities.
src/AditiKraft.Krafter.Backend · high confidence
Background jobs and email notifications restructured with TickerQ integration
The background job infrastructure has been reorganized under \Infrastructure/Jobs\, introducing a dedicated \BackgroundJobsContext\ for TickerQ persistence and a \Jobs\ class that defines email-sending tasks via the \\[TickerFunction\]\ attribute. The \JobService\ now relies on \ITimeTickerManager\ to enqueue jobs, removing the previous dependency on tenant-specific logic. Email notification capabilities have been consolidated into the \Infrastructure/Notifications\ folder, featuring a new \IEmailService\ interface, an \EmailService\ implementation that supports cancellation tokens, and configuration for SMTP settings. Additionally, the TickerQ dashboard is now explicitly configured with basic authentication enabled.
src/AditiKraft.Krafter.Backend/Infrastructure/Jobs · high confidence
Build system migration to Fallout and new template publishing capability
The build system has migrated from the Nuke framework to Fallout, updating all underlying build infrastructure and imports. As a result of this refactor, the default build target has changed from publishing container images to publishing the Krafter template as a NuGet package. This new workflow includes a dedicated target to pack the template project (AditiKraft.Krafter.Templates.csproj) with a configurable version (defaulting to 0.0.13) and a subsequent target to push the resulting package to NuGet.org, requiring a NuGet API key parameter.
build · high confidence
Centralized Refit client configuration with tenant-aware routing and date handling
The web client now uses a unified Refit infrastructure to manage API communication. A new \RefitServiceExtensions\ class centrally registers API clients (such as Users, Roles, Tenants, and Auth) with specific HTTP message handlers: \RefitTenantHandler\ rewrites request URLs based on the current tenant and execution context (using the backend URL for server-side and direct API calls, or the client base address for BFF/auth flows), while \RefitAuthHandler\ handles authentication for backend APIs. Additionally, a \UiDateTimeJsonConverter\ ensures consistent date serialization by converting outgoing dates to UTC and localizing incoming responses only in browser environments, preventing timezone mismatches.
src/UI/AditiKraft.Krafter.UI.Web.Client/Infrastructure/Refit · high confidence
Centralized tenant-aware URL resolution for HTTP requests
The application now uses a new TenantIdentifier service to dynamically resolve tenant-specific backend API URLs and root domains based on the current UI context (Web or WebAssembly). This change ensures that HTTP requests are correctly routed to the appropriate tenant's backend, supporting both multi-tenant and single-tenant modes by extracting tenant identifiers from the UI host or falling back to a default, while also handling server-side versus client-side request differences.
src/UI/AditiKraft.Krafter.UI.Web.Client/Infrastructure/Http · high confidence
Client authentication infrastructure restructured with coordinated token refresh
The client-side authentication layer in the Web Client has been reorganized into a dedicated \Infrastructure/Auth\ module, introducing a new \AuthStorageService\ for local token management and a \TokenRefreshCoordinator\ to synchronize concurrent refresh requests. The \RefitAuthHandler\ now automatically intercepts outgoing API calls to refresh expired access tokens and retry unauthorized requests, while the \UIAuthenticationStateProvider\ handles initial state restoration from server-side cookies and ensures permissions are correctly mapped to claims. This change centralizes auth logic, improves resilience against token expiration during active use, and aligns the client's authentication flow with the unified backend contracts.
src/UI/AditiKraft.Krafter.UI.Web.Client/Infrastructure/Auth · high confidence
Database schema updates and migration infrastructure reorganization
This change introduces several database schema adjustments and reorganizes the migration files. In the main application database, the unique index on the role name has been removed, and the background jobs context now enforces a 'Restrict' delete behavior for parent-child job relationships while adding a concurrency token to the lock holder field. In the tenant database, the tenant identifier is now required, and a new migration adds a unique expression index on the lowercased tenant identifier to prevent duplicates among non-deleted tenants. Additionally, the default seed data for the root tenant has been updated to use '[e-mail redacted]' and 'root' as the identifier. The migration infrastructure itself has been reorganized: files have been moved from the old 'Backend' path to 'AditiKraft.Krafter.Backend/Migrations', namespaces updated, and the design-time context factory refactored to use a centralized helper for connection strings.
src/AditiKraft.Krafter.Backend/Migrations · high confidence
Introduce Aspire AppHost with PostgreSQL and automated migrations
The development environment now uses an Aspire AppHost to orchestrate the application stack, replacing previous configurations. This change introduces a PostgreSQL database server with PgAdmin, an executable-based database migrator that runs before the backend API starts, and wiring for the backend and web UI projects. Configuration has been updated to include Aspire hosting logs and default PostgreSQL credentials, streamlining local development setup.
aspire/AditiKraft.Krafter.Aspire.AppHost · high confidence
Introduce multi-tenant architecture with URL routing and permission contracts
This change establishes the foundational contracts for a multi-tenant system. It adds \AppUrls\ to handle complex URL resolution, including validation for tenant base domains and subdomain-based tenant identification. A new \TenancyMode\ enum and \TenantSettings\ class (defaulting to \Multi\) define the operational mode. The \PermissionCatalog\ is introduced to centralize permission definitions (e.g., for Users, Tenants, Roles) into Root, Admin, and Basic sets. Additionally, common models like \Response\<T\>\, \CurrentTenantDetails\, and \GetRequestInput\ are standardized, and various backend symbols (routes, claims, actions) are renamed and moved into the \Contracts\ namespace for consistency.
src/AditiKraft.Krafter.Contracts/Common · high confidence
Introduction of new Blazor WebAssembly application shell and theme handling
The application now uses a new \App.razor\ component as the root layout, which integrates Radzen UI components, Bit.BlazorUI.Extras, and Google Fonts. A key behavioral change is the introduction of server-side theme persistence: the application now reads the \AppTheme\ cookie from the HTTP context during initialization to determine whether to render in Light or Dark mode, falling back to client-side settings if the cookie is absent.
src/UI/AditiKraft.Krafter.UI.Web/Components · high confidence
Migrate shared contracts to dedicated namespace with validation and null-safety updates
The application's shared data contracts have been moved from the internal \Backend.Features.Roles.\_Shared\ location into the public \AditiKraft.Krafter.Contracts\ namespace, establishing a clear boundary for reusable types. This migration introduces FluentValidation rules for authentication, user, role, and tenant requests (such as email format checks and password length constraints) and updates several DTOs to use nullable reference types and modern C\# collection initializers for improved null safety.
src/AditiKraft.Krafter.Contracts/Contracts · high confidence
New client infrastructure services and namespace migration
The client application now includes a new set of infrastructure services under the \AditiKraft.Krafter.UI.Web.Client.Infrastructure.Services\ namespace, replacing the previous \Krafter.UI.Web.Client\ namespace. This introduces \ApiCallService\ for standardized API error handling and notifications, \MenuService\ which dynamically hides the Tenant Management menu in single-tenant mode, \ThemeManager\ for handling light/dark/auto theme preferences via JavaScript interop, and \FormFactor\ to identify the WebAssembly platform. Additionally, \ValidationErrorResponse\ is added to support FluentValidation error parsing, while \LayoutService\, \NullHttpContextAccessor\, and \IFormFactor\ have been migrated to the new namespace with minor code cleanup.
src/UI/AditiKraft.Krafter.UI.Web.Client/Infrastructure/Services · high confidence
New middleware pipeline and refined error handling for multi-tenant applications
The middleware layer now includes a new authentication pipeline (AuthMiddleware) that standardizes the order of authentication, current-user initialization, and authorization. A new MultiTenantServiceMiddleware handles tenant resolution, supporting both single-tenant mode (using a default tenant) and multi-tenant mode (resolving tenants via host, headers, or query parameters), while returning 404s for invalid or reserved tenant identifiers. The existing ExceptionMiddleware has been refactored to improve user experience: it now re-throws exceptions for non-API requests (such as Blazor pages or static files) to allow standard ASP.NET Core error pages to display instead of raw JSON, and it simplifies database error handling by removing specific SQL Server exception logic in favor of a generic database error message, while also updating internal type references (e.g., KrafterException to AppException).
src/AditiKraft.Krafter.Backend/Web/Middleware · high confidence
Persistence layer renamed and simplified with new tenant context
The main database context has been renamed from KrafterContext to ApplicationDbContext, and a new TenantDbContext has been introduced to handle tenant administration data separately. This change aligns the codebase with updated namespace conventions (AditiKraft.Krafter.Backend) and standardizes entity naming (e.g., KrafterUser to ApplicationUser). Additionally, temporal table support has been removed from the model builder, simplifying the schema generation for history entities to use standard columns with default timestamps instead of database-specific temporal features.
src/AditiKraft.Krafter.Backend/Infrastructure/Persistence · high confidence
Real-time hub now enforces tenant isolation for message routing
The new RealtimeHub implementation ensures that real-time messages are scoped to specific tenants. Upon connection, the hub retrieves the current tenant context and adds the client to a dedicated group (e.g., GroupTenant-{tenantId}). Subsequent messages are only sent to clients within that specific tenant group, preventing cross-tenant data leakage. If authentication or tenant context is missing, the connection is rejected.
src/AditiKraft.Krafter.Backend/Infrastructure/Realtime · high confidence
Realtime contract types moved to new namespace
The SignalR method constants (ReceiveMessage, SendMessage, ComponentAddedOrRemovedOrRestored) have been relocated from the Backend.Hubs namespace to AditiKraft.Krafter.Contracts.Realtime. This structural change updates the namespace declaration and flattens the class hierarchy for these contract definitions, which may require consumers to update their using statements or references to the new location.
src/AditiKraft.Krafter.Contracts/Realtime · high confidence
Rebrand to Aditi Kraft and introduce branded UI components
The application has been rebranded from Krafter to Aditi Kraft, reflected in the namespace migration from \Krafter.UI.Web.Client\ to \AditiKraft.Krafter.UI.Web.Client\ across the Common components. This change introduces new branded UI elements, including a \Logo\ component that dynamically switches between light and dark variants based on the user's theme preference, and a \LoadingIndicator\ component with five size options. The main layout now features a centered footer with the Aditi Kraft copyright text, and the mobile header has been adjusted to hide the logo on smaller screens to prevent layout flashing. Additionally, the \NavigationItem\ component now displays 'New' and 'Updated' badges on menu items, and the \DebouncedSearchInput\ component has been added to support debounced search functionality with optional manual trigger buttons.
src/UI/AditiKraft.Krafter.UI.Web.Client/Common · high confidence
Redesigned Error page with Radzen UI components
The Error page has been updated to use Radzen components, featuring a centered layout with an error icon, styled text, and action buttons to navigate home or retry the request. The page now displays the request ID when available and uses CSS variables for consistent theming.
src/UI/AditiKraft.Krafter.UI.Web/Components/Pages · high confidence
Refactor authentication service registration and JWT configuration
The authentication setup in the backend has been reorganized to improve modularity and clarity. The \ConfigureJwtBearerOptions\ class has been extracted into its own dedicated file, separating JWT-specific configuration logic from the main service registration. The \AuthenticationRegistration\ class, renamed from \DependencyInjection\, now centralizes the registration of authentication services, including JWT, Google OAuth, and current user middleware. Additionally, the Google OAuth client configuration has been updated to handle missing configuration values gracefully by providing empty string defaults, preventing potential null reference issues during startup.
src/AditiKraft.Krafter.Backend/Web/Authentication · high confidence
Refactored user and role management with unified permission synchronization
The Users and Roles features have been restructured to use a shared \RolePermissionService\ for consistent permission handling across create, update, and delete operations. The \ApplicationRole\ and \ApplicationUser\ entities now enforce tenant boundaries and soft-delete behaviors, with the \RolePermissionService.SynchronizeAsync\ method managing claim additions, removals, and soft-deletes in a single transaction. User creation and updates delegate to \IUserMutationService\ for role synchronization and email job enqueuing, while route definitions have been standardized to use \ApiRoutes\ and \RouteSegment\ constants for consistent endpoint paths.
src/AditiKraft.Krafter.Backend/Features/Users · high confidence
Refactored user identity models and services into a shared common module
The user management logic has been reorganized into a new \Features/Users/Common\ directory, renaming the core identity entities from \KrafterUser\ to \ApplicationUser\ (along with \ApplicationUserRole\, \ApplicationUserClaim\, etc.) to align with standard ASP.NET Core Identity conventions. This change introduces dedicated interfaces and implementations for user operations: \IUserMutationService\ and \UserMutationService\ now handle user creation, profile updates, and email changes (including syncing tenant admin emails), while \IUserService\ and \UserService\ provide permission checking capabilities. The refactoring also consolidates seed data constants for the root user and tenant within the new service layer.
src/AditiKraft.Krafter.Backend/Features/Users/Common · high confidence
Removal of legacy Blazor WebAssembly App shell and imports
The legacy Blazor WebAssembly application shell has been removed from the UI components. This includes the deletion of the main App.razor layout (which previously handled theme initialization and Radzen UI styling), its code-behind, the Error.razor page, and the global \_Imports.razor file. Users will no longer see the previous client-side rendering structure for these core components, indicating a shift away from the standalone WASM hosting model.
src/UI/Krafter.UI.Web/Components · high confidence
Removal of legacy backend scaffolding and configuration files
This change removes a large set of legacy files from the \src/Backend\ directory, including the CORS configuration, authentication and multi-tenant middleware, custom exception classes, and various shared models and interfaces. It also deletes the SignalR hub, background job context, and database context implementations, along with the main \Program.cs\ entry point. These deletions indicate a significant restructuring or cleanup of the backend architecture, likely in preparation for a new implementation or migration.
src/Backend · high confidence
Removal of legacy client infrastructure services
The \CommonService\, \FormFactor\, \HttpService\, \MenuService\, and \ThemeManager\ classes have been removed from the \Infrastructure/Services\ directory. This eliminates the previous custom implementations for HTTP communication, menu management, theme handling, and form factor detection, indicating a shift in how the client application manages these core functionalities.
src/UI/Krafter.UI.Web.Client/Infrastructure/Services · high confidence
Removal of local storage service for authentication tokens
The \IKrafterLocalStorageService\ interface and its \KrafterLocalStorageService\ implementation have been removed from the application. This eliminates the client-side capability to cache authentication tokens, refresh tokens, permissions, and their expiry dates in local storage, meaning the application will no longer persist these credentials in the browser's local storage.
src/UI/Krafter.UI.Web.Client/Infrastructure/Storage · high confidence
Removed legacy static assets and client-side theme logic
The application has removed its previous static branding and styling resources, including the main app.css file, all SVG logo variants (horizontal and vertical, in light and dark modes), loading indicators, the favicon, and the JavaScript helper script responsible for detecting system theme preferences and mobile device status. This cleanup eliminates the old CSS-based theming and client-side theme detection logic, aligning the client with the new design system and Radzen theming approach.
src/UI/Krafter.UI.Web.Client/wwwroot · high confidence
Rename projects and namespaces to AditiKraft.Krafter prefix
The Aspire Service Defaults library and the Backend Features module have been renamed to use the AditiKraft.Krafter namespace prefix. This change updates the project structure and code namespaces from the previous Krafter/Backend naming convention to AditiKraft.Krafter, ensuring consistent branding across the solution's core infrastructure and feature interfaces.
aspire/AditiKraft.Krafter.Aspire.ServiceDefaults, src/AditiKraft.Krafter.Backend/Features · high confidence
Renames and reorganizes backend common modules
The backend's shared code has been restructured: namespaces and file paths are updated to the AditiKraft.Krafter.Backend.Common hierarchy, and the CurrentUser implementation is moved into the Common/Auth folder. Tenant management interfaces and the CurrentTenantService are consolidated under Common/Tenants, with a dedicated registration method for DI. Entity base classes and interfaces (ITenant, ISoftDelete, IHistory) are extracted into Common/Entities, and utility extensions (paging, request origin, IP address) are centralized in Common/Extensions. The PasswordGenerator is also moved to Common and now guarantees at least one uppercase letter, lowercase letter, digit, and special character in generated passwords.
src/AditiKraft.Krafter.Backend/Common · high confidence
Replaced Kiota-generated API client with Refit
The auto-generated Kiota request builders in the web client (e.g., ApiRequestBuilder, CronTickerRequestBuilder) have been removed, replacing the previous Kiota-based HTTP integration with Refit. This change alters how the client constructs and executes API calls, shifting from the Kiota abstraction layer to Refit's interface-based approach.
src/UI/Krafter.UI.Web.Client/Client · high confidence
Single-host deployment variant with PostgreSQL and integrated migration
The aspire-single location now provides a single-host deployment model where the API and Blazor UI run in one process, backed by a PostgreSQL database instead of the previous Redis/Garnet cache. The AppHost programmatically provisions the Postgres server and database, runs a database migrator executable before the application starts, and configures the app to use its own HTTPS endpoint for internal server-to-server calls, simplifying local development and single-instance deployments.
aspire-single · high confidence
Support for single-tenant mode in tenant resolution
The new TenantFinderService now bypasses database lookups when the system is configured for single-tenant mode (TenancyMode.Single), immediately returning the default tenant for any identifier. This change allows the application to operate in a single-tenant configuration without requiring specific tenant identifiers in requests, while still enforcing standard checks for tenant activity and validity in multi-tenant scenarios.
src/AditiKraft.Krafter.Backend/Infrastructure/Persistence/Tenants · high confidence
Tenant data seeding and link building logic consolidated
The backend now centralizes tenant initialization and URL construction within the \Features/Tenants/Common\ area. A new \DataSeedService\ handles the creation of default roles (Admin, Basic) with specific permission sets, generates a root user for new tenants (sending a welcome email with generated credentials), and ensures the root tenant has a predefined root user. Additionally, a \TenantLinkBuilder\ utility was added to construct tenant-specific UI links, and the core \Tenant\ model was moved and updated to enforce a non-nullable \Identifier\ property.
src/AditiKraft.Krafter.Backend/Features/Tenants/Common · high confidence
Tenant management API restructured with stricter validation and root tenant protection
The Tenants feature has been refactored to enforce stricter data integrity and security. Tenant creation now explicitly sets the \CreatedOn\ timestamp to UTC and validates that the expiry date (\ValidUpto\) is provided in UTC, preventing truncation errors. The root tenant is now protected from modification of its identifier, admin email, active status, and validity date. Additionally, tenant deletion has been converted to a soft-delete operation (setting \IsDeleted\), and the API routes have been standardized under \ApiRoutes.Tenants\ with consistent permission checks.
src/AditiKraft.Krafter.Backend/Features/Tenants · high confidence
Unified server-side authentication with cookie-based token persistence and proactive refresh
The web application now handles authentication entirely on the server for both split-host and single-host deployment modes. A new AuthCookieMiddleware intercepts backend auth responses to persist tokens as HttpOnly cookies, while a centralized AuthStorageService manages these cookies and a HybridCache for permissions. BlazorJwtBearerEvents now reads tokens from these cookies and proactively refreshes expired tokens during server-side rendering, ensuring seamless user sessions. The system also enriches user identities with permission claims and adapts challenge/forbidden responses based on the hosting mode (redirecting for browsers, returning JSON for API calls).
src/UI/AditiKraft.Krafter.UI.Web/Infrastructure · high confidence
Unified single-host deployment with configurable UI URLs and updated security defaults
The application now supports a single-host deployment model where the backend API and Blazor UI run in the same process, replacing the previous distributed setup. This change introduces configurable root UI URLs and tenant base domains via the \Urls\ section in \appsettings.json\, allowing for flexible hosting scenarios including sibling UI domains. Security defaults have been adjusted, specifically increasing the JWT token expiration time from 3 to 60 minutes. Additionally, authentication handling is unified via \AuthCookieMiddleware\ to ensure consistent cookie setting for both login and logout operations across the new hosting mode.
src-single/UI/AditiKraft.Krafter.UI.Web · high confidence
Unify UI host configuration and centralize authentication middleware
The UI web host now supports configurable root URLs and tenant base domains via the \Urls\ section in \appsettings.json\, enabling sibling UI domain setups. Authentication is centralized through a new \AuthCookieMiddleware\ that intercepts login, refresh, and external-auth responses to set HttpOnly cookies, ensuring consistent cookie behavior across hosting modes. The application entry point (\Program.cs\) has been restructured to bind JWT settings, register UI host services, and map token endpoints under a unified API prefix, while global usings have been consolidated to reduce boilerplate.
src/UI/AditiKraft.Krafter.UI.Web · high confidence
Test coverage
Added configuration tests for CORS, tenant URL routing, and UI URL settings; Added persistence and design-time configuration tests; Added test coverage for tenant management, validation, and real-time hub behavior; Added tests for authentication token refresh coordination; Added tests for role permission handling and user mutation logic; Added tests for tenant-aware permission authorization.
Dependencies
Upgrade to .NET 10 and modernize dependencies
The project has been upgraded from .NET 9 to .NET 10, updating the target framework across all backend, UI, and Aspire components. This release replaces the Nuke build system with Fallout, swaps the Redis-based caching infrastructure for PostgreSQL (using \Microsoft.Extensions.Caching.Postgres\ and \Aspire.Hosting.PostgreSQL\), and migrates API client generation from Kiota to Refit. Additionally, the API documentation UI has been updated from Swagger to Scalar, and the Radzen.Blazor UI library has been upgraded to version 8.3.2.
(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 52 → 59 (+6.6)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 76 → 77 (+1.4)
- Architecture 65 → 66 (+1.4)
- Maturity 65 → 68 (+3.4)
- Readiness 39 → 54 (+15.3)
- Security 70 → 70 (-0.4)
- Event-Driven 100 (new)
- Accessibility 59 → 55 (-4.4)
- Performance 74 → 74 (+0.0)
Resolved (35)
- Bounded contexts not declared
- Build did not complete in the analyzer
- Change coupling: IRolesApi.cs ↔ IUsersApi.cs (src/UI/AditiKraft.Krafter.UI.Web.Client/Infrastructure/Refit/IRolesApi.cs)
- CommentedOutCode (src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Auth/Common/IExternalAuthService.cs)
- Dead code: ConfigureCreatedOnColumn (src/AditiKraft.Krafter.Backend/Infrastructure/Persistence/TenantDbContext.cs)
- Duplicate response types with divergent signatures. The non-generic Response class and the generic Response<T> class both provide a Success method. However, Response<T>.Success accepts a payload (T data) while Response.Success does not. This creates confusion about which type to use for API responses and breaks the generic/non-generic consistency pattern.
- Duplicated block (10 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Users/Common/UserService.cs)
- Duplicated block (11 lines × 3) (src/AditiKraft.Krafter.Backend/Features/Roles/DeleteRole.cs)
- Duplicated block (16 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Tenants/Common/DataSeedService.cs)
- Duplicated block (16 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web/Services/AuthStorageServiceServer.cs)
- Duplicated block (17 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web/Services/AuthStorageServiceServer.cs)
- Duplicated block (20 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Users/CreateUser.cs)
- Duplicated block (22 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Roles/CreateRole.cs)
- Duplicated block (6 lines × 2) (src/AditiKraft.Krafter.Backend/Web/Middleware/MultiTenantServiceMiddleware.cs)
- Duplicated block (7 lines × 2) (src/AditiKraft.Krafter.Backend/Infrastructure/Persistence/ApplicationDbContext.cs)
- Duplicated block (8 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Tenants/Common/DataSeedService.cs)
- Duplicated block (9 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Roles/Common/MultiSelectRoleDropDownDataGrid.razor.cs)
- ExceptionMiddleware.InvokeAsync (cyclomatic 19) (src/AditiKraft.Krafter.Backend/Web/Middleware/ExceptionMiddleware.cs)
- High: security finding (details withheld)
- High: security finding (details withheld)
- …and 15 more
New (49)
- CommentedOutCode (aspire/AditiKraft.Krafter.Aspire.ServiceDefaults/Extensions.cs)
- CommentedOutCode (src/UI/AditiKraft.Krafter.UI.Web.Client/Routes.razor)
- Coverage not measured — no coverage collector is wired up
- Duplicated block (11 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Roles/Common/MultiSelectRoleDropDownDataGrid.razor.cs)
- Duplicated block (11 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web.Client/Features/Roles/Common/SingleSelectRoleDropDownDataGrid.razor.cs)
- Duplicated block (11 lines × 3) (src/AditiKraft.Krafter.Backend/Features/Roles/DeleteRole.cs)
- Duplicated block (11–12 lines × 2) (src/AditiKraft.Krafter.Contracts/Common/Models/CommonDtoProperty.cs)
- Duplicated block (12 lines × 3) (src/AditiKraft.Krafter.Backend/Features/Roles/Common/ApplicationRoleClaim.cs)
- Duplicated block (13 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Tenants/Common/Tenant.cs)
- Duplicated block (14 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Users/GetUsers.cs)
- Duplicated block (16 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web/Infrastructure/Auth/AuthStorageServiceServer.cs)
- Duplicated block (17 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web.Client/Infrastructure/Services/ApiCallService.cs)
- Duplicated block (17–20 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Users/Common/UserService.cs)
- Duplicated block (21 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Tenants/Common/DataSeedService.cs)
- Duplicated block (42 lines × 2) (src/UI/AditiKraft.Krafter.UI.Web/Infrastructure/Auth/AuthStorageServiceServer.cs)
- Duplicated block (5 lines × 2) (src/AditiKraft.Krafter.Contracts/Common/Models/DeleteRequestInputValidator.cs)
- Duplicated block (5 lines × 3) (src/AditiKraft.Krafter.Backend/Common/Extensions/RequestExtensions.cs)
- Duplicated block (7 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Roles/Common/ApplicationRole.cs)
- Duplicated block (7 lines × 2) (src/AditiKraft.Krafter.Backend/Features/Tenants/CreateTenant.cs)
- Duplicated block (7 lines × 4) (src/AditiKraft.Krafter.Backend/Common/Entities/CommonEntityProperty.cs)
- …and 29 more
Changes since last survey
- 33 commits — 20 feature/other, 13 fixes
By area
- src/UI — 9 commits
- src/AditiKraft.Krafter.Backend — 8 commits
- (root) — 6 commits
- (repo) — 5 commits
- build/Build.cs — 2 commits
- .fallout/build.schema.json — 1 commit
- .github/workflows — 1 commit
- aspire-single/AditiKraft.Krafter.Aspire.AppHost — 1 commit
Notable commits
- fix: Merge pull request #80 from AditiKraft/fix/tenant-validity-utc
- fix: Merge pull request #82 from AditiKraft/fix/grid-theme-refresh
- fix: fix(aspire): run source single-host project
- fix: fix(auth): coordinate server UI token refresh across request scopes
- fix: fix(auth): preserve tenant context and coordinate token refresh
- fix: fix(deps): patch vulnerable openapi package
- fix: fix(template): exclude backend settings from single-host output
- fix: fix(tenants): exclude IP addresses from subdomain detection
- fix: fix(tenants): preserve exact utc expiry
- fix: fix(tenants): save validity dates as utc
- fix: fix(tenants): set CreatedOn on create and cover validators with tests
- fix: fix(ui): preserve grid visibility during refresh
- fix: fix(ui-roles): block saves until role permissions load successfully
- change: Merge pull request #79 from AditiKraft/refactor/project-structure
- change: Merge pull request #81 from AditiKraft/feat/local-time-utc-storage
- change: Merge pull request #83 from AditiKraft/changes/migrate-nuke-to-fallout
- change: chore(build): bump template version to 0.0.11
- change: chore(build): bump template version to 0.0.12
- change: chore(build): bump template version to 0.0.13
- change: chore(build): migrate from NUKE to Fallout build
- …and 13 more
API surface
- 1 added · 0 removed (a removed endpoint is potentially breaking)
Added endpoints (1)
- GET /
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
AditiKraft/Krafter 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 21 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 265c43c8b924aff96439320c5060b66753dacf0e — 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-fa71c66cabd8.