first commit
This commit is contained in:
85
docs/security-stack/security/license/src/time/time.md
Normal file
85
docs/security-stack/security/license/src/time/time.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# `@suaveplan/license` — time
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Time-encoding helpers for the four `TimeEncodingType` variants. The
|
||||
72-bit payload encodes time in 18 bits with an additional 2-bit
|
||||
discriminator (`NONE` / `ABSOLUTE_DAYS` / `RELATIVE_DAYS` /
|
||||
`ABSOLUTE_TIMESTAMP`), giving four distinct expiration strategies. This
|
||||
module turns those numeric fields into concrete `{ isExpired,
|
||||
expirationDate }` records and lets callers inject a `Clock` (from
|
||||
`@suaveplan/types`) for deterministic test runs.
|
||||
|
||||
## Features
|
||||
|
||||
- Four expiration strategies, one switch — no separate code paths per
|
||||
call site.
|
||||
- Injectable `Clock` parameter; defaults to `Date.now()` so production
|
||||
callers don't have to thread it through.
|
||||
- `getDayNumber` / `dayNumberToDate` round-trip helpers used by
|
||||
generation when computing absolute-day expirations.
|
||||
- Default-arm fall-through returns `{ isExpired: false }` for unknown
|
||||
encodings, matching upstream's permissive behaviour (so a future
|
||||
encoding variant never bricks an older validator).
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { checkExpiration } from "@suaveplan/license/time/time";
|
||||
import { TimeEncodingType } from "@suaveplan/license/types/license";
|
||||
|
||||
const r = checkExpiration(TimeEncodingType.NONE, 0);
|
||||
console.log(r.isExpired); // false (perpetual)
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Threading a deterministic `Clock` through to relative-day expiry:
|
||||
|
||||
```ts
|
||||
import type { Clock } from "@suaveplan/types";
|
||||
import { checkExpiration } from "@suaveplan/license/time/time";
|
||||
import { TimeEncodingType } from "@suaveplan/license/types/license";
|
||||
|
||||
const clock: Clock = () => Date.UTC(2026, 5, 17, 12, 0, 0);
|
||||
const creation = new Date("2026-06-01T00:00:00Z");
|
||||
const r = checkExpiration(
|
||||
TimeEncodingType.RELATIVE_DAYS,
|
||||
14,
|
||||
undefined, // use clock
|
||||
creation,
|
||||
clock
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `getDayNumber(date?: Date, clock?: Clock): number`
|
||||
|
||||
Days since the Unix epoch. Uses `date.getTime()` when provided, otherwise
|
||||
the injected `clock` (default `Date.now()`).
|
||||
|
||||
### `dayNumberToDate(dayNumber: number): Date`
|
||||
|
||||
Days since Unix epoch → `Date`.
|
||||
|
||||
### `checkExpiration(timeEncodingType, timeValue, referenceDate?, creationDate?, clock?): { isExpired, expirationDate? }`
|
||||
|
||||
Determine expiration for a license. `referenceDate` defaults to
|
||||
`new Date(clock())`. `creationDate` is consulted only for
|
||||
`RELATIVE_DAYS` (falls back to `referenceDate`).
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The unknown-encoding default arm (`return { isExpired: false }`) is
|
||||
intentional — it makes adding a new encoding variant a backward-
|
||||
compatible change for existing validators, which is important because
|
||||
license keys are long-lived and may outlive the validator that
|
||||
originally minted them. The `clock` parameter sits last in the
|
||||
argument list and defaults to `Date.now()`, so the public
|
||||
`checkExpiration` call site stays compact in normal usage and only
|
||||
expands when a test needs determinism.
|
||||
Reference in New Issue
Block a user