4.9 KiB
Add @suaveplan/license — port-main verbatim + enterprise stack
Package: @suaveplan/license
Status: PROPOSED
Type: migration (port-main wire-format verbatim) + enterprise enhancements (additive)
- Spec delta: ./specs/license/spec.md
Why
Software license-key issuance and validation. Ports ../suaveplan/packages/security/license/ verbatim at the wire-format level (72-bit bitpacked payload, secp256k1 signature truncated to 20 bytes by default, Crockford Base32 with signature-derived obfuscation) so genesis-generated keys interoperate byte-for-byte with upstream-generated keys. Layers the genesis enterprise stack on top: SuaveplanError-typed errors with a 12-code registry, Zod boundary validation, OpenTelemetry counters/histogram, AbortSignal, injectable Clock/Rng, sibling .md docs ≥200 words each, mitata benchmarks, fast-check property tests, dep-graph test, spec-conformance test, 100/100/100/100 coverage. Adds a pluggable RevocationStore with an in-memory implementation as an opt-in offline blocklist — does not change the wire format.
Unblocks @suaveplan/server-keys (in flight; enterprise-server-server-keys).
What changes
Net-new package at version 0.1.0. Public surface (every symbol from upstream index.ts/index.types.ts/bitpack.ts/obfuscation.ts, plus enterprise additions):
- Codec:
base32Encode/base32Decode,SimpleBitPacker/SimpleBitUnpacker,packPayload/unpackPayload,obfuscateLicenseKey/deobfuscateLicenseKey/extractSignatureFromKey - Time:
getDayNumber,dayNumberToDate,checkExpiration—Clockinjectable - Flags:
hasFlag,combineFlags,hasFeature,combineFeatures,getEnabledFeatures - Generation:
generateLicense,createPayload(Rng injectable),parseLicense - Validation:
validateLicense,isValidLicense— full + truncated signature paths - Manager:
LicenseManagerclass withaddPublicKey/setSigningKey/setRevocationStore/generate/generateTrial/validate/isValid/parse/revoke/isRevoked - Revocation:
RevocationStoreinterface,createMemoryRevocationStore(LRU),fingerprintLicense,LicenseValidationError.REVOKED(additive enum variant; the other 6 variants are preserved verbatim) - Errors:
LicenseError extends SuaveplanError<LicenseErrorCode>with 12 codes (LICENSE.{INVALID_INPUT, INVALID_ENCODING, MALFORMED, PAYLOAD_OUT_OF_RANGE, UNSUPPORTED_VERSION, UNKNOWN_SIGNING_KEY, INVALID_SIGNATURE, EXPIRED, REVOKED, NO_SIGNING_KEY, FEATURE_INDEX_OUT_OF_RANGE, ABORTED}) - Schemas:
LicensePayloadSchema,LicenseGenerationOptionsSchema,LicenseValidationOptionsSchema,QuickLicenseOptionsSchema(Zod) - OTel: counter
license.generate_total, counterlicense.validate_total{license.valid}, histogramlicense.validate_duration_ms - Enums + types preserved verbatim from upstream:
TimeEncodingType,LicenseFlags,PackageTier,LicenseValidationError,LicensePayload,LicenseDetails,LicenseGenerationOptions,LicenseGenerationResult,LicenseValidationOptions,LicenseValidationSuccess,LicenseValidationFailure,LicenseValidationResult,LicenseParsedResult,LicenseManagerConfig,QuickLicenseOptions,KeyRegistry - Constants verbatim from upstream:
LICENSE_VERSION(=2),FULL_SIGNATURE_BYTES(=64),SIGNATURE_BYTES(=20),MIN_SIGNATURE_BYTES(=16),BASE32_ALPHABET,LICENSE_SCHEMA, plus genesis-addedPAYLOAD_BYTES(=9) - Subpath exports per feature module
Out of scope
- Network-based revocation (HTTP CRL/OCSP). Follow-up package; the shipped
RevocationStoreinterface accepts async implementations so the follow-up is non-breaking. - Hardware-fingerprint enforcement.
MACHINE_LOCKEDenum value is preserved (wire format); enforcement is application policy. - License rotation workflows. Business logic, owned by callers.
- Schema-registry integration. Wire format is self-describing via the 3-bit
versionfield.
Source mapping
| Capability | Upstream source | Notes |
|---|---|---|
| Wire format (72-bit payload, sig modes, Base32, obfuscation) | ../suaveplan/packages/security/license/src/{index,index.types,bitpack,obfuscation}.ts |
verbatim |
Enterprise audit requirements (no React/Node deps, Zod, fast-check, deterministic Clock/Rng, OTel, structured errors, AbortSignal, i18n-ready, 100% coverage, 200-word .md) |
../suaveplan/enterprise/license.md L37-L63 |
all addressed |
LicenseError + LICENSE_* code registry, OTel instruments, RevocationStore, Clock/Rng injection, AbortSignal plumbing, dep-graph + spec-conformance tests, mitata benchmarks |
genesis-original | genesis-wide enterprise policy (CLAUDE.md, openspec/AGENTS.md) — upstream throws plain Errors and has no OTel/Zod/revocation |
Impact
Affected dependents
None today — net-new on genesis. First consumer will be @suaveplan/server-keys (separate change enterprise-server-server-keys).