The building blocks of a .NET 10 microservice platform, as 104 NuGet packages.
Primitives and the request context, DDD, CQRS, PostgreSQL, messaging, caching, storage, search, AI, security, presentation, workflows, scheduling and reporting. No business logic, and a build that enforces the architecture.
What it is · Get started · Architecture · Package tree · Samples · Status · Using it · Building · Contributing
Every service in a microservice platform needs the same plumbing: who is calling and for which tenant, how a command is validated, authorized and committed, how an event reaches another service, how errors become HTTP responses, how a dependency reports that it is ready. Platform.SharedKernel writes that plumbing once, as small packages with narrow jobs, so a service only has to write its own business.
| 📦 104 packages | in 21 capability domains, released together at one version |
| 🧱 7 tiers | every package is Foundation, Model, Abstractions, Adapter, Host, Testing or Tooling, and the build rejects a reference its tier may not take |
| 🧪 A test double for every contract | 20 *.Testing packages, so a service's unit tests need no containers |
| 🛡️ 45 analyzer rules | Roslyn rules for the conventions: [LoggerMessage]-only logging, no discarded Result, no raw SDK clients, no magic strings, deterministic workflows |
| 🚀 7 sample services | built only from the packed packages and run in CI against real PostgreSQL, RabbitMQ, MinIO, Meilisearch and Elasticsearch |
| 📖 One README standard | every package README has the same shape — install, quick start, configuration, reference, testing, pitfalls — checked by a test |
- Capability-oriented. One folder per capability. A capability with several providers splits into
.Abstractions+.{Provider}, so application code never depends on a vendor. - Tier-enforced. What a package may reference is checked by MSBuild before compile
(
SKTIER001–SKTIER006) and again by architecture tests. ASP.NET Core never leaks below the Host tier. - Results, not exceptions. Expected failures are
Result<T>values with typedErrors, mapped once to RFC 9457 ProblemDetails, gRPC status or a message fault. - Multi-tenant by default. One
TenantIdtype flows from the HTTP edge through the pipeline, the database (row-level security), the cache, storage, search and the message bus, and code fails closed when it is missing. - Kubernetes-native. OpenTelemetry built in,
/health/live+/health/ready, and every provider registers its own readiness probe. - Licence-conscious. MassTransit is pinned to 8.5.x (the last Apache-2.0 release) and MediatR to 12.4.1 (the last MIT release). EPPlus, QuestPDF and iText7 were declined on licensing.
A service built on the kernel has four projects, and each one references only the tier made for it.
samples/OrderApi is exactly this shape, with an architecture test that keeps it so.
1. Pin the version once — see Using the packages for the full Directory.Packages.props.
2. Reference by project:
| Project | References | For example |
|---|---|---|
Orders.Domain |
Model tier | SharedKernel.Domain |
Orders.Application |
Abstractions tier | SharedKernel.Application |
Orders.Infrastructure |
Adapter tier | SharedKernel.Persistence.EfCore, SharedKernel.Messaging.MassTransit.RabbitMq |
Orders.Api |
Host tier | SharedKernel.ServiceDefaults, SharedKernel.Presentation.WebApi, SharedKernel.Application.Pipeline |
3. Write the business, not the plumbing:
// Application — a command, its handler and the permission it needs
[RequirePermission("orders.create")]
public sealed record PlaceOrder(Guid CustomerId, decimal Amount, string IdempotencyKey)
: ICommand<Guid>, IIdempotentRequest;
// Api — one registration call for the whole request pipeline
builder.AddServiceDefaults();
builder.Services.AddSharedKernelApplication(
typeof(PlaceOrderHandler).Assembly,
app => app.UseMediatR().WithIdempotency().WithTransactions());Tracing, logging, metrics, authorization and validation run on every request; the With… stages are
opt-in, and the host refuses to start if a stage's dependency is missing. The
samples guide walks through a complete service.
Each package has a tier. The tier says which project of a consuming service may reference it, and which other packages the package itself may reference.
flowchart LR
subgraph service["A consuming service"]
direction TB
Api["Api / Worker"]
Infra["Infrastructure"]
App["Application"]
Dom["Domain"]
end
subgraph kernel["Platform.SharedKernel tiers"]
direction TB
Host["<b>Host</b> · 20<br/>ASP.NET Core, composition"]
Adapter["<b>Adapter</b> · 38<br/>PostgreSQL, Redis, MassTransit, S3…"]
Abs["<b>Abstractions</b> · 11<br/>provider-neutral contracts"]
Model["<b>Model</b> · 2<br/>Domain, Contracts"]
Found["<b>Foundation</b> · 10<br/>Result, request context, crypto"]
Host --> Adapter --> Abs --> Model --> Found
end
Testing["<b>Testing</b> · 20<br/>fakes for test projects"] -.-> Host
Tooling["<b>Tooling</b> · 3<br/>analyzers, arch tests, linter"]
Api --> Host
Infra --> Adapter
App --> Abs
Dom --> Model
| Tier | May reference | Consumed by |
|---|---|---|
| Foundation | Foundation | every project |
| Model | Foundation, Model (Microsoft.Extensions.*.Abstractions only) |
the Domain project |
| Abstractions | Foundation, Model, Abstractions (Microsoft.Extensions.*.Abstractions only) |
the Application project |
| Adapter | the tiers above, plus declared adapter edges; never ASP.NET Core | the Infrastructure project |
| Host | everything except Testing and Tooling | the Api / Worker project |
| Testing | everything except Tooling | test projects only |
| Tooling | nothing | the build |
The full rules, including the purity rules that tiers cannot express, are in
CONTRIBUTING.md. Build internals are in eng/README.md.
All 104 packages. Every name links to the package's README, and every domain links to its overview. The badge after each name is the package's tier.
-
📁 00.Governance — the rules the rest of the repo is held to · 3 packages
- SharedKernel.Analyzers
Tooling— 45 Roslyn rules for the platform conventions, compiler-only - SharedKernel.ArchitectureTests
Tooling— prebuilt NetArchTest rules for dependency purity, provider isolation and secure defaults - SharedKernel.Linter
Tooling— CSharpier format check for CI plus the shared.editorconfig
- SharedKernel.Analyzers
-
📁 01.Core — primitives, the execution context and cross-cutting utilities · 13 packages
- SharedKernel.Primitives
Foundation—Result<T>,Error,IClock,IIdGenerator, SmartEnum, well-known headers, readiness probes - SharedKernel.Execution
Foundation—IRequestContext,TenantId/TenantScope,IUnitOfWork: the caller on every channel - SharedKernel.Core
Foundation— railway extensions forResult,ResultTry, guard clauses, base exceptions - SharedKernel.Configuration
Foundation— options validated at startup, not at first use - SharedKernel.FeatureManagement
Foundation— typed feature flags on OpenFeature, per-tenant rollouts - SharedKernel.Compression
Foundation— framed Brotli/gzip with a decompression-size cap - SharedKernel.Cryptography
Foundation— AES-256-GCM, envelope encryption, signatures, HMAC, password hashing, TOTP - SharedKernel.Cryptography.Argon2
Adapter— Argon2id password hashing as PHC strings - SharedKernel.Cryptography.KeyVault.Azure
Adapter— Azure Key Vault keys for encryption and signing - SharedKernel.DataPrivacy
Foundation— personal-data taxonomy, log redaction, masking, GDPR/KVKK data-subject requests - SharedKernel.Localization
Foundation— translated error messages with typed arguments - SharedKernel.Validation
Foundation— parsed value types: IBAN, BIC, card number, VAT, LEI, phone, national id… - SharedKernel.Validation.FluentValidation
Adapter— FluentValidation rules for those types
- SharedKernel.Primitives
-
📁 02.Caching — hybrid caching, distributed locks and Redis · 7 packages
- SharedKernel.Caching.Abstractions
Abstractions—ICacheService,ITenantCacheService,IDistributedLockService - SharedKernel.Caching.FusionCache
Adapter— the cache: stampede protection, fail-safe, optional encryption - SharedKernel.Caching.Redis.Core
Adapter— the one shared Redis connection, TLS and readiness - SharedKernel.Caching.Redis
Adapter— Redis L2 and backplane for FusionCache - SharedKernel.Caching.Redis.DistributedLocking
Adapter— locks, leases and fencing tokens - SharedKernel.Caching.Redis.HashStore
Adapter— typed Redis hash storage - SharedKernel.Caching.Redis.PubSub
Adapter— loss-tolerant Redis Pub/Sub signals
- SharedKernel.Caching.Abstractions
-
📁 03.Domain — domain-driven design building blocks · 1 package
- SharedKernel.Domain
Model— entities, aggregates, value objects, strongly typed ids, specifications,Money
- SharedKernel.Domain
-
📁 04.Contracts — cross-service wire contracts · 1 package
- SharedKernel.Contracts
Model— versioned integration events in a CloudEvents envelope, offset and cursor paging
- SharedKernel.Contracts
-
📁 05.Application — CQRS and the request pipeline · 4 packages
- SharedKernel.Application
Abstractions— commands, queries, handlers,ISenderand pipeline markers, owned by the kernel - SharedKernel.Application.Pipeline
Host— one registration call: tracing, logging, metrics, authorization, validation, idempotency, auditing, transactions - SharedKernel.Application.Pipeline.Caching
Host— query caching and post-commit eviction - SharedKernel.Application.Mediator.MediatR
Host— MediatR 12.4.1 behindISender, swappable
- SharedKernel.Application
-
📁 06.Persistence — PostgreSQL through EF Core and Dapper · 6 packages
- SharedKernel.Persistence.Abstractions
Abstractions— ORM-free repositories, paging, bulk mutations, cross-tenant scope - SharedKernel.Persistence.Npgsql
Adapter— data sources, TLS, database roles, SQLSTATE classification - SharedKernel.Persistence.EfCore
Adapter— EF Core 10 in one call: conventions, unit of work, tenant filter, row-level security - SharedKernel.Persistence.Dapper
Adapter— hand-written SQL that joins the same transaction and tenant - SharedKernel.Persistence.EfCore.Auditing
Adapter— tamper-evident, HMAC-chained audit ledger - SharedKernel.Persistence.EfCore.Encryption
Adapter— field-level encryption, blind indexes, key rotation, crypto-shredding
- SharedKernel.Persistence.Abstractions
-
📁 07.Messaging — integration events over MassTransit · 5 packages
- SharedKernel.Messaging.Abstractions
Abstractions—IMessageBus,IEventPublisher, scheduling and version translation - SharedKernel.Messaging.MassTransit
Adapter— one fluent chain: retry, circuit breaker, idempotency, ordering, payload encryption - SharedKernel.Messaging.MassTransit.RabbitMq
Adapter— RabbitMQ transport with delayed delivery - SharedKernel.Messaging.MassTransit.AzureServiceBus
Adapter— Azure Service Bus transport - SharedKernel.Messaging.MassTransit.EfCore
Adapter— transactional outbox on the service's own DbContext
- SharedKernel.Messaging.Abstractions
-
📁 08.Storage — object storage · 3 packages
- SharedKernel.Storage.Abstractions
Abstractions— named and tenant stores, streaming, presigned URLs, conditional writes - SharedKernel.Storage.S3
Adapter— Amazon S3, MinIO and S3-compatible storage - SharedKernel.Storage.Obs
Adapter— Huawei Cloud OBS
- SharedKernel.Storage.Abstractions
-
📁 09.Search — full-text search · 3 packages
- SharedKernel.Search.Abstractions
Abstractions—ISearchIndex<T>, a provider-neutral filter AST, index provisioning - SharedKernel.Search.Meilisearch
Adapter— Meilisearch: instant search, tenant search tokens - SharedKernel.Search.ElasticSearch
Adapter— Elasticsearch: aggregations, cursor export, suggestions
- SharedKernel.Search.Abstractions
-
📁 10.Intelligence — embeddings, vectors and LLMs · 3 packages
- SharedKernel.AI.Abstractions
Abstractions— embedding generation, tenant-scoped vector collections, orchestration - SharedKernel.AI.Qdrant
Adapter— Qdrant vector database - SharedKernel.AI.SemanticKernel
Adapter— LLM orchestration on Microsoft Semantic Kernel
- SharedKernel.AI.Abstractions
-
📁 11.Communication — outbound service-to-service calls · 3 packages
- SharedKernel.Communication
Adapter— the shared base: per-client settings, service discovery, outbound auth, mutual TLS - SharedKernel.Communication.Rest
Adapter— typedHttpClients: safe retries, caller propagation,Result<T>instead of exceptions - SharedKernel.Communication.Grpc
Adapter— gRPC clients: deadline, retry policy, load balancing, rich status →Result<T>
- SharedKernel.Communication
-
📁 12.Security — authentication · 5 packages
- SharedKernel.Security.Abstractions
Abstractions—IUserContext: subject, tenant, roles, permissions, step-up signals - SharedKernel.Security.Oidc
Host— JWT bearer for any OIDC provider, DPoP, certificate-bound tokens, revocation - SharedKernel.Security.ApiKey
Host— managed API keys for machine clients - SharedKernel.Security.Mtls
Host— client-certificate authentication, private CA trust - SharedKernel.Security.Totp
Host— TOTP enrollment, step-up and recovery codes
- SharedKernel.Security.Abstractions
-
📁 13.ServiceDefaults — host composition · 7 packages
- SharedKernel.ServiceDefaults
Host— OpenTelemetry, health endpoints, readiness, startup gate, rate limiting - SharedKernel.ServiceDefaults.Security
Host— the HTTP request context and correlation id middleware - SharedKernel.ServiceDefaults.Persistence
Host— database readiness checks - SharedKernel.ServiceDefaults.Security.Mtls
Host— Kestrel client-certificate negotiation - SharedKernel.ServiceDefaults.Configuration.KeyVault
Host— Azure Key Vault as a configuration source - SharedKernel.ServiceDefaults.Localization
Host— request culture from user, tenant orAccept-Language - SharedKernel.MultiTenancy
Host— tenant resolution (claim → header → database) and the tenant catalog
- SharedKernel.ServiceDefaults
-
📁 14.Presentation — inbound APIs · 6 packages
- SharedKernel.Presentation.Core
Host— authorization attributes and error presentation shared by HTTP and gRPC - SharedKernel.Presentation.WebApi
Host— minimal APIs: one ProblemDetails shape, typed results, endpoint modules, ETags, idempotency keys - SharedKernel.Presentation.OpenApi
Host— API versioning, one OpenAPI document per version, Scalar - SharedKernel.Presentation.Grpc
Host— gRPC services with the same errors and authorization - SharedKernel.Presentation.SignalR
Host— hub error contract, request context and rate limiting - SharedKernel.Presentation.GraphQL
Host— HotChocolate conventions
- SharedKernel.Presentation.Core
-
📁 15.Integration — delivery to destinations outside the platform · 4 packages
- SharedKernel.Integration.Webhooks
Adapter— signed, retried, SSRF-guarded webhooks with secret rotation - SharedKernel.Integration.Notifications.Abstractions
Abstractions—INotificationSenderfor email and SMS - SharedKernel.Integration.Notifications.Email.SendGrid
Adapter— SendGrid email over REST - SharedKernel.Integration.Notifications.Sms.Twilio
Adapter— Twilio SMS over REST
- SharedKernel.Integration.Webhooks
-
📁 16.Testing — test doubles for every capability · 20 packages
- SharedKernel.Testing
Testing—FakeClock, in-memory logger,TestRequestContext, fakers, assertions - SharedKernel.AI.Testing
Testing— deterministic embeddings and an in-memory vector store - SharedKernel.Application.Testing
Testing— runs a request through the real pipeline, no mediator needed - SharedKernel.Caching.Testing
Testing— fake cache, tenant cache and distributed locks - SharedKernel.Caching.Redis.Testing
Testing— fake Redis hashes and Pub/Sub - SharedKernel.Communication.Testing
Testing— a stub HTTP handler for REST clients and gRPC call fakes - SharedKernel.Cryptography.Testing
Testing— recording crypto fakes with failure simulation - SharedKernel.FeatureManagement.Testing
Testing— a feature client with per-test flags - SharedKernel.Idempotency.Testing
Testing— an in-memory idempotency store - SharedKernel.Integration.Testing
Testing— in-memory webhook dispatcher and notification sender - SharedKernel.Messaging.Testing
Testing— in-memory bus and publisher with assertions - SharedKernel.Persistence.Testing
Testing— fake repositories and unit of work, PostgreSQL test servers - SharedKernel.Presentation.Testing
Testing— gRPC and GraphQL test helpers - SharedKernel.Reporting.Testing
Testing— in-memory exporters and HTML-to-PDF converter - SharedKernel.Scheduling.Testing
Testing— a recording job registry - SharedKernel.Search.Testing
Testing— an in-memory search index that evaluates the filter AST - SharedKernel.Security.Testing
Testing— fake user context, test certificates and DPoP proofs - SharedKernel.ServiceDefaults.Testing
Testing— in-memory tenant catalog and health-check assertions - SharedKernel.Storage.Testing
Testing— in-memory named and tenant stores - SharedKernel.Workflows.Testing
Testing— in-memory workflow dispatcher
- SharedKernel.Testing
-
📁 17.Workflows — durable execution · 1 package
- SharedKernel.Workflows.Temporal
Adapter— Temporal workflows and activities, tenant-scoped dispatch, payload encryption
- SharedKernel.Workflows.Temporal
-
📁 18.Idempotency — duplicate-request and duplicate-message protection · 3 packages
- SharedKernel.Idempotency.Abstractions
Abstractions— one atomic reservation contract,IIdempotencyStore - SharedKernel.Idempotency.Redis
Adapter— Redis store with atomic Lua - SharedKernel.Idempotency.EfCore
Adapter— PostgreSQL store withINSERT … ON CONFLICT
- SharedKernel.Idempotency.Abstractions
-
📁 19.Scheduling — background jobs · 1 package
- SharedKernel.Scheduling
Adapter— cron, recurring and one-shot jobs that run once across replicas
- SharedKernel.Scheduling
-
📁 20.Reporting — exports and documents · 5 packages
- SharedKernel.Reporting.Abstractions
Abstractions— streamingIReportExporter<TRow>andIHtmlToPdfConverter - SharedKernel.Reporting.Csv
Adapter— RFC 4180 CSV in constant memory, formula-injection guard - SharedKernel.Reporting.Spreadsheet
Adapter— streamed Excel (.xlsx) on SpreadCheetah - SharedKernel.Reporting.Pdf
Adapter— tabular PDF on PDFsharp/MigraDoc - SharedKernel.Reporting.Gotenberg
Adapter— HTML → PDF through a Gotenberg container
- SharedKernel.Reporting.Abstractions
Runnable services built only from the packed packages. Each one is the reference for one area, and
CI runs them against real infrastructure. Start with samples/README.md, the guide
to consuming the kernel.
| Sample | Reference for | Runs against |
|---|---|---|
| OrderApi | The four-project service shape (Domain / Application / Infrastructure / Api), enforced by an architecture test | nothing external |
| BillingApi | The full persistence stack: EF Core + Dapper, row-level security, field encryption, audit ledger | PostgreSQL |
| ShippingApi | Messaging: publish/send, delayed delivery, consumer idempotency, caller context across the bus | RabbitMQ |
| DocumentsApi | Object storage and reporting: named/tenant stores, presigned links, CSV/Excel/PDF exports | MinIO, Gotenberg |
| CatalogApi | Search: Meilisearch and Elasticsearch side by side | Meilisearch, Elasticsearch |
| CheckoutApi → InventoryApi | Two services talking: typed REST and gRPC clients, service discovery, an API key, safe retries with Idempotency-Key, the caller carried across, downstream errors returned as Result |
nothing external (loopback ports) |
Note
Pre-release. The architecture and the 104 packages are in place on main. The first release
under the one-version train, v1.0.0-alpha.1, has not been tagged yet. Until then, expect breaking
changes between commits.
Done
-
Tiered foundation: the seven tiers are enforced by the build, and one execution context covers every channel (HTTP, gRPC, messages, workflows, jobs)
-
A kernel-owned CQRS model with a mediator-agnostic pipeline
-
Pre-publish reviews of persistence, storage, messaging, application/presentation and reporting, each verified by a sample service
-
A release train: one tag gates on every test suite, consumer harness and sample, then publishes all packages together
-
One README standard across every package, checked by an architecture test
Next
- 🏷️ Tag
v1.0.0-alpha.1and publish the full package set - 🔍 Pre-publish reviews of the remaining domains
Every package ships at the same version. Pin that version once, in your Directory.Packages.props,
and point every SharedKernel.* package at it. Upgrading is then a one-line change, and the packages can
never end up at mixed versions.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<!-- The one SharedKernel release this service builds against. -->
<SharedKernelVersion>1.0.0-alpha.1</SharedKernelVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="SharedKernel.Primitives" Version="$(SharedKernelVersion)" />
<PackageVersion Include="SharedKernel.Application" Version="$(SharedKernelVersion)" />
<PackageVersion Include="SharedKernel.ServiceDefaults" Version="$(SharedKernelVersion)" />
<!-- One line per SharedKernel package you reference, always $(SharedKernelVersion). -->
</ItemGroup>
</Project>Don't pin one SharedKernel.* package to a different version, and don't float the version (*).
The package feed and its NuGet.Config setup are in
CONTRIBUTING.md → Consuming the packages. Which package goes in
which project of your service is in samples/README.md.
You need the .NET 10 SDK (10.0.300 or newer, see global.json). The Integration lane
also needs Docker.
dotnet build Platform.SharedKernel.slnx -c Release
dotnet test Platform.SharedKernel.Unit.slnf -c Release --no-build # no Docker needed
dotnet test Platform.SharedKernel.Integration.slnf -c Release --no-build # Testcontainers
dotnet pack Platform.SharedKernel.slnx -c Release --no-build -o artifacts/packages
eng/verify-packages.sh artifacts/packages # checks the release set; the folder must hold one pack onlyReleasing: push a v<major>.<minor>.<patch>[-prerelease] tag on main.
release.yml runs every gate: the tier check, the build, both test
lanes, and every consumer harness and sample against the packed packages. Only then does it publish the
whole set at the tag's version. No package can be published on its own. Details are in
CONTRIBUTING.md.
| File | What's in it |
|---|---|
CONTRIBUTING.md |
How to build, test, add a package and open a pull request |
eng/README.md |
Build internals: tier check, package checks, versioning, CI workflows |
docs/package-readme-standard.md |
The shape every package README follows |
NN.Domain/README.md |
The overview of one capability domain |
CLAUDE.md, NN.Domain/CLAUDE.md |
Maintainer rules: architecture, conventions, "what goes where" |
state-map.md, NN.Domain/state-map.md |
The living work board: packages, open work, completed phases |
Contributions are welcome. Read CONTRIBUTING.md first: it covers the tier rules the
build enforces, the conventions the analyzers check, and what must pass before a pull request can merge.
Everyone taking part is expected to follow the Code of Conduct.
The repository is set up for Claude Code. Every domain has a
CLAUDE.md with its rules, and .claude/ holds a team of agents (an architecture lead, a planner and an
implementer per domain, a DevOps lead) with commands such as /arch, /implement-phase <domain> and
/sync-brain. Using it is optional; the rules it follows are the same ones in CONTRIBUTING.md.
Please report vulnerabilities privately, as described in SECURITY.md.
Released under the MIT License © 2026 Gresta-Vertex-Labs.