Skip to content
bitzorcas
中EN

Concept

ADR 0504: Signed community licenses and the built-in small-deployment entitlement

The signed community.web.v1 boundary and the deployment-wide authoritative meter, atomic 30-user cap, and commercial-license precedence of community.small.v1.

Last updated

Status

Accepted (Revised, 2026-07-25).

Context

Minimal websites, APIs, and mini-program shells may not need core Platform business capability. Small applications and SaaS deployments with at most 30 active natural-person users should also be able to run without first completing customer-specific license issuance.

“No customer license required” cannot mean accepting an unsigned license, trusting a client-reported count, or scattering Development bypasses. The capacity boundary must come from authoritative Identity lifecycle facts and be enforced safely across concurrent user writes.

Decision

  1. community.web.v1 remains a vendor-signed protocol-v2 shared-license policy. It is fixed to mini-api, mini-api-single, single-tenant, no Platform or industry extension, and only the framework.core and framework.aspnetcore Features.

  2. community.small.v1 is active as a built-in product capacity entitlement, not a License Envelope. The host must explicitly configure Licensing:Runtime:PolicyId=community.small.v1, and only the persistent authoritative Identity meter can allow it.

  3. Metering aggregates every tenant under one persistent DeploymentId. Active and Locked, non-Host natural-person users consume seats. PendingActivation, Disabled, Expired, soft-deleted, Host operations, API clients, and application identities do not.

  4. The user aggregate, unique (DeploymentId, TenantId, UserId) allocation state, singleton meter, and append-only ledger share one unit of work. Creating, registering, activating, or re-enabling first selects one allocation winner and then acquires a seat with a database conditional update requiring ActiveUserCount < 30. Disable, expiry, deletion, and GDPR erasure release through a conditional allocation transition; count-then-save is forbidden.

  5. API rebuilds allocation state and the meter from authoritative Identity facts before accepting business traffic. Hostless tenant provisioning invokes the same entry before creating the first administrator. Unknown evidence fails closed.

  6. Commercial-entitlement precedence is fixed:

    Signed license stateSmall community behavior
    Valid / GraceSigned entitlement wins; the cap is removed while metering continues
    Unavailable / ExpiredFall back when the authoritative count is 0..30
    Invalid / RevokedNever fall back; tampering and revocation remain visible
  7. /health/license represents the currently usable runtime entitlement. The built-in entitlement reports LIC.COMMUNITY_SMALL, active count, maximum, and meter sequence. Base /health/ready remains independent.

0013-runtime-license-policy-catalog.json records status and evidence semantics, protected jointly by Runtime, Identity, migration, and architecture tests.

Consequences

  • With Development defaulting to community.small.v1, business functions for up to 30 users need no license file or public key.
  • User 31 receives Identity.User.CommunityActiveUserLimitExceeded at the atomic database write boundary; concurrent requests cannot bypass it.
  • Repeated or concurrent release of one user’s seat decrements the meter once. GDPR erasure fails the whole transaction on an aggregate-version conflict instead of metering from stale state.
  • An over-capacity deployment can still search, inspect, disable, and delete users to return to 30. Creation, invitation, activation, and re-enabling remain denied.
  • A valid commercial license removes the cap seamlessly; Invalid and Revoked still fail closed.
  • community.small.v1 grants no private NuGet Feed entitlement and does not weaken the signed community.web.v1 boundary.

See also

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%