Skip to content

Latest commit

 

History

1,421 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Platform.SharedKernel

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.

.NET 10 License: MIT Packages Domains Status CI

What it is · Get started · Architecture · Package tree · Samples · Status · Using it · Building · Contributing


🧭 What it is

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

Principles

  • 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 typed Errors, mapped once to RFC 9457 ProblemDetails, gRPC status or a message fault.
  • Multi-tenant by default. One TenantId type 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.

⚡ Get started

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.


🏛️ Architecture

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
Loading
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.


🌳 The package tree

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.


🚀 Sample services

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)

📍 Status & roadmap

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.1 and publish the full package set
  • 🔍 Pre-publish reviews of the remaining domains

📦 Using the packages

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.


🛠️ Building this repository

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 only

Releasing: 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.

Repository map

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

🤝 Contributing

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.

AI-assisted development

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.


🔒 Security & license

Please report vulnerabilities privately, as described in SECURITY.md.

Released under the MIT License © 2026 Gresta-Vertex-Labs.

About

Modular SharedKernel for .NET 10 microservices: layered, independently publishable NuGet packages covering Result/Error primitives, DDD, CQRS, EF Core + PostgreSQL, MassTransit, FusionCache/Redis, OpenTelemetry, OIDC/mTLS/DPoP security and Temporal workflows. Roslyn analyzers and architecture tests enforce the layer rules.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages