/** * Minimal ULID generator — zero dependencies, Web Crypto API only. * *. Used by the bundle writer to generate stable opaque * handles for `.noydb` containers. * * **What's a ULID?** A 128-bit identifier encoded as 26 Crockford * base32 characters. Layout: * * ``` * 01HYABCDEFGHJKMNPQRSTVWXYZ * |--------||---------------| * 48-bit 80-bit * timestamp randomness * ``` * * The first 10 chars encode a millisecond Unix timestamp (so ULIDs * sort lexicographically by creation time), and the remaining 16 * chars are random. Crockford base32 omits I/L/O/U to avoid * ambiguity in handwriting and URLs. * * **Why hand-roll instead of pulling in `ulid`?** The package adds * a dep, the implementation is ~30 lines, and the bundle module * is the only consumer. Adding `ulid` would also drag in its own * crypto polyfill that we don't need on Node 18+ or modern * browsers. * * **Privacy consideration:** the timestamp prefix is observable in * the bundle header. This is a deliberate trade-off: * - Pro: lexicographic sortability lets bundle adapters list * newest-first without an extra index. * - Con: a casual observer can read the bundle's creation time * from the handle. They cannot read it from any OTHER field * (the header explicitly forbids `_exported_at`), and a * creation timestamp is the same kind of metadata that * filesystem mtime would already expose for a downloaded * bundle. The leak is therefore equivalent to what's already * visible from the file's mtime — not a new exposure. * * If a future use case needs timestamp-free handles, a v2 of the * format could specify "use the random portion only" without a * format break — `validateBundleHeader` only checks the regex * shape, not the encoded timestamp. */ /** * Generate a fresh ULID. Uses `crypto.getRandomValues` for the * randomness portion — same Web Crypto API the rest of the * codebase uses for IVs and salt. * * Returns a 26-character string. Calling twice in the same * millisecond produces two distinct ULIDs (the random portion * differs); ULIDs from the same millisecond are NOT guaranteed * to be monotonically ordered relative to each other, only * relative to ULIDs from a different millisecond. The bundle * format never relies on intra-millisecond ordering. */ export declare function generateULID(): string; /** * Validate that a string is a syntactically well-formed ULID. Used * by the bundle header validator. Does NOT verify that the * timestamp portion decodes to a sensible date — the format only * cares about the encoding shape. */ export declare function isULID(value: string): boolean;