A modular .NET SDK with pluggable data providers, extensible hosting, and built-in observability — designed for building production-ready services and applications.
- About
- Technology Stack
- Architecture
- Getting Started
- Project Structure
- Key Features
- Development Workflow
- Coding Standards
- Testing
- Architectural Decision Records
- Contributing
- Security
- License
xSDK is a modular SDK library for .NET that provides a collection of reusable building blocks for data access, hosting, extensibility, and observability. It abstracts common infrastructure concerns — such as database providers, file storage, secrets management, and telemetry — behind clean, consistent interfaces, letting application teams focus on domain logic.
Key goals:
- Pluggable data providers: Swap between Entity Framework Core, MongoDB, LiteDB, FlatFile, Consul, or Vault-based storage without changing application code.
- Opinionated hosting: A slim, convention-based host that wires up DI, logging, and configuration with minimal boilerplate.
- Extensibility: Plugin infrastructure and extension points for custom scenarios.
- Observability: First-class OpenTelemetry integration for metrics, traces, and logs.
| Category | Technology | Version |
|---|---|---|
| Runtime | .NET | 10.0 |
| Language | C# | latest |
| Web Framework | ASP.NET Core | 10.0 |
| ORM | Entity Framework Core | 10.0.5 |
| Document DB | MongoDB (EF Core provider) | 10.0.1 |
| Embedded DB | LiteDB / LiteDB.Async | 5.0.21 |
| Flat File Store | JsonFlatFileDataStore | 2.4.2 |
| Service Discovery | Consul | 1.8.0 |
| Secrets Management | VaultSharp | 1.17.5.1 |
| Plugin System | Weikio.PluginFramework | 1.5.1 |
| Validation | FluentValidation | 12.1.1 |
| Object Mapping | Mapster | 10.0.6 |
| Observability | OpenTelemetry | 1.15.1 |
| API Versioning | Asp.Versioning | 8.1.1 |
| API Documentation | Microsoft.AspNetCore.OpenAPI | 10.0.5 |
| Cloud Events | CloudNative.CloudEvents | 2.8.0 |
| CLI | Spectre.Console.Cli | 0.53.1 |
| HTTP Client | RestSharp | 114.0.0 |
| Security Middleware | NWebsec | 3.0.0 |
| Serialization | YamlDotNet | 16.3.0 |
| Release Tooling | semantic-release / pnpm | — |
xSDK follows a modular, layered architecture where each library is independently consumable:
┌──────────────────────────────────────────────────────────┐
│ Application Layer │
│ (demos/, ASP.NET Core APIs, Console Apps) │
└─────────────────────────┬────────────────────────────────┘
│
┌─────────────────────────▼────────────────────────────────┐
│ xSdk.Extensions.* │
│ AspNetCore | AspNetCore.Links | CloudEvents | │
│ Commands | Telemetry │
└─────────────────────────┬────────────────────────────────┘
│
┌─────────────────────────▼────────────────────────────────┐
│ xSdk (Host) │
│ Hosting | Plugin Extensions | IO | Variables │
└─────────────────────────┬────────────────────────────────┘
│
┌─────────────────────────▼────────────────────────────────┐
│ xSdk.Data (Base Data Layer) │
│ IDataStore<T> | Repository | Fake Mode │
└──────┬──────────┬──────────┬──────────┬─────────┬────────┘
│ │ │ │ │
┌────▼───┐ ┌───▼────┐ ┌───▼────┐ ┌───▼──┐ ┌───▼────┐
│EF Core │ │MongoDB │ │FlatFile│ │Vault │ │Consul │
└────────┘ └────────┘ └────────┘ └──────┘ └────────┘
│
┌─────────────────────────────▼────────────────────────────┐
│ xSdk.Core (Foundation) │
│ Primitives | Utilities | Validation | Mapping | I/O │
└──────────────────────────────────────────────────────────┘
Core design principles:
- Repository Pattern: All data access is abstracted behind
IDataStore<TEntity>interfaces. - Dependency Injection First: Services register themselves via
Add[ServiceName]extension methods. - Async/Await Throughout: All I/O operations are fully async with
CancellationTokenpropagation. - Pluggable Providers: Switch data backends through configuration, not code changes.
- Observable by Design: OpenTelemetry instrumentation built into data and hosting layers.
- .NET 10 SDK (version
10.0.200or later, seeglobal.json) - just (command runner for development tasks)
- pnpm 10.x (required for release tooling only)
- Git
git clone https://github.com/velvet-lab/xsdk.git
cd xsdk
# Restore and build all libraries
just buildjust test# Example: console host demo
cd demos/console/host
dotnet run# Core SDK
dotnet add package xSdk
# Entity Framework data provider
dotnet add package xSdk.Data.EntityFramework
# ASP.NET Core extensions
dotnet add package xSdk.Extensions.AspNetCoreusing Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using xSdk.Hosting;
var host = Host
.CreateBuilder(args, "my-app", "my-company", "ma")
.ConfigureServices((context, services) =>
{
services.AddMyService();
})
.Build();
await host.RunAsync();xsdk/
├── libs/ # SDK library projects
│ ├── xSdk.Core/ # Foundation: primitives, utilities, validation, mapping
│ ├── xSdk/ # Host layer: hosting, plugin extensions, IO, variables
│ ├── xSdk.Plugin/ # Plugin host infrastructure (IPluginHost / WebPluginHost)
│ ├── xSdk.Data/ # Base data layer: IDataStore<T>, repository, fake mode
│ ├── xSdk.Data.EntityFramework/ # EF Core data provider
│ ├── xSdk.Data.EntityFramework.MongoDB/ # MongoDB via EF Core provider
│ ├── xSdk.Data.FlatFile/ # JSON flat-file data provider
│ ├── xSdk.Data.NoSql/ # LiteDB embedded NoSQL provider
│ ├── xSdk.Data.Vault/ # HashiCorp Vault secret provider
│ ├── xSdk.Extensions.Agents/ # MCP server plugin for AI agent integration
│ ├── xSdk.Extensions.AspNetCore/ # ASP.NET Core helpers and middleware
│ ├── xSdk.Extensions.AspNetCore.Links/ # HATEOAS-style link generation
│ ├── xSdk.Extensions.CloudEvents/ # CloudNative.CloudEvents integration
│ ├── xSdk.Extensions.Commands/ # CLI command extensions (Spectre.Console)
│ └── xSdk.Extensions.Telemetry/ # OpenTelemetry setup and configuration
├── demos/ # Sample applications
│ ├── console/ # Basic console host demo
│ ├── datalayer-entityframework/ # EF Core demo
│ ├── datalayer-flatfile/ # Flat-file storage demo
│ ├── datalayer-mongodb/ # MongoDB demo
│ ├── datalayer-nosql/ # LiteDB demo
│ ├── datalayer-vault/ # Vault demo
│ ├── host/ # Generic host demo
│ ├── plugin/ # Plugin system demo
│ ├── telemetry/ # OpenTelemetry demo
│ └── webapi/ # ASP.NET Core Web API demo
├── docs/adr/ # Architectural Decision Records
├── think-tank/ # Experimental / incubating features (e.g. xSdk.Data.Consul)
├── Directory.Build.props # Shared MSBuild properties
├── Directory.Build.targets # Shared MSBuild targets
├── Directory.Packages.props # Central NuGet package version management
├── global.json # .NET SDK version pin
├── xsdk.sln # Main solution file
└── xsdk-demos.sln # Demos solution file
Each library under libs/ follows the same layout:
libs/xSdk.SomeLibrary/
├── src/ # Production code
└── tests/ # Unit tests (mirrors src structure)
- Shared primitives, utility types, and base abstractions used across all other libraries
- Object mapping via
Mapster(compile-time generated, zero-overhead) FluentValidationregistration helpers- API versioning primitives via
Asp.Versioning - SemanticVersioning support
RestSharp-based HTTP client helpers
SlimHost— lightweight, convention-based .NET generic host with pre-configured logging and DITestHost/TestHostFixture— helpers for integration tests- File system abstractions via
Zio - Variable/placeholder resolution engine with YAML support
- Plugin infrastructure via
IPluginHost/WebPluginHost(seexSdk.Plugin) - OpenTelemetry integration wired into host startup
- Unified
IDataStore<TEntity>abstraction shared by all providers - Repository factory and Fake/In-Memory mode for demos and tests
- YAML-based data seeding support
- Entity Framework Core — SQL databases with full EF feature set, soft-delete support
- MongoDB — document store via the official EF Core MongoDB provider
- LiteDB — embedded, serverless NoSQL database (async variant included)
- FlatFile — JSON file-based storage for simple scenarios
- Vault — read secrets and configuration from HashiCorp Vault
- Consul (incubating,
think-tank/) — service discovery and key/value configuration from HashiCorp Consul - Async-first API with
CancellationTokenpropagation throughout
- API versioning configuration
- Problem Details middleware integration
- FluentValidation DI registration
- NWebsec security headers middleware
- API key authentication support
- OpenTelemetry traces, metrics, and logs in one setup call
- OTLP exporter support (Console + gRPC/HTTP)
- Runtime, EF Core, ASP.NET Core, HTTP, gRPC, Redis, and process instrumentation
- Container, host, and OS resource detectors
IPluginHost/WebPluginHostmodel — DI-registered plugin hosts participating in the normalIServiceCollectionlifecycle (see ADR-027)- Builder-scoped
SlimHost— no static singleton, full test isolation (see ADR-026) - Convention-based
Enable*extension methods per extension package
- MCP (Model Context Protocol) server plugin via
AgentsPluginHost EnableAgents()extension method onIHostBuilder
- CloudNative CloudEvents serialization and routing for event-driven architectures
- Rich CLI application framework via
Spectre.Console.Cli - Convention-based command registration
- Hypermedia link generation for REST APIs following HATEOAS principles
| Branch | Purpose |
|---|---|
main |
Stable, released code |
next |
Default integration branch (pre-release) |
feature-* |
Feature development |
Pull requests target the next branch. Merges to main trigger official releases.
This project uses Conventional Commits enforced by lint-commits CI workflow. Commit messages must follow the format:
<type>(<scope>): <description>
feat(data): add LiteDB async support
fix(hosting): resolve null reference in SlimHost startup
docs(readme): update getting started section
Common types: feat, fix, docs, test, refactor, chore, perf.
| Workflow | Trigger | Description |
|---|---|---|
unit-tests.yml |
Push / PR to main, next |
Quality assurance — build and test |
sonar-scan.yml |
PR to next |
SonarCloud quality analysis |
check-format.yml |
PR to main, next |
Verify code formatting |
check-license.yml |
PR to main, next |
Validate license headers |
lint-commits.yml |
PR (opened / sync / edited) | Conventional commit enforcement |
lint-dotnet.yml |
PR to main, next |
.NET code consistency scan |
release.yml |
Push to main, next |
Semantic versioning & GitHub Release |
Releases are fully automated via semantic-release:
# Install Node.js dependencies (for release tooling)
pnpm install
# Dry-run to preview the next release
pnpm exec semantic-release --dry-runThe version is derived from conventional commit history and NuGet packages are published automatically.
All C# code in this repository follows the guidelines in .github/instructions/csharp.instructions.md. Key conventions:
| Construct | Convention | Example |
|---|---|---|
| Types, Methods, Properties | PascalCase | DataStore, GetByIdAsync |
| Private fields, locals, parameters | camelCase | _repository, userId |
| Interfaces | I prefix |
IDataStore<T> |
| Generic type parameters | T prefix |
TEntity, TContext |
| Async methods | Async suffix |
SaveAsync, GetAllAsync |
- Nullable reference types are enabled project-wide — handle
nullcorrectly at API boundaries. ConfigureAwait(false)must be used in all library-level async code.CancellationTokenmust be accepted and passed through in every async method.- One type per file, file name matches the type name.
ArgumentNullException.ThrowIfNull()for parameter validation at public entry points.- Line length target: 120 characters.
- Code formatting is enforced via
.editorconfigand checked in CI.
- Register services via
Add[ServiceName]extension methods. - Prefer constructor injection; avoid service locator pattern.
- Use the Options pattern (
IOptions<T>) for configuration. - Follow the repository pattern for all data access.
For full details see the instruction files in .github/instructions/.
| Library | Version | Purpose |
|---|---|---|
| xunit.v3 | 3.2.2 | Test runner ([Fact], [Theory]) |
| Moq | 4.20.72 | Mocking framework |
| Testcontainers.MongoDb | 4.11.0 | Integration tests with real containers (MongoDB, etc.) |
Xunit.SkippableFact |
1.5.23 | Skip tests conditionally |
Bogus |
35.6.5 | Fake data generation |
Microsoft.EntityFrameworkCore.InMemory |
10.0.5 | In-memory EF Core provider for unit tests |
coverlet.collector |
8.0.1 | Code coverage collection (XPlat Code Coverage) |
MethodName_Scenario_ExpectedBehavior
Examples:
GetByIdAsync_WhenEntityExists_ReturnsEntitySaveAsync_WithNullEntity_ThrowsArgumentNullExceptionUpdateAsync_WhenConcurrencyConflict_ThrowsDbUpdateConcurrencyException
[Fact]
public async Task GetByIdAsync_WhenEntityExists_ReturnsEntity()
{
var store = new InMemoryDataStore<User>();
var user = new User { Id = "1", Name = "Alice" };
await store.InsertAsync(user);
var result = await store.SelectAsync("1");
Assert.NotNull(result);
Assert.Equal("Alice", result!.Name);
}# All tests
just test
# Specific project
dotnet test libs/xSdk/tests/
# With coverage
dotnet test xsdk.sln --collect:"XPlat Code Coverage"Test projects are named [ProjectName].Tests and mirror the source project structure. Tests must be independent and runnable in any order.
All significant design decisions are documented in docs/adr/. Each ADR captures the context, decision, and consequences.
| ADR | Title |
|---|---|
| ADR-001 | Modular Library Architecture |
| ADR-002 | Slim Host Singleton |
| ADR-003 | Plugin Extensibility Model |
| ADR-004 | Variable / Setup Configuration System |
| ADR-005 | Repository Pattern with Factory |
| ADR-006 | Provider-Agnostic Data Layer |
| ADR-007 | Entity Framework Data Provider |
| ADR-008 | NoSQL LiteDB Provider |
| ADR-009 | Flat-File JsonStore Provider |
| ADR-010 | Vault Secret Management |
| ADR-011 | MongoDB via EF Core |
| ADR-012 | Demo Fake Repository Mode |
| ADR-013 | NLog Logging Framework |
| ADR-014 | OpenTelemetry Observability |
| ADR-015 | ASP.NET Core Web Host Extension |
| ADR-016 | CloudEvents Integration |
| ADR-017 | Spectre Console Commands |
| ADR-018 | Mapster Object Mapping |
| ADR-019 | Zio Filesystem Abstraction |
| ADR-020 | Central Package Management |
| ADR-021 | SemVer Version Validation |
| ADR-022 | Weikio Plugin Framework |
| ADR-023 | ASP.NET Core Links / Hypermedia |
| ADR-024 | xSdk.Core as Unified Foundation Layer |
| ADR-025 | HashiCorp Consul as Service-Discovery and Configuration Provider |
- Fork the repository and create a feature branch from
next. - Follow the C# development guidelines.
- Write unit tests for all public APIs (mandatory).
- Ensure all XML documentation (
///) is complete on public members. - Run
just buildandjust testlocally before pushing. - Use Conventional Commits for all commit messages.
- Open a pull request targeting the
nextbranch.
This repository ships with a full set of GitHub Copilot customizations:
| Resource | Purpose |
|---|---|
| copilot-instructions.md | Project-wide coding context |
| .github/instructions/ | 9 focused instruction files by topic |
| .github/agents/ | 4 specialized agent modes (see below) |
| .github/skills/ | 10 reusable skill modules from awesome-copilot |
| .github/guidance/ | Commit, pull request, and review guidance |
Available agents:
| Agent | Purpose |
|---|---|
| C# Expert | Senior .NET developer — clean, idiomatic, secure C# code |
| GitHub Actions Expert | Secure CI/CD workflows, action SHA pinning, OIDC |
| ADR Generator | Create structured Architecture Decision Records |
| Technical Debt Remediation Plan | Analyze and prioritize technical debt |
See SECURITY.md for the full security policy and vulnerability reporting process.
Supported versions:
| Version | Supported |
|---|---|
| 1.1.x | ✅ |
| < 1.1.0 | ❌ |
To report a vulnerability, use GitHub's private vulnerability reporting or email danlorb@velvet-lab.net. Do not open public GitHub issues for security vulnerabilities.
This project is licensed under the Apache-2.0 License — see the LICENSE file for details.
Copyright © 2026 Velvet Lab