dotnet-cqrs/CLAUDE.md
Mathias Beaulieu-Duncan a4525bad6a Add Claude Code harness: rules, skills, hooks, and editorconfig
- Add path-specific rules for commands/queries, dynamic queries, validation, and gRPC
- Add /add-command, /add-query, /add-dynamic-query scaffolding skills
- Add project settings with post-edit formatting, proto validation, and build-gate hooks
- Add .editorconfig codifying existing code style conventions
- Trim CLAUDE.md from 414 to 130 lines (domain details moved to rules)
- Add .harness-version tracking for the shared claude-harness repo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 03:30:27 -04:00

6.1 KiB

CLAUDE.md

This file provides guidance to AI agents when working with code in this repository.

For domain-specific patterns (commands, queries, validation, gRPC, dynamic queries), see .claude/rules/. For scaffolding commands, see .claude/skills/ (/add-command, /add-query, /add-dynamic-query).

Project Overview

This is Svrnty.CQRS, a modern implementation of Command Query Responsibility Segregation (CQRS) for .NET 10. It was forked from PoweredSoft.CQRS and provides:

  • CQRS pattern implementation with command/query handlers exposed via HTTP or gRPC
  • Automatic HTTP endpoint generation via Minimal API
  • Automatic gRPC endpoint generation with source generators and Google Rich Error Model validation
  • Dynamic query capabilities (filtering, sorting, grouping, aggregation)
  • FluentValidation support with RFC 7807 Problem Details (HTTP) and Google Rich Error Model (gRPC)

Solution Structure

The solution contains projects organized by responsibility:

Abstractions (interfaces and contracts only):

  • Svrnty.CQRS.Abstractions - Core interfaces (ICommandHandler, IQueryHandler, discovery contracts)
  • Svrnty.CQRS.DynamicQuery.Abstractions - Dynamic query interfaces (multi-targets netstandard2.1 and net10.0)
  • Svrnty.CQRS.Grpc.Abstractions - gRPC-specific interfaces and contracts

Implementation:

  • Svrnty.CQRS - Core discovery and registration logic
  • Svrnty.CQRS.MinimalApi - Minimal API endpoint mapping for commands/queries
  • Svrnty.CQRS.DynamicQuery - PoweredSoft.DynamicQuery integration for advanced filtering
  • Svrnty.CQRS.DynamicQuery.MinimalApi - Minimal API endpoint mapping for dynamic queries
  • Svrnty.CQRS.FluentValidation - Validation integration helpers
  • Svrnty.CQRS.Grpc - gRPC service implementation support
  • Svrnty.CQRS.Grpc.Generators - Source generator for .proto files and gRPC service implementations

Sample:

  • Svrnty.Sample - Demo project showcasing both HTTP and gRPC endpoints

Key Design Principle: Abstractions projects contain ONLY interfaces/attributes with minimal dependencies. Implementation projects depend on abstractions.

Build Commands

dotnet restore            # Restore dependencies
dotnet build              # Build entire solution
dotnet build -c Release   # Build in Release mode
dotnet pack -c Release -o ./artifacts -p:Version=1.0.0  # Create NuGet packages

Testing

No test projects currently exist. When adding tests:

  • Place them in a tests/ directory
  • Name them with .Tests suffix (e.g., Svrnty.CQRS.Tests)

Architecture

Metadata-Driven Discovery

The framework uses a metadata pattern for runtime discovery:

  1. services.AddCommand<TCommand, THandler>() registers the handler in DI and creates ICommandMeta metadata as a singleton
  2. Discovery services (ICommandDiscovery, IQueryDiscovery) query all registered metadata from DI
  3. Endpoint mapping (HTTP and gRPC) uses discovery to dynamically generate endpoints at startup

Key Files:

  • Svrnty.CQRS.Abstractions/Discovery/ - Metadata interfaces
  • Svrnty.CQRS/Discovery/ - Discovery implementations
  • Svrnty.CQRS.MinimalApi/EndpointRouteBuilderExtensions.cs - HTTP endpoint generation
  • Svrnty.CQRS.DynamicQuery.MinimalApi/EndpointRouteBuilderExtensions.cs - Dynamic query endpoint generation
  • Svrnty.CQRS.Grpc.Generators/ - gRPC service generation via source generators

Integration

Commands and queries can be exposed via HTTP (Minimal API), gRPC, or both simultaneously. The fluent configuration API handles all wiring:

builder.Services.AddSvrntyCqrs(cqrs =>
{
    cqrs.AddGrpc(grpc => grpc.EnableReflection());
    cqrs.AddMinimalApi();
});

app.UseSvrntyCqrs(); // Maps all endpoints

See Svrnty.Sample/Program.cs for a complete working example.

Package Configuration

Key Dependencies

  • Microsoft.Extensions.DependencyInjection.Abstractions: 10.0.0
  • FluentValidation: 11.11.0
  • PoweredSoft.DynamicQuery: 3.0.1
  • Grpc.AspNetCore: 2.68.0+
  • Grpc.StatusProto: 2.71.0+ (Rich Error Model)
  • Microsoft.CodeAnalysis.CSharp: 5.0.0-2.final (source generators, targets netstandard2.0)

Publishing

NuGet packages publish automatically via GitHub Actions (.github/workflows/publish-nugets.yml) when a release is created. Tag becomes the version.

# Manual publish
dotnet pack -c Release -o ./artifacts -p:Version=1.2.3
dotnet nuget push ./artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key YOUR_KEY

Development Workflow

Adding a New Feature to the Framework:

  1. Add interface to appropriate Abstractions project
  2. Implement in corresponding implementation project
  3. Update ServiceCollectionExtensions with registration method
  4. When extending discovery, create corresponding metadata classes (implement ICommandMeta/IQueryMeta)
  5. Update package version and release notes

C# 14 Language Features

The project uses C# 14. Be aware of these reserved keywords:

  • field: Contextual keyword in property accessors for implicit backing fields
  • extension: Reserved for extension containers; use @extension for identifiers

Important Implementation Notes

  1. Async Everywhere: All handlers are async. Always support CancellationToken.
  2. Generic Type Safety: Framework relies heavily on generics. Maintain strong typing.
  3. Endpoint Mapping Timing: Discovery services must be registered before calling UseSvrntyCqrs().
  4. AOT Compatibility: IsAotCompatible is set but not enforced — many dependencies are not AOT-compatible.

Common Code Locations

  • Handler interfaces: Svrnty.CQRS.Abstractions/ICommandHandler.cs, IQueryHandler.cs
  • Discovery: Svrnty.CQRS/Discovery/
  • Service registration: */ServiceCollectionExtensions.cs in each project
  • HTTP endpoints: Svrnty.CQRS.MinimalApi/EndpointRouteBuilderExtensions.cs
  • Dynamic queries: Svrnty.CQRS.DynamicQuery/DynamicQueryHandler.cs
  • gRPC generators: Svrnty.CQRS.Grpc.Generators/
  • Sample: Svrnty.Sample/