Expand description
Enterprise licensing gate (DW-032).
The edition boundary as a runtime value: a LicenseGate holds an
optional verified license and answers the two questions every
enterprise feature asks before it engages — “are we in enterprise
mode?” (LicenseGate::is_enterprise) and “does this license grant
feature X?” (LicenseGate::has_feature). OSS builds (the default,
no ent cargo feature) compile a stub gate that is always
LicenseGate::none: every enterprise feature is inert by
construction, and no licensing-core dependency is pulled in.
§Verification model
When the ent feature is compiled in, LicenseGate::from_file
reads a license file, verifies its Ed25519 signature against the
product’s public key, and checks expiry. The public key is NEVER
user-configurable in the YAML (an operator must not be able to
substitute their own key to forge a license): it comes from the
DWARA_LICENSE_PUBLIC_KEY environment variable or, when unset, the
compiled-in development key (local/CI only — production MUST set the
env var). The product ID is pinned to "dwara" so a license issued
for another ShristiLabs product cannot be replayed here.
§Grace period
A license that has passed its expires_at timestamp is not
immediately fatal. For a configurable grace window (default 7 days,
0..=30) after expiry, enterprise features keep working and a warning
is logged — the operator has a buffer to renew. After the grace
window the gate degrades to OSS: LicenseGate::is_enterprise
returns false and every enterprise feature falls back to its OSS
behavior. This is the done-when: “Invalid/expired license degrades to
OSS feature set gracefully.”
§Startup vs reload
The gate is built once at startup (dwara-bin) and rebuilt on every
config reload that carries a license block. A signature-invalid
license REFUSES to start (exit 1) at cold start; on reload, a
signature-invalid license keeps the running generation serving (the
same atomic-not-publish rollback as every other reload failure). A
missing license file refuses to start at cold start and keeps serving
on reload.
§Feature claim flags
The license’s features vector carries claim strings. The gate
checks them by exact string match. The current enterprise features
and their claim strings:
redis_rate_limiter— DW-031 (not yet implemented; the gate provides the check, the feature will call it).config_convergence— DW-054 (not yet implemented; same).redis_cache— SCALE-04 (#183): Redis-backed shared response cache.
Future enterprise features add their claim string here and call
LicenseGate::has_feature at their config-validation site.
Structs§
- License
Gate - The enterprise licensing gate.
Enums§
- License
Load Error - Error produced while loading or verifying a license.
- License
Status - The runtime status of the license gate, mirrored by the
dwara_license_statusmetric (0..=3).
Constants§
- DEFAULT_
GRACE_ PERIOD_ DAYS - Default grace period (days) after a license expires before the gate
degrades to OSS. Configurable via
gateway.license.grace_period_days(0..=30); 0 means no grace (immediate degradation on expiry). The canonical value lives incrate::config::limits(the lowest domain) so both this module andsnapshot::validateread the same number without an upward import; this re-export is the convenience path for gate consumers. - FEATURE_
CONFIG_ CONVERGENCE - License claim string for config convergence (DW-054).
- FEATURE_
FIPS - License claim string for FIPS 140-3 mode (DW-111). A license that
carries this claim REQUIRES the gateway to be running in FIPS mode
(the
fipscargo feature compiled in and the self-test passed). When the license grants this claim but the gateway is NOT in FIPS mode, the license is invalid (config-time check). - FEATURE_
REDIS_ CACHE - License claim string for the Redis shared response cache (SCALE-04, #183). A license that carries this claim enables the Redis-backed response cache so a fleet of N instances shares one cache and achieves fleet-wide hit ratios instead of N x cold caches.
- FEATURE_
REDIS_ QUOTAS - License claim string for the Redis distributed quota backend (DW-155). A license that carries this claim enables the Redis-backed quota checker so a fleet of N instances shares one counter per (consumer, budget, window) and enforces the CONFIGURED cap.
- FEATURE_
REDIS_ RATE_ LIMITER - License claim string for the Redis rate-limiter backend (DW-031).
- MAX_
GRACE_ PERIOD_ DAYS - Maximum configurable grace period (days). Re-exported from
crate::config::limitsfor the same reason asDEFAULT_GRACE_PERIOD_DAYS. - PRODUCT_
ID - The product ID this gateway verifies licenses for. Pinned so a license issued for another ShristiLabs product cannot be replayed against dwara even in the unlikely event of key reuse.
- PUBLIC_
KEY_ ENV_ VAR - The environment variable holding the base64-encoded Ed25519 public key for license verification. When unset, the compiled-in development key is used (local/CI only; production MUST set this).