UNPKG

syncguard

Version:

Functional TypeScript library for distributed locking across microservices. Prevents race conditions with Redis, PostgreSQL, Firestore, and custom backends. Features automatic lock management, timeout handling, and extensible architecture.

64 lines (63 loc) 3.78 kB
import type { HashId } from "./types.js"; /** * Generates cryptographically strong lock ID (22-char base64url from 16 CSPRNG bytes). * @returns 22-character base64url encoded lock identifier */ export declare function generateLockId(): string; /** * Canonical 96-bit hash for user keys (NFC normalized, 24 hex chars). * * @remarks **Non-cryptographic hash for observability only.** * Uses a fast triple-hash algorithm suitable for sanitization, telemetry, * and UI display. Effective 96-bit space provides low collision probability * for typical workloads. Do NOT use for security-sensitive purposes. * * @param value - User-provided key string * @returns 24-character hex hash identifier */ export declare function hashKey(value: string): HashId; /** * Formats fence token as 15-digit zero-padded string for lexicographic ordering. * Internal helper - backends use this for consistent fence formatting. * 15-digit format guarantees full safety within Lua's 53-bit precision limit * (2^53-1 ≈ 9.007e15) while providing 10^15 capacity (~31.7 years at 1M locks/sec). * @param value - Fence counter (bigint or integer number) * @returns 15-digit string (e.g., "000000000000001") * @throws {LockError} "InvalidArgument" if value is not a finite non-negative integer */ export declare function formatFence(value: bigint | number): string; /** * Canonical storage key generation algorithm (NORMATIVE). * NORMATIVE: All backends MUST use this algorithm (or a byte-for-byte equivalent). * * This is the single source of truth for storage key generation across all backends. * All backends MUST use this function; custom implementations are FORBIDDEN. * * **Requirements:** * - Measures byte length (UTF-8), not string length, for accurate backend limit checks * - Reserves bytes for backend suffixes (e.g., ":id:" + 22-char lockId ≈ 26 bytes) to prevent derived key overflows * - Hashes the FULL prefixed key when truncation is required to preserve namespace boundaries and avoid collisions * - Uses base64url encoding for hashed output compactness (128 bits → 22 chars vs. 32 hex chars) * - Normalizes key to Unicode NFC form for canonical hashing * - Fails fast if prefix + reserve makes valid keys impossible * - Uses fixed 128-bit hash truncation for strong collision resistance (~2.8e-39 prob at 10^9 keys) * - Synchronous implementation for Node.js/Bun (no async overhead) * - O(1) performance: Negligible for small keys (TextEncoder/hash/loop are fast) * * **Two-Step Fence Key Pattern**: When generating fence keys, backends MUST: * 1. Compute base storage key: `baseKey = makeStorageKey(prefix, userKey, limit, reserve)` * 2. Derive fence key from base: `fenceKey = makeStorageKey(prefix, "fence:${baseKey}", limit, reserve)` * * This ensures 1:1 mapping between user keys and fence counters when hash truncation occurs. * * @param prefix - Backend-specific prefix (e.g., "syncguard"); can be empty * @param key - User-provided key; MUST NOT be empty (validated upstream) * @param backendLimitBytes - Backend-specific byte limit (e.g., 1500 for Firestore, 1000 for Redis) * @param reserveBytes - Bytes reserved for suffixes in derived keys (e.g., Redis index/fence keys) * @returns Storage key, truncated/hashed if necessary * @throws {LockError} "InvalidArgument" if prefix + reserve exceeds limit, or if even hashed form exceeds limit * @see docs/specs/interface.md#storage-key-generation - Normative specification * @see docs/specs/interface.md#fence-key-derivation - Two-step fence key pattern * @see docs/adr/006-mandatory-key-truncation.md - Mandatory uniform key truncation rationale */ export declare function makeStorageKey(prefix: string, key: string, backendLimitBytes: number, reserveBytes: number): string;