🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Svrnty Inc. <eng@svrnty.com>
5.8 KiB
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
# 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 registrationSvrnty.CQRS.MinimalApi— HTTP endpoint mappingSvrnty.CQRS.DynamicQuery— PoweredSoft.DynamicQuery integrationSvrnty.CQRS.DynamicQuery.MinimalApi— Dynamic query HTTP endpointsSvrnty.CQRS.FluentValidation— Validation helpersSvrnty.CQRS.Grpc— gRPC service supportSvrnty.CQRS.Grpc.Generators— Source generator for .proto + gRPC service implementations
Sample: Svrnty.Sample — HTTP + gRPC demo
Architecture
Metadata-Driven Discovery
services.AddCommand<TCommand, THandler>()registers handler + createsICommandMetaICommandDiscovery/IQueryDiscoveryquery all registered metadata from DI- 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<TSource, TDestination>with filters, sorts, groups, aggregatesIQueryableProvider<TSource>provides base IQueryableIAlterQueryableService<TSource, TDestination>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. <eng@svrnty.com>
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
JPbranch 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/<name>.body.mdthen runperfecto build <name> - To update shared conventions: edit
JP/CLAUDE.md, updateperfecto/shared/, then runperfecto 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.