first commit
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# `@suaveplan/license` — constants
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Wire-format constants for the license package. Every value here
|
||||
is part of the binary contract: the per-field bit widths
|
||||
(`FIELD_BITS`), the Base32 alphabet, the signature lengths, the version
|
||||
byte, and the day-to-millisecond conversion factor. Changing any
|
||||
constant breaks every existing license key, so they live in their own
|
||||
module and are imported by every code path that touches the format.
|
||||
|
||||
## Features
|
||||
|
||||
- `LICENSE_VERSION` (currently `2`) — pinned by the 3-bit version field;
|
||||
`validateLicense` rejects any payload with a higher version.
|
||||
- `FULL_SIGNATURE_BYTES` (64) / `SIGNATURE_BYTES` (20) /
|
||||
`MIN_SIGNATURE_BYTES` (16) — the three signature-length thresholds
|
||||
honoured by generation and validation.
|
||||
- `BASE32_ALPHABET` — 32-char Crockford-style alphabet (no I/L/O/U) used
|
||||
by both encode and decode.
|
||||
- `LICENSE_SCHEMA` — per-field maximum values, used by Zod schemas and
|
||||
by the bounds checks in `packPayload`.
|
||||
- `FIELD_BITS` — per-field bit widths summing to 72, consumed by the
|
||||
bitpacker.
|
||||
- `PAYLOAD_BYTES` (9), `OBFUSCATION_PAYLOAD_CHARS` (15), and
|
||||
`MS_PER_DAY` (86 400 000) — derived constants pulled out so callers
|
||||
don't have to recompute them.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { LICENSE_VERSION, BASE32_ALPHABET } from "@suaveplan/license/constants/constants";
|
||||
|
||||
console.log(`Targeting wire format v${LICENSE_VERSION}`);
|
||||
console.log(`Alphabet size: ${BASE32_ALPHABET.length}`); // 32
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Bounds-checking a payload field at the application layer before
|
||||
constructing it:
|
||||
|
||||
```ts
|
||||
import { LICENSE_SCHEMA } from "@suaveplan/license/constants/constants";
|
||||
import type { LicensePayload } from "@suaveplan/license/types/license";
|
||||
|
||||
function clampPayload(p: LicensePayload): LicensePayload {
|
||||
return {
|
||||
...p,
|
||||
productId: Math.min(p.productId, LICENSE_SCHEMA.productId),
|
||||
timeValue: Math.min(p.timeValue, LICENSE_SCHEMA.timeValue),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Symbol | Type | Value |
|
||||
|---|---|---|
|
||||
| `LICENSE_VERSION` | `2` | Current format version |
|
||||
| `FULL_SIGNATURE_BYTES` | `64` | secp256k1 compact signature length |
|
||||
| `SIGNATURE_BYTES` | `20` | Default truncated-signature length |
|
||||
| `MIN_SIGNATURE_BYTES` | `16` | Lowest acceptable truncation |
|
||||
| `BASE32_ALPHABET` | `string` | `0-9A-HJKMNP-TV-Z` (32 chars) |
|
||||
| `LICENSE_SCHEMA` | `Readonly<Record<field, max>>` | Per-field max values |
|
||||
| `FIELD_BITS` | `Readonly<Record<field, bits>>` | Per-field bit widths |
|
||||
| `PAYLOAD_BYTES` | `9` | Packed payload size |
|
||||
| `OBFUSCATION_PAYLOAD_CHARS` | `15` | Chars rotated by obfuscation |
|
||||
| `MS_PER_DAY` | `86_400_000` | UTC day in milliseconds |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Every constant is declared `as const`, so its TypeScript type is the
|
||||
literal value (e.g. `LICENSE_VERSION: 2`), giving exhaustiveness benefits
|
||||
when compared in `switch` statements. The two records (`LICENSE_SCHEMA`
|
||||
and `FIELD_BITS`) are also frozen at the type level via `as const`,
|
||||
preventing accidental mutation through their `Readonly` view.
|
||||
Reference in New Issue
Block a user