/** * Device Identity Module * @module @skillsmith/core/config/device-identity * * SMI-5391: Cross-harness inventory sync — device identity and push throttle. * * Manages a stable client-generated device UUID persisted in ~/.skillsmith/config.json * under the `inventory` namespace. Provides helpers for labelling the device, tracking * the last inventory push timestamp, and determining when an auto-push is due. * * The SERVER (`user_telemetry_preferences.inventory_sync_enabled`) remains the source * of truth for consent. `isInventorySyncDisabledLocally()` is a fast-path LOCAL * opt-out that short-circuits the upload before it starts. * * @example * ```typescript * import { * getOrCreateDeviceId, * getLastInventoryPushAt, * shouldAutoPush, * recordInventoryPush, * } from './device-identity.js' * * const deviceId = getOrCreateDeviceId() * if (shouldAutoPush(Date.now(), getLastInventoryPushAt())) { * // ...build + upload the snapshot for `deviceId`... * recordInventoryPush(new Date().toISOString()) * } * ``` */ /** * Return the persisted device UUID, or `undefined` if none has been created yet. * * Pure read — no side effects. * * SMI-5391 */ export declare function getDeviceId(): string | undefined; /** * Return the persisted device UUID, creating and persisting a new v4 UUID if none exists. * * The generated UUID satisfies the edge-function validator regex: * `/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i` * * Preserves any existing `deviceLabel` and `lastPushAt` during the write. * Concurrency-safe across processes (SMI-5531) — see * {@link getOrCreatePersistedId}. * * SMI-5391 */ export declare function getOrCreateDeviceId(): string; /** * Return the persisted per-install telemetry identifier, creating and * persisting a new one (`sha256(randomUUID())`) if none exists yet. * * SMI-5531: generated and persisted UNCONDITIONALLY — this call must * succeed and persist an id regardless of `SKILLSMITH_TELEMETRY_ENABLED` / * `POSTHOG_API_KEY`, which is exactly the env-gated condition that made the * legacy `context.distinctId` inert for virtually every real user. If a * future refactor re-couples this to that legacy gate, this fix is inert * again under a new field name — do not add any env/flag check here. * * Concurrency-safe across processes — see {@link getOrCreatePersistedId}. */ export declare function getOrCreateInstallId(): string; /** * Set (or clear) the optional user-facing label for this device. * * Passing `undefined` removes `deviceLabel` from the persisted block while * preserving `deviceId` and `lastPushAt`. * * SMI-5391 * * @param label - Human-readable device name, or `undefined` to clear. */ export declare function setDeviceLabel(label: string | undefined): void; /** * Clear the device identity so the next inventory push registers a fresh device. * * Implementation note: delegates to `saveConfig({ inventory: undefined })`, which * removes the entire `inventory` block (including `deviceLabel` if set). This is the * simplest correct approach and is explicitly acceptable per the SMI-5391 spec. A * subsequent `getOrCreateDeviceId()` call will generate a new UUID. * * SMI-5391 */ export declare function forgetDevice(): void; /** * Return `true` when the local env flag opts this device out of inventory sync. * * Checks `SKILLSMITH_INVENTORY_DISABLE` — accepts `'1'` or `'true'` * (case-insensitive). This is a LOCAL fast-path opt-out only; the SERVER * (`user_telemetry_preferences.inventory_sync_enabled`) remains the authoritative * consent gate. * * SMI-5391 */ export declare function isInventorySyncDisabledLocally(): boolean; /** * Return the ISO timestamp of the last successful inventory push, or `undefined`. * * SMI-5391 */ export declare function getLastInventoryPushAt(): string | undefined; /** * Persist an ISO timestamp marking a successful inventory push. * * Preserves any existing `deviceId` and `deviceLabel` during the write. * * SMI-5391 * * @param timestampIso - ISO 8601 timestamp (e.g. `new Date().toISOString()`). */ export declare function recordInventoryPush(timestampIso: string): void; /** * Return `true` when an auto-push is due. * * Pure function — `now` is injected for deterministic tests (reuses the * SMI-4590 session-throttle convention). * * @param now - Current Unix epoch in milliseconds (e.g. `Date.now()`). * @param lastPushAt - ISO timestamp of the previous push; `undefined` means never pushed. * @param throttleMs - Minimum gap between pushes in milliseconds (default: 24 h). * @returns `true` if `lastPushAt` is absent, unparseable, or at/beyond `throttleMs` ago. * * SMI-5391 */ export declare function shouldAutoPush(now: number, lastPushAt?: string, throttleMs?: number): boolean; //# sourceMappingURL=device-identity.d.ts.map