.NET SDK — feature blocks & architecture
The SDK is a minimal mandatory core plus a set of optional, stackable feature blocks. You assemble a client by taking the core and adding only the blocks you need: a connected desktop app takes the online transport and metering blocks; an air-gapped device takes offline activation and a file cache instead.
Blocks are described here by ID, responsibility and dependencies, not by .NET types
alone. That makes the model language-neutral: a non-.NET client — the shipped C/C++
interop, say — can implement a deliberate subset (license validation and an offline
cache, with no HTTP stack at all) and still be conformant. The
.NET packages are one implementation of this model; Client.OfflineStore
is one example of an add-on stacking on the core.
Every block has a defined absent behavior — when a block is missing, the SDK degrades to a known state rather than failing. Those rules are in Spec rules.
Feature blocks
Section titled “Feature blocks”Each block has a stable ID, a responsibility, the blocks it requires, and the current .NET types and package that implement it.
| Block | Requires | .NET types | Package |
|---|---|---|---|
| CORE-VALIDATE (mandatory) | — | SecureLicenseTokenValidation, SecureTokenAccess, LicenseClock, LicenseClaims, RsaPublicKey, ILicensePublicKeyProvider |
Client.LicenseConsumer |
| CORE-SESSION | CORE-VALIDATE | LicenseService, LicenseSession, LicenseClient, LicenseClientBuilder |
Client.LicenseConsumer |
| IDENTITY-BINDING | — | INodeIdProvider, IComponentNodeIdProvider, Sha256FingerprintSigner, ILicenseKeyProvider, IApplicationInfoProvider |
Client.LicenseConsumer |
| STORE-MEMORY / STORE-FILE | CORE-VALIDATE | InMemoryLicenseStore, LicenseFileStore, AtomicFile |
Client.LicenseConsumer |
| METER-RECORD (+ METER-RECORD-FILE) | CORE-SESSION | ITransactionStore, InMemoryTransactionStore, FileTransactionStore, UsageReporter, ScheduledUsageReporter |
Client.LicenseConsumer |
| METER-UPLOAD | METER-RECORD + TRANSPORT-HTTP | ITransactionProcessor, TransactionsToMonetizeServerConnector, TransactionUploadScheduler |
Client.LicenseConsumer.Connected |
| METER-BALANCE | TRANSPORT-HTTP | IAssetConsumption, AssetBalanceConsumption, NullAssetConsumption |
Connected |
| ENTITLEMENTS | CORE-VALIDATE | IFeatureValidation, FeatureValidation |
Client.LicenseConsumer |
| TRANSPORT-HTTP | CORE-SESSION | HttpLicenseProvider, LicenseRefreshScheduler (activation path); HttpConnector + Client.Provisioning |
Connected |
| OFFLINE-ACTIVATION | CORE-VALIDATE, IDENTITY-BINDING, STORE-FILE | request / response / receipt exchange | Client.OfflineStore |
| HOSTING-ASPNET / HOSTING-MULTITENANT | TRANSPORT-HTTP | DI root, hosted services, OIDC, OTel / Finbuckle multi-tenant | Client.AspNetCore |
| ADMIN | TRANSPORT-HTTP | provider-side management APIs | Client.Admin + Client.Provisioning |
- CORE-VALIDATE — verifies the JWS RS256 license token against a pinned public key, with a monotonic clock, the validity window and license claims. This is the trust root.
- CORE-SESSION — the acquire / cache / refresh lifecycle: provider→store fallback, single-flight acquisition gates, and the client builder.
- IDENTITY-BINDING — node-id and fingerprint providers, the license-key source and app identity: the inputs that bind a license to a machine and application.
- STORE-MEMORY / STORE-FILE — the license cache: in-process, or a durable atomic-write file cache.
- METER-RECORD — local usage buffering; METER-RECORD-FILE adds an HMAC-chained, tamper-evident file log.
- METER-UPLOAD — drains buffered usage to the server on a schedule.
- METER-BALANCE — server-side asset consumption: a non-binding check, and the commit that binds.
- ENTITLEMENTS — feature and entitlement checks over license claims.
- TRANSPORT-HTTP — online activation and refresh: auth, circuit breaker and retry.
- OFFLINE-ACTIVATION — air-gapped activation through a request / response / receipt exchange.
- HOSTING-ASPNET / HOSTING-MULTITENANT — the application host: DI root, hosted services, OIDC, OpenTelemetry and Finbuckle multi-tenant support.
- ADMIN — provider-side management APIs.
Spec rules
Section titled “Spec rules”- CORE-VALIDATE is mandatory and must be Full in every conformant client. It is the license trust root.
- Every other block is optional. A client declares which blocks it implements, rated Full / Partial / None per block.
- Each omitted block has a defined absent behavior:
- No provider present → no refresh scheduler runs; the client operates from the store only.
- TRANSPORT-HTTP absent → store-only activation (licenses come from the cache, not the network).
- METER-BALANCE absent →
NullAssetConsumptionis used (consumption calls are no-ops). - METER-UPLOAD absent → OFFLINE-ACTIVATION receipt export/import is the alternative drain for METER-RECORD: buffered usage leaves the machine through the receipt exchange instead of an HTTP upload.
How the packages stack
Section titled “How the packages stack”The blocks group into three tiers. Add-ons depend on the core, and the core on the
foundation — never the reverse. The core’s only foundation dependency is the wire DTO
contracts; the HttpConnector transport enters with the Connected add-on, which is what
keeps the core HTTP-free.
- Core package — HTTP-free, targets
netstandard2.0for broad reach. Holds CORE-VALIDATE, CORE-SESSION, IDENTITY-BINDING, STORE-MEMORY / STORE-FILE, METER-RECORD and ENTITLEMENTS. A client built from the core alone validates licenses, binds identity, caches to memory or disk, records usage locally and enforces entitlements — with no network stack. - Add-on packages — opt-in, each stacks on the core: Connected (TRANSPORT-HTTP + METER-UPLOAD + METER-BALANCE), OfflineStore (OFFLINE-ACTIVATION), ASP.NET Host (HOSTING-ASPNET / HOSTING-MULTITENANT) and Admin (ADMIN).
- Foundation — shared low-level pieces every online tier builds on: the
HttpConnectortransport and the wire DTO contracts.
What each profile includes
Section titled “What each profile includes”A profile is a named assembly of blocks. The matrix rates each block per profile as Full, Partial or None; where a block ships as an add-on, the cell names the package that provides it.
- dotnet-min — the core package only, no HTTP. Validation, session, identity, both stores, metering and entitlements are Full; offline activation is available by adding OfflineStore. No upload, balance, HTTP transport, hosting or admin.
- dotnet-desktop — core + Connected. Adds online activation/refresh, usage upload and server-side balance.
- dotnet-full — core + Connected + ASP.NET Host (and Admin for provider-side management). Every block is Full.
- cpp-embedded (shipped) — the lean subset, the shipped
libmonetizeitconfigured without a server URL (store-only): CORE-VALIDATE Full; STORE-FILE and ENTITLEMENTS Full; OFFLINE-ACTIVATION import-only (it imports responses and receipts but does not originate the exchange); no HTTP transport, hosting or admin. Being the same binary as cpp-connected, it exceeds the profile’s minimum in places (session, identity and local METER-RECORD work offline too). - cpp-connected (shipped) — cpp-embedded plus the online path: session, identity, all
metering and HTTP transport are Full; offline activation stays import-only; no hosting
or admin. Implemented by compiling the .NET consumer core with Native AOT
behind the C ABI in the SDK repository’s
dotnet/capi(monetizeit.h), consumed from C++ via the header-only RAII wrapper incpp/capi.