# dotnet-cqrs -- Development Guide ## Overview Svrnty.CQRS — modern CQRS implementation for .NET 10. Forked from PoweredSoft.CQRS. Provides command/query handlers exposed via HTTP (Minimal API) or gRPC (source-generated), dynamic query capabilities, FluentValidation with RFC 7807 (HTTP) and Google Rich Error Model (gRPC). ## Tech Stack - **Framework:** .NET 10 / C# 14 - **Packages:** 10 NuGet packages + 1 sample project - **gRPC:** Grpc.AspNetCore 2.68+, source-generated service implementations - **Validation:** FluentValidation 11.11.0 - **Dynamic queries:** PoweredSoft.DynamicQuery 3.0.1 ## Build & Test ```bash # Restore dependencies dotnet restore # Build entire solution dotnet build # Build in Release mode dotnet build -c Release # Create NuGet packages dotnet pack -c Release -o ./artifacts -p:Version=1.0.0 ``` No test projects currently. When adding tests: `tests/` directory, `.Tests` suffix. ## Solution Structure **Abstractions (interfaces only):** - `Svrnty.CQRS.Abstractions` — Core interfaces (ICommandHandler, IQueryHandler) - `Svrnty.CQRS.DynamicQuery.Abstractions` — Dynamic query interfaces (multi-targets netstandard2.1 + net10.0) - `Svrnty.CQRS.Grpc.Abstractions` — gRPC-specific contracts **Implementation:** - `Svrnty.CQRS` — Core discovery and registration - `Svrnty.CQRS.MinimalApi` — HTTP endpoint mapping - `Svrnty.CQRS.DynamicQuery` — PoweredSoft.DynamicQuery integration - `Svrnty.CQRS.DynamicQuery.MinimalApi` — Dynamic query HTTP endpoints - `Svrnty.CQRS.FluentValidation` — Validation helpers - `Svrnty.CQRS.Grpc` — gRPC service support - `Svrnty.CQRS.Grpc.Generators` — Source generator for .proto + gRPC service implementations **Sample:** `Svrnty.Sample` — HTTP + gRPC demo ## Architecture ### Metadata-Driven Discovery 1. `services.AddCommand()` registers handler + creates `ICommandMeta` 2. `ICommandDiscovery` / `IQueryDiscovery` query all registered metadata from DI 3. Endpoint mapping (HTTP/gRPC) uses discovery to dynamically generate endpoints at startup ### Integration Options - **gRPC** (recommended for performance): Source-generated `CommandServiceImpl` / `QueryServiceImpl` - **HTTP** (recommended for web): `MapSvrntyCommands()` / `MapSvrntyQueries()` via Minimal API - **Both**: Dual protocol support in single codebase ### Dynamic Query System - `IDynamicQuery` with filters, sorts, groups, aggregates - `IQueryableProvider` provides base IQueryable - `IAlterQueryableService` for middleware (security filters) - Up to 5 interceptors per query type ## Conventions - Abstractions contain ONLY interfaces/attributes with minimal dependencies - Handler naming: strip "Command"/"Query" suffix, convert to lowerCamelCase (e.g. `CreatePersonCommand` → `createPerson`) - All handlers are async with CancellationToken support - Endpoint mapping happens at startup — discovery must be registered first - FluentValidation: HTTP returns RFC 7807, gRPC returns Google Rich Error Model ## Key Files - Handler interfaces: `Svrnty.CQRS.Abstractions/ICommandHandler.cs`, `IQueryHandler.cs` - Discovery: `Svrnty.CQRS/Discovery/` - Registration: `*/ServiceCollectionExtensions.cs` - HTTP endpoints: `Svrnty.CQRS.MinimalApi/EndpointRouteBuilderExtensions.cs` - gRPC generators: `Svrnty.CQRS.Grpc.Generators/` ## Publishing NuGet packages via GitHub Actions on release: `.github/workflows/publish-nugets.yml` ## What NOT to Do - Do NOT modify abstractions projects to add implementation dependencies - Do NOT skip CancellationToken in handler signatures - Do NOT call `MapSvrntyCommands()` before registering discovery services - Do NOT add heavy dependencies to abstractions packages ## Critical Rules ### Commit Authorship All AI-authored commits MUST use: ``` Co-Authored-By: Svrnty Inc. ``` NEVER use: - Third-party AI tool names (e.g. "Claude") in any Co-Authored-By - Third-party AI company names (e.g. "Anthropic") in any Co-Authored-By - Third-party AI tool names in commit messages ### Documentation References - Do NOT reference third-party AI tool names as product names in any documentation - Use "agent runtime", "agent CLI", or "Svrnty runtime" instead - CLAUDE.md files keep their filename (industry standard) but content must not mention third-party AI tool names as products ### Branch Strategy - All repos use the `JP` branch for active development - Always check which branch you're on before committing ### Cross-Repo Changes - If a change spans multiple repos, commit to each repo separately - Reference the related repo in commit messages when relevant - Run tests in each affected repo before committing ## Documentation Triad This repo maintains three canonical files. Keep them in sync. ### PROJECT.md — What & Why - User perspective. No code, no architecture. - Update when: features added/removed, scope changes, user-facing behaviour changes. ### GRAPH.md — Architecture - Unicode cascade diagrams. Entire file IS the diagram. - Update when: modules added/removed, data flow changes, API surface changes. ### CLAUDE.md — How to Work Here - Assembled by perfecto from shared fragments + repo body. - To update repo content: edit `perfecto/repo/.body.md` then run `perfecto build ` - To update shared conventions: edit `JP/CLAUDE.md`, update `perfecto/shared/`, then run `perfecto build --all` ## GRAPH.md Maintenance This repo contains a `GRAPH.md` file with unicode cascade diagrams showing the architecture. **You MUST update GRAPH.md whenever you**: - Add, remove, or rename modules, directories, or major components - Change data flow, dependencies, or integration points - Modify the public API surface or protocol contracts Keep the diagrams accurate. They are read by non-technical stakeholders.