device-id
Source: device-id.js:13
The machine's identity for the per-seat device cap: a random UUID, created once and reused forever. Main-process only, like everything auth-adjacent.
On macOS it lives in the Keychain (via /usr/bin/security), which survives app deletion and app-data wipes — a reinstall keeps its slot. Anywhere the Keychain isn't available (other platforms, locked keychain) it falls back to a plain JSON file in userData; the ID is random and grants nothing by itself, so the file needs no encryption — the only cost of the fallback is that wiping app data makes the machine look new (one self-service deactivation fixes that).
Instance Methods
keychainRead(): string
Read the device ID from the macOS Keychain.
Returns
string— The stored ID, or null when absent or the Keychain is unavailable.
keychainWrite(id: string): boolean
Write the device ID to the macOS Keychain.
Parameters
id(string) — Device UUID to store.
Returns
boolean— True on success, false when the Keychain refused.
getDeviceId(userDataDir: string): string
Get-or-create the device ID, stable across calls. Prefers the Keychain on macOS and falls back to userData/device-id.json when the Keychain refuses, on other platforms, or when EZL_PASSWORD_STORE=basic. That env var is the existing test hook (e2e + headless CI): it opts safeStorage out of the OS keychain, and device identity follows — the throwaway test profile gets a file-backed ID, so every e2e launch is a fresh machine and tests never write to the developer's real Keychain. An unreadable or first-run file mints a fresh UUID and writes it.
Parameters
userDataDir(string) — Electron userData directory (app.getPath('userData')).
Returns
string— The device UUID.
Other
SERVICE
Keychain service name the device ID is stored under. @type {string}