Private
Public Access
CI / rust (push) Successful in 3m6s
CI / go (push) Successful in 33s
CI / js (push) Successful in 34s
Standalone clients that resolve a machine unique ID (OS machine ID first, falling back to a generated UUID persisted to disk), detect hostname/IP/ container/orchestrator, and register+re-ping origin.warky.dev's public service-checkin endpoint on a daily interval. Ported from icy2's internal origincheckin package but extended to the full check-in contract and made dependency-light for external reuse. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import { randomUUID } from "node:crypto";
|
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { homedir, platform, tmpdir } from "node:os";
|
|
import { dirname, join } from "node:path";
|
|
|
|
export interface Logger {
|
|
warn(msg: string, err?: unknown): void;
|
|
}
|
|
|
|
const noopLogger: Logger = { warn: () => {} };
|
|
|
|
function readLinuxMachineId(): string | undefined {
|
|
for (const path of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
try {
|
|
const id = readFileSync(path, "utf8").trim();
|
|
if (id) return id;
|
|
} catch {
|
|
// try the next candidate path
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function readDarwinMachineId(): string | undefined {
|
|
try {
|
|
const out = execFileSync("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"], {
|
|
encoding: "utf8",
|
|
timeout: 2000,
|
|
});
|
|
return out.match(/"IOPlatformUUID"\s*=\s*"([0-9A-Fa-f-]+)"/)?.[1];
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
function readWindowsMachineId(): string | undefined {
|
|
try {
|
|
const out = execFileSync(
|
|
"reg",
|
|
["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid"],
|
|
{ encoding: "utf8", timeout: 2000 },
|
|
);
|
|
return out.match(/MachineGuid\s+REG_SZ\s+([0-9A-Fa-f-]+)/)?.[1];
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/** detectOsMachineId reads the real OS machine ID, or undefined if unavailable/unsupported. */
|
|
export function detectOsMachineId(): string | undefined {
|
|
switch (platform()) {
|
|
case "linux":
|
|
return readLinuxMachineId();
|
|
case "darwin":
|
|
return readDarwinMachineId();
|
|
case "win32":
|
|
return readWindowsMachineId();
|
|
default:
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* machineIdDetector is a mutable indirection over detectOsMachineId so
|
|
* tests can stub OS machine-id lookup without depending on the actual
|
|
* host's state. It's a settable-property holder rather than a plain
|
|
* exported `let` because ES module namespace bindings can't be reassigned
|
|
* from outside the module.
|
|
*/
|
|
export const machineIdDetector: { current: () => string | undefined } = {
|
|
current: detectOsMachineId,
|
|
};
|
|
|
|
/** defaultInstallIdPath returns the fallback-UUID persistence path used when no explicit path is given. */
|
|
export function defaultInstallIdPath(): string {
|
|
const base = process.env.XDG_CONFIG_HOME || join(homedir() || tmpdir(), ".config");
|
|
return join(base, "origin-client", "install-id");
|
|
}
|
|
|
|
/**
|
|
* resolveMachineId returns the unique install ID to report to Origin, in
|
|
* priority order:
|
|
*
|
|
* 1. explicit, if non-empty - a caller-supplied override.
|
|
* 2. the real OS machine ID (/etc/machine-id on Linux, IOPlatformUUID on
|
|
* macOS, MachineGuid on Windows), if readable.
|
|
* 3. the ID already persisted at path, if present.
|
|
* 4. a newly generated UUID, which resolveMachineId attempts to persist
|
|
* to path for future runs.
|
|
*
|
|
* OS-ID and persistence failures are logged as warnings, not thrown:
|
|
* resolveMachineId always returns a usable ID.
|
|
*/
|
|
export function resolveMachineId(explicit?: string, path?: string, logger: Logger = noopLogger): string {
|
|
const trimmedExplicit = explicit?.trim();
|
|
if (trimmedExplicit) return trimmedExplicit;
|
|
|
|
const osId = machineIdDetector.current();
|
|
if (osId) {
|
|
const trimmed = osId.trim();
|
|
if (trimmed) return trimmed;
|
|
} else {
|
|
logger.warn("machine id: OS machine id unavailable, falling back to a generated id");
|
|
}
|
|
|
|
const resolvedPath = path && path.length > 0 ? path : defaultInstallIdPath();
|
|
|
|
try {
|
|
const existing = readFileSync(resolvedPath, "utf8").trim();
|
|
if (existing) return existing;
|
|
} catch {
|
|
// no persisted id yet
|
|
}
|
|
|
|
const id = randomUUID();
|
|
try {
|
|
mkdirSync(dirname(resolvedPath), { recursive: true, mode: 0o750 });
|
|
writeFileSync(resolvedPath, id + "\n", { mode: 0o600 });
|
|
} catch (err) {
|
|
logger.warn("machine id: failed to persist generated id, using an ephemeral id for this run", err);
|
|
}
|
|
return id;
|
|
}
|