{"owner":"kurrent-io","repo":"KurrentDB","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\nDetailed reference docs live in `.claude/docs/` — fetch them when working in a specific area.\n\n## Quick Reference: Where to Look\n\n| Working on... | Read |\n|---|---|\n| Core infrastructure, project layout | `.claude/docs/architecture.md` |\n| API v2 services | `.claude/docs/api-v2-patterns.md` |\n| Writing tests | `.claude/docs/testing.md` |\n| Protocol buffers, gRPC | `.claude/docs/protocol-v2.md` |\n| Message bus, enumerators, authorization, indexes | `.claude/docs/patterns-and-conventions.md` |\n\n## Development Commands\n\n### Build\n- `dotnet build -c Release --framework=net10.0 KurrentDB.slnx`\n\n### Test\n- `dotnet test --solution KurrentDB.slnx` - Run all tests\n- `dotnet test src/ProjectName.Tests/` - Run specific project\n- `dotnet test --filter \"FullyQualifiedName~TestMethodName\"` - Run single test\n\n### Development Server\n- `dotnet ./src/KurrentDB/bin/Release/net10.0/KurrentDB.dll --dev --db ./tmp/data --index ./tmp/index --log ./tmp/log`\n- HTTP/gRPC: 2113, Internal TCP: 1112\n- Admin UI: `http://localhost:2113` | Legacy: `http://localhost:2113/web`\n\n## Architecture (Summary)\n\nKurrentDB is an event-native database. .NET 10.0, 90+ projects, plugin-based architecture.\n\n**Key areas**: Core engine, Plugin system, API v2, Projections (V1 + V2), Secondary Indexing (DuckDB), Schema Registry, Connectors. See `.claude/docs/architecture.md` for full details.\n\n### Active Development Areas\n\n- **API v2** (`src/KurrentDB.Api.V2/`) — next-gen API, evolving rapidly. See `.claude/docs/api-v2-patterns.md`\n- **Projections V2** (`src/KurrentDB.Projections.V2/`) — next-gen projection engine with partitioned processing\n- **Schema Registry** (`src/SchemaRegistry/`) — event validation and schema management\n- **Secondary Indexing** (`src/KurrentDB.SecondaryIndexing/`) — DuckDB-backed query optimization\n\n### Projections V2 Engine\n\nKey components and their threading model:\n- `ProjectionEngineV2`: Main read loop, dispatches events to partitions, triggers checkpoints\n- `PartitionDispatcher`: Routes events to partition channels by hash of partition key\n- `PartitionProcessor`: Processes events within a single partition, manages state and output buffers\n- `CheckpointCoordinator`: Chandy-Lamport style — collects frozen buffers from all partitions, writes atomic multi-stream checkpoint\n- `CoreProjectionV2`: Adapter implementing `ICoreProjectionControl` — **runs on projection worker queue, NOT thread safe**\n- `ProjectionProcessingStrategyV2`: Factory creating V2 engines\n\nUses `ISystemClient` for writes (not raw `IPublisher`), `IReadStrategy` for reads.\n\n## Threading Model and Concurrency\n\n**Always ask: \"What thread does this run on? Is that safe?\"**\n\n### Critical Threading Rules\n\n- **Projection worker queue**: `CoreProjection`, `CoreProjectionV2` — NOT thread safe. Never call from thread pool.\n- **Bus dispatch thread**: `CallbackEnvelope` callbacks run here. **Never use `CallbackEnvelope` + `TaskCompletionSource` to await a response** — use `TcsEnvelope<T>` instead (uses `RunContinuationsAsynchronously`).\n- **Fire-and-forget tasks**: `_ = SomeAsync()` must not call back into non-thread-safe objects.\n\n### DotNext Threading Utilities\n\n- `TcsEnvelope<T>`: Safe async await for bus responses\n- `AsyncExclusiveLock`: Ensure only one operation in flight (e.g., checkpointing)\n- `[AsyncMethodBuilder(typeof(SpawningAsyncTaskMethodBuilder))]`: Start async method on new thread, don't capture caller's sync context. Use for background loops.\n\n### Lifecycle Rules\n\n- The component that creates a `CancellationTokenSource` owns it (cancel + dispose).\n- If a component can be stopped and restarted, stop must complete before start begins.\n- Prefer `Run(checkpoint, ct)` over separate `Start()`/`Stop()` when lifecycle is a single run.\n- When checkpointing from multiple partitions, ensure only one checkpoint in flight at a time.\n\n## C# Coding Conventions\n\n### Parameter Design — Non-Optional, No Fallbacks\n\n```csharp\n// WRONG: silent fallback hides a bug\npublic Foo(IPublisher publisher, IPublisher mainBus = null) {\n    _mainBus = mainBus ?? publisher;\n}\n\n// CORRECT\npublic Foo(IPublisher publisher, IPublisher mainBus) {\n    _mainBus = mainBus;\n}\n```\n\n- No `= null` on parameters that are actually required\n- No `= 1` magic number defaults on version/config parameters\n- Replace `?? fallbackValue` with `?? throw new InvalidOperationException(\"explanation\")` when null is a bug\n- Make types non-nullable (`T` not `T?`) when the value is always expected\n- Always pass `ClaimsPrincipal` and `requireLeader` explicitly — never hardcode or default\n\n### Naming\n\n- **Versioned classes**: `NounVersionSuffix` — `CoreProjectionV2` (not `V2CoreProjection`)\n- **Parameter accuracy**: `mainQueue` if it's a queue (not `mainBus`)\n- **Named booleans**: `requireLeader: true` at call sites, not just `true`\n- **Constants**: `ProjectionConstants.EngineV2` not `2`, `ExpectedVersion.Any` not `-2`\n\n### Encapsulation\n\n- Expose `IReadOnlyList<>`, `IReadOnlyDictionary<>` to consumers that only read\n- Use `private init` on record properties set only by factory methods\n- Pass factory instead of both value + factory\n\n### Micro-Patterns\n\n- `string.StartsWith('$')` (char overload, faster) over `string.StartsWith(\"$\")`\n- `string.GetHashCode()` over `XxHash32(Encoding.UTF8.GetBytes(...))` when hash stability isn't needed\n- `[]` collection expression over `new Dictionary<K,V>()`\n- Don't put `IAsyncDisposable` on interfaces when disposal is an implementation concern\n\n### Abstraction Discipline\n\n- Two classes doing the same thing with different config? Merge — pass the config as a parameter.\n- Interface adding lifecycle (`IAsyncDisposable`) that's the implementation's concern? Simplify the interface.\n- Method takes both a value and a factory-for-that-value? Just use the factory.\n\n## Log Level Policy\n\n| Level | When |\n|---|---|\n| **Verbose** | Per-event, per-message — anything that fires per-record |\n| **Debug** | Checkpoint writes, per-batch operations |\n| **Information** | Engine start/stop, lifecycle transitions only |\n| **Warning** | Recoverable errors, degraded states |\n| **Error** | Unrecoverable failures |\n\nPer-event or per-checkpoint log messages must NOT be `Information`.\n\n## MCP Servers\n\n- **Microsoft Docs**: `microsoft_docs_search`, `microsoft_docs_fetch` — query for .NET/Azure docs\n- **Context7**: Library documentation and code examples\n- Config: `.claude/settings.json` (committed), `.claude/settings.local.json` (local)\n\n## Configuration Defaults (v25.1)\n\n- **SecondaryIndexing:Enabled** — `true`\n- **ServerGC** — `true`\n- **StreamInfoCacheCapacity** — `100000`\n- **MemDb** — Deprecated, will be removed\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\nDetailed reference docs live in `.claude/docs/` — fetch them when working in a specific area.\n\n## Quick Reference: Where to Look\n\n| Working on... | Read |\n|---|---|\n| Core infrastructure, project layout | `.claude/docs/architecture.md` |\n| API v2 services | `.claude/docs/api-v2-patterns.md` |\n| Writing tests | `.claude/docs/testing.md` |\n| Protocol buffers, gRPC | `.claude/docs/protocol-v2.md` |\n| Message bus, enumerators, authorization, indexes | `.claude/docs/patterns-and-conventions.md` |\n\n## Development Commands\n\n### Build\n- `dotnet build -c Release --framework=net10.0 KurrentDB.slnx`\n\n### Test\n- `dotnet test --solution KurrentDB.slnx` - Run all tests\n- `dotnet test src/ProjectName.Tests/` - Run specific project\n- `dotnet test --filter \"FullyQualifiedName~TestMethodName\"` - Run single test\n\n### Development Server\n- `dotnet ./src/KurrentDB/bin/Release/net10.0/KurrentDB.dll --dev --db ./tmp/data --index ./tmp/index --log ./tmp/log`\n- HTTP/gRPC: 2113, Internal TCP: 1112\n- Admin UI: `http://localhost:2113` | Legacy: `http://localhost:2113/web`\n\n## Architecture (Summary)\n\nKurrentDB is an event-native database. .NET 10.0, 90+ projects, plugin-based architecture.\n\n**Key areas**: Core engine, Plugin system, API v2, Projections (V1 + V2), Secondary Indexing (DuckDB), Schema Registry, Connectors. See `.claude/docs/architecture.md` for full details.\n\n### Active Development Areas\n\n- **API v2** (`src/KurrentDB.Api.V2/`) — next-gen API, evolving rapidly. See `.claude/docs/api-v2-patterns.md`\n- **Projections V2** (`src/KurrentDB.Projections.V2/`) — next-gen projection engine with partitioned processing\n- **Schema Registry** (`src/SchemaRegistry/`) — event validation and schema management\n- **Secondary Indexing** (`src/KurrentDB.SecondaryIndexing/`) — DuckDB-backed query optimization\n\n### Projections V2 Engine\n\nKey components and their threading model:\n- `ProjectionEngineV2`: Main read loop, dispatches events to partitions, triggers checkpoints\n- `PartitionDispatcher`: Routes events to partition channels by hash of partition key\n- `PartitionProcessor`: Processes events within a single partition, manages state and output buffers\n- `CheckpointCoordinator`: Chandy-Lamport style — collects frozen buffers from all partitions, writes atomic multi-stream checkpoint\n- `CoreProjectionV2`: Adapter implementing `ICoreProjectionControl` — **runs on projection worker queue, NOT thread safe**\n- `ProjectionProcessingStrategyV2`: Factory creating V2 engines\n\nUses `ISystemClient` for writes (not raw `IPublisher`), `IReadStrategy` for reads.\n\n## Threading Model and Concurrency\n\n**Always ask: \"What thread does this run on? Is that safe?\"**\n\n### Critical Threading Rules\n\n- **Projection worker queue**: `CoreProjection`, `CoreProjectionV2` — NOT thread safe. Never call from thread pool.\n- **Bus dispatch thread**: `CallbackEnvelope` callbacks run here. **Never use `CallbackEnvelope` + `TaskCompletionSource` to await a response** — use `TcsEnvelope<T>` instead (uses `RunContinuationsAsynchronously`).\n- **Fire-and-forget tasks**: `_ = SomeAsync()` must not call back into non-thread-safe objects.\n\n### DotNext Threading Utilities\n\n- `TcsEnvelope<T>`: Safe async await for bus responses\n- `AsyncExclusiveLock`: Ensure only one operation in flight (e.g., checkpointing)\n- `[AsyncMethodBuilder(typeof(SpawningAsyncTaskMethodBuilder))]`: Start async method on new thread, don't capture caller's sync context. Use for background loops.\n\n### Lifecycle Rules\n\n- The component that creates a `CancellationTokenSource` owns it (cancel + dispose).\n- If a component can be stopped and restarted, stop must complete before start begins.\n- Prefer `Run(checkpoint, ct)` over separate `Start()`/`Stop()` when lifecycle is a single run.\n- When checkpointing from multiple partitions, ensure only one checkpoint in flight at a time.\n\n## C# Coding Conventions\n\n### Parameter Design — Non-Optional, No Fallbacks\n\n```csharp\n// WRONG: silent fallback hides a bug\npublic Foo(IPublisher publisher, IPublisher mainBus = null) {\n    _mainBus = mainBus ?? publisher;\n}\n\n// CORRECT\npublic Foo(IPublisher publisher, IPublisher mainBus) {\n    _mainBus = mainBus;\n}\n```\n\n- No `= null` on parameters that are actually required\n- No `= 1` magic number defaults on version/config parameters\n- Replace `?? fallbackValue` with `?? throw new InvalidOperationException(\"explanation\")` when null is a bug\n- Make types non-nullable (`T` not `T?`) when the value is always expected\n- Always pass `ClaimsPrincipal` and `requireLeader` explicitly — never hardcode or default\n\n### Naming\n\n- **Versioned classes**: `NounVersionSuffix` — `CoreProjectionV2` (not `V2CoreProjection`)\n- **Parameter accuracy**: `mainQueue` if it's a queue (not `mainBus`)\n- **Named booleans**: `requireLeader: true` at call sites, not just `true`\n- **Constants**: `ProjectionConstants.EngineV2` not `2`, `ExpectedVersion.Any` not `-2`\n\n### Encapsulation\n\n- Expose `IReadOnlyList<>`, `IReadOnlyDictionary<>` to consumers that only read\n- Use `private init` on record properties set only by factory methods\n- Pass factory instead of both value + factory\n\n### Micro-Patterns\n\n- `string.StartsWith('$')` (char overload, faster) over `string.StartsWith(\"$\")`\n- `string.GetHashCode()` over `XxHash32(Encoding.UTF8.GetBytes(...))` when hash stability isn't needed\n- `[]` collection expression over `new Dictionary<K,V>()`\n- Don't put `IAsyncDisposable` on interfaces when disposal is an implementation concern\n\n### Abstraction Discipline\n\n- Two classes doing the same thing with different config? Merge — pass the config as a parameter.\n- Interface adding lifecycle (`IAsyncDisposable`) that's the implementation's concern? Simplify the interface.\n- Method takes both a value and a factory-for-that-value? Just use the factory.\n\n## Log Level Policy\n\n| Level | When |\n|---|---|\n| **Verbose** | Per-event, per-message — anything that fires per-record |\n| **Debug** | Checkpoint writes, per-batch operations |\n| **Information** | Engine start/stop, lifecycle transitions only |\n| **Warning** | Recoverable errors, degraded states |\n| **Error** | Unrecoverable failures |\n\nPer-event or per-checkpoint log messages must NOT be `Information`.\n\n## MCP Servers\n\n- **Microsoft Docs**: `microsoft_docs_search`, `microsoft_docs_fetch` — query for .NET/Azure docs\n- **Context7**: Library documentation and code examples\n- Config: `.claude/settings.json` (committed), `.claude/settings.local.json` (local)\n\n## Configuration Defaults (v25.1)\n\n- **SecondaryIndexing:Enabled** — `true`\n- **ServerGC** — `true`\n- **StreamInfoCacheCapacity** — `100000`\n- **MemDb** — Deprecated, will be removed\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\nDetailed reference docs live in `.claude/docs/` — fetch them when working in a specific area.\n\n## Quick Reference: Where to Look\n\n| Working on... | Read |\n|---|---|\n| Core infrastructure, project layout | `.claude/docs/architecture.md` |\n| API v2 services | `.claude/docs/api-v2-patterns.md` |\n| Writing tests | `.claude/docs/testing.md` |\n| Protocol buffers, gRPC | `.claude/docs/protocol-v2.md` |\n| Message bus, enumerators, authorization, indexes | `.claude/docs/patterns-and-conventions.md` |\n\n## Development Commands\n\n### Build\n- `dotnet build -c Release --framework=net10.0 KurrentDB.slnx`\n\n### Test\n- `dotnet test --solution KurrentDB.slnx` - Run all tests\n- `dotnet test src/ProjectName.Tests/` - Run specific project\n- `dotnet test --filter \"FullyQualifiedName~TestMethodName\"` - Run single test\n\n### Development Server\n- `dotnet ./src/KurrentDB/bin/Release/net10.0/KurrentDB.dll --dev --db ./tmp/data --index ./tmp/index --log ./tmp/log`\n- HTTP/gRPC: 2113, Internal TCP: 1112\n- Admin UI: `http://localhost:2113` | Legacy: `http://localhost:2113/web`\n\n## Architecture (Summary)\n\nKurrentDB is an event-native database. .NET 10.0, 90+ projects, plugin-based architecture.\n\n**Key areas**: Core engine, Plugin system, API v2, Projections (V1 + V2), Secondary Indexing (DuckDB), Schema Registry, Connectors. See `.claude/docs/architecture.md` for full details.\n\n### Active Development Areas\n\n- **API v2** (`src/KurrentDB.Api.V2/`) — next-gen API, evolving rapidly. See `.claude/docs/api-v2-patterns.md`\n- **Projections V2** (`src/KurrentDB.Projections.V2/`) — next-gen projection engine with partitioned processing\n- **Schema Registry** (`src/SchemaRegistry/`) — event validation and schema management\n- **Secondary Indexing** (`src/KurrentDB.SecondaryIndexing/`) — DuckDB-backed query optimization\n\n### Projections V2 Engine\n\nKey components and their threading model:\n- `ProjectionEngineV2`: Main read loop, dispatches events to partitions, triggers checkpoints\n- `PartitionDispatcher`: Routes events to partition channels by hash of partition key\n- `PartitionProcessor`: Processes events within a single partition, manages state and output buffers\n- `CheckpointCoordinator`: Chandy-Lamport style — collects frozen buffers from all partitions, writes atomic multi-stream checkpoint\n- `CoreProjectionV2`: Adapter implementing `ICoreProjectionControl` — **runs on projection worker queue, NOT thread safe**\n- `ProjectionProcessingStrategyV2`: Factory creating V2 engines\n\nUses `ISystemClient` for writes (not raw `IPublisher`), `IReadStrategy` for reads.\n\n## Threading Model and Concurrency\n\n**Always ask: \"What thread does this run on? Is that safe?\"**\n\n### Critical Threading Rules\n\n- **Projection worker queue**: `CoreProjection`, `CoreProjectionV2` — NOT thread safe. Never call from thread pool.\n- **Bus dispatch thread**: `CallbackEnvelope` callbacks run here. **Never use `CallbackEnvelope` + `TaskCompletionSource` to await a response** — use `TcsEnvelope<T>` instead (uses `RunContinuationsAsynchronously`).\n- **Fire-and-forget tasks**: `_ = SomeAsync()` must not call back into non-thread-safe objects.\n\n### DotNext Threading Utilities\n\n- `TcsEnvelope<T>`: Safe async await for bus responses\n- `AsyncExclusiveLock`: Ensure only one operation in flight (e.g., checkpointing)\n- `[AsyncMethodBuilder(typeof(SpawningAsyncTaskMethodBuilder))]`: Start async method on new thread, don't capture caller's sync context. Use for background loops.\n\n### Lifecycle Rules\n\n- The component that creates a `CancellationTokenSource` owns it (cancel + dispose).\n- If a component can be stopped and restarted, stop must complete before start begins.\n- Prefer `Run(checkpoint, ct)` over separate `Start()`/`Stop()` when lifecycle is a single run.\n- When checkpointing from multiple partitions, ensure only one checkpoint in flight at a time.\n\n## C# Coding Conventions\n\n### Parameter Design — Non-Optional, No Fallbacks\n\n```csharp\n// WRONG: silent fallback hides a bug\npublic Foo(IPublisher publisher, IPublisher mainBus = null) {\n    _mainBus = mainBus ?? publisher;\n}\n\n// CORRECT\npublic Foo(IPublisher publisher, IPublisher mainBus) {\n    _mainBus = mainBus;\n}\n```\n\n- No `= null` on parameters that are actually required\n- No `= 1` magic number defaults on version/config parameters\n- Replace `?? fallbackValue` with `?? throw new InvalidOperationException(\"explanation\")` when null is a bug\n- Make types non-nullable (`T` not `T?`) when the value is always expected\n- Always pass `ClaimsPrincipal` and `requireLeader` explicitly — never hardcode or default\n\n### Naming\n\n- **Versioned classes**: `NounVersionSuffix` — `CoreProjectionV2` (not `V2CoreProjection`)\n- **Parameter accuracy**: `mainQueue` if it's a queue (not `mainBus`)\n- **Named booleans**: `requireLeader: true` at call sites, not just `true`\n- **Constants**: `ProjectionConstants.EngineV2` not `2`, `ExpectedVersion.Any` not `-2`\n\n### Encapsulation\n\n- Expose `IReadOnlyList<>`, `IReadOnlyDictionary<>` to consumers that only read\n- Use `private init` on record properties set only by factory methods\n- Pass factory instead of both value + factory\n\n### Micro-Patterns\n\n- `string.StartsWith('$')` (char overload, faster) over `string.StartsWith(\"$\")`\n- `string.GetHashCode()` over `XxHash32(Encoding.UTF8.GetBytes(...))` when hash stability isn't needed\n- `[]` collection expression over `new Dictionary<K,V>()`\n- Don't put `IAsyncDisposable` on interfaces when disposal is an implementation concern\n\n### Abstraction Discipline\n\n- Two classes doing the same thing with different config? Merge — pass the config as a parameter.\n- Interface adding lifecycle (`IAsyncDisposable`) that's the implementation's concern? Simplify the interface.\n- Method takes both a value and a factory-for-that-value? Just use the factory.\n\n## Log Level Policy\n\n| Level | When |\n|---|---|\n| **Verbose** | Per-event, per-message — anything that fires per-record |\n| **Debug** | Checkpoint writes, per-batch operations |\n| **Information** | Engine start/stop, lifecycle transitions only |\n| **Warning** | Recoverable errors, degraded states |\n| **Error** | Unrecoverable failures |\n\nPer-event or per-checkpoint log messages must NOT be `Information`.\n\n## MCP Servers\n\n- **Microsoft Docs**: `microsoft_docs_search`, `microsoft_docs_fetch` — query for .NET/Azure docs\n- **Context7**: Library documentation and code examples\n- Config: `.claude/settings.json` (committed), `.claude/settings.local.json` (local)\n\n## Configuration Defaults (v25.1)\n\n- **SecondaryIndexing:Enabled** — `true`\n- **ServerGC** — `true`\n- **StreamInfoCacheCapacity** — `100000`\n- **MemDb** — Deprecated, will be removed\n","category":"root","tokens":1685}]}