M6d.Cerebro
0.3.0
dotnet add package M6d.Cerebro --version 0.3.0
NuGet\Install-Package M6d.Cerebro -Version 0.3.0
<PackageReference Include="M6d.Cerebro" Version="0.3.0" />
<PackageVersion Include="M6d.Cerebro" Version="0.3.0" />
<PackageReference Include="M6d.Cerebro" />
paket add M6d.Cerebro --version 0.3.0
#r "nuget: M6d.Cerebro, 0.3.0"
#:package M6d.Cerebro@0.3.0
#addin nuget:?package=M6d.Cerebro&version=0.3.0
#tool nuget:?package=M6d.Cerebro&version=0.3.0
Cerebro C# SDK
This SDK provides reusable licensing and entitlement-gating primitives for any C# / ASP.NET Core application that consumes Cerebro licenses.
Project structure
The library is organized by responsibility to make navigation easier:
src/M6d.Cerebro/Licensing/Abstractions: public service contracts.src/M6d.Cerebro/Licensing/Models: license payload and validation result models.src/M6d.Cerebro/Licensing/Options: configurable licensing options.src/M6d.Cerebro/Licensing/Services: default implementations.src/M6d.Cerebro/Licensing/Extensions: DI and startup helpers.src/M6d.Cerebro/Licensing/Constants: built-in public keys.src/M6d.Cerebro/Licensing/AspNetCore/Abstractions: HTTP entitlement resolver contracts.src/M6d.Cerebro/Licensing/AspNetCore/Options: ASP.NET Core behavior configuration.src/M6d.Cerebro/Licensing/AspNetCore/Routing: route-to-entitlement mapping primitives.src/M6d.Cerebro/Licensing/AspNetCore/Middleware: request gating middleware.src/M6d.Cerebro/Licensing/AspNetCore/Extensions: ASP.NET Core pipeline/endpoint helpers.samples: runnable example projects.
What is included
- License key validation compatible with Cerebro-generated keys.
- Typed entitlement reads and on/off checks from validated licenses.
- ASP.NET Core middleware for:
- blocking requests with invalid or expired licenses.
- blocking requests whose entitlement the license does not enable.
- returning RFC 7807 Problem Details responses by default.
- Configurable route-to-entitlement mapping.
- Optional endpoint helper to expose the license's entitlements.
Samples
samples/MinimalApiEntitlementGateSample: minimal API with license validation middleware and entitlement gating.samples/StartupStyleApiSample: class-basedStartupconfiguration with controllers and endpoint routing.
Testing
- Unit tests live in
tests/M6d.Cerebro.Tests(xunit.v3 on Microsoft.Testing.Platform). - From the repository root,
bun run dotnetbuilds, checks formatting, tests and packs the solution.bun run --cwd packages/cerebro-dotnet <build|check|test|lint|format|pack>runs one command throughscripts/dotnet.ts, which refuses an SDK other than the oneglobal.jsonpins. - The package targets
net10.0.Directory.Build.propsturns every analyzer rule into an error, and CSharpier owns formatting.
Releases
Releases run from the monorepo; see "Releasing" in the root README.md.
Installation and setup
NuGet package ID: M6d.Cerebro.
Register services in Program.cs or Startup.ConfigureServices:
using M6d.Cerebro.Licensing.Extensions;
using M6d.Cerebro.Licensing.AspNetCore.Extensions;
using System.Net.Http;
services.AddCerebroLicensing(
configureLicensing: options =>
{
options.LicenseKeyEnvironmentVariableName = "MSR_LICENSE_KEY";
options.AppId = "your-product-id";
// options.PublicKey = "..."; // optional override
},
configureEntitlementRouting: routes =>
{
routes.MapFirstSegmentPrefix("kpis", "kpis");
routes.MapFirstSegmentPrefix("plans", "plans");
routes.MapFirstSegmentPrefix("operations", "operations");
routes.MapPathPrefix("settings/kpis", "kpis", HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete, HttpMethod.Patch);
routes.MapPathPrefix("settings/plans", "plans", HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete, HttpMethod.Patch);
});
Set AppId to the product ID from Cerebro to reject licenses for other products.
The comparison is case-sensitive. A mismatch returns CerebroLicenseValidationFailure.WrongApp.
The default is null, which accepts any product.
Add middleware in the request pipeline:
using M6d.Cerebro.Licensing.AspNetCore.Extensions;
app.UseCerebroLicenseValidation();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCerebroEntitlementGating();
Optionally fail startup if the license is invalid:
using M6d.Cerebro.Licensing.Extensions;
app.Services.EnsureCerebroLicenseIsValid();
Optionally expose the current license entitlements:
using M6d.Cerebro.Licensing.AspNetCore.Extensions;
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapCerebroEntitlementsEndpoint();
});
By default, MapCerebroEntitlementsEndpoint() maps GET /licenses/entitlements:
{ "reports": true, "exports": false, "maxUsers": 10, "tier": "pro", "seats": null }
An invalid license produces {}. License validation middleware can still block requests before they reach the endpoint.
Direct service usage
Inject ICerebroLicenseService anywhere:
using M6d.Cerebro.Licensing.Abstractions;
public class MyService(ICerebroLicenseService licenseService)
{
public bool CanUseAdvancedReports() => licenseService.IsEnabled("advanced_reports");
public bool CanAddUser(long userCount) => licenseService.IsWithinLimit("maxUsers", userCount + 1);
public bool HasUnlimitedSeats() =>
licenseService.TryGet<long?>("seats", out var seats) && seats is null;
public long? GetMaxUsers() =>
licenseService.TryGet<long?>("maxUsers", out var users) ? users : 0;
public double? GetPrice() =>
licenseService.TryGet<double?>("price", out var price) ? price : 0;
}
GetEntitlements() returns the license's entitlements by code as signed, an IReadOnlyDictionary<string, JsonElement>.
IsEnabled(code) is true only for an entitlement signed as JSON true.
IsWithinLimit(code, count) is true when the entitlement is a number of at least count, or JSON null (unlimited); any other value or an absent code allows nothing.
TryGet<T>(code, out value) uses the configured CerebroLicensingOptions.JsonSerializerOptions.
Code lookup is case-insensitive, as with IsEnabled and IsWithinLimit.
It returns false and the default value for absent codes, invalid licenses, or incompatible requested types.
Use long? for whole numbers and double? for decimals. A null number means unlimited.
For example, 3000000000 fits long?; requesting it as int? returns false and null.
Signature validation is cached. Expiration is checked on every service call through UtcNowProvider when ValidateExpirationDate is enabled.
Expired licenses return LicenseExpired and grant no entitlements.
Generate API docs
The project enables XML documentation output in the library project file. Public APIs are documented with XML comments so IDE IntelliSense and generated docs remain useful for integrators.
Compatibility details
- License payload is decoded as UTF-16.
- Signature verification uses RSA PKCS#1 v1.5 with MD5 hash.
- Payload fields are
id,appId,deviceIds,expirationDate, andentitlements. entitlementsmaps every active entitlement code totrueorfalsefor on/off entitlements, otherwise a string, number, ornull. A null number means unlimited.CerebroLicenseDetails.Entitlementsis anIReadOnlyDictionary<string, JsonElement>. A payload withoutentitlements, or with an object or array as a value, fails withDeserializationFailed.- The signer escapes
[SEPARATOR]inside JSON strings as\u005BSEPARATOR]. Signature validation uses the original JSON; parsing restores the literal text.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.