/** * Machine-ID provisioning — owns the per-host identity used to attribute * conflict mirrors, telemetry rows, and `.hq-conflicts/index.json` entries. * * Historically the menubar app (`indigoai-us/hq-sync`) was the sole writer * of `machineId` via `~/.hq/menubar.json`, and every other sync caller * best-effort read from there. That arrangement is backwards: hq-cloud is * the engine that runs on every sync host (macOS-with-menubar, macOS CLI, * Linux HQ Pro Outposts, future Windows), while the menubar is an optional * macOS-only UI. Linux outposts therefore had no menubar.json, so * `readShortMachineId()` returned the literal string `"unknown"` and * every conflict file on those hosts was tagged `-unknown` (which then * also slipped past `EPHEMERAL_PATH_PATTERN` in `src/cli/share.ts` — see * Fix 2 — and rode S3 round-trips as a regular file). * * This module flips ownership: hq-cloud provisions a UUID on first call * and persists it to `/.hq/machine-id` (one line, plain text). * Every subsequent call hits the persisted file. Existing macOS installs * with menubar-written IDs are migrated forward on first call: tier 3 * picks up the menubar.json value, writes it to `/.hq/machine-id`, * and returns it — so the id is stable across the migration window. * * Resolution order (first hit wins, every miss falls through): * 1. `process.env.HQ_MACHINE_ID` — explicit override for CI / tests. * 2. `/.hq/machine-id` — source-of-truth on the host. * 3. `~/.hq/menubar.json` `machineId` field — back-compat for existing * macOS installs; migrated forward to tier 2 on first read. * 4. Autogen — write a fresh UUID to `/.hq/machine-id` and return. * * Concurrent autogen race is benign: two writers each pick a fresh UUID, * last-writer-wins on disk, both processes re-read the now-stable file on * their next call. The window is narrow (single sync run startup) and the * downside (one extra conflict-file rename across a single race window) is * trivial compared to the litter-ratchet bug it replaces. */ /** * Path to `~/.hq/menubar.json`. Evaluated lazily at call time (not module * load) so tests overriding `HOME` post-import see the right file. Going * through `os.homedir()` rather than `process.env.HOME` keeps the Windows * USERPROFILE fallback intact. */ declare function menubarJsonPath(): string; /** * Path to `/.hq/machine-id` — the source-of-truth file. */ declare function hqRootMachineIdPath(hqRoot: string): string; /** * Read the persisted id from `/.hq/machine-id`, or undefined if * absent/unreadable/empty. Trims trailing whitespace so manual edits with * a final newline don't break attribution. */ declare function readHqRootMachineId(hqRoot: string): string | undefined; /** * Read the menubar-written id from `~/.hq/menubar.json`, or undefined if * the file is missing / unreadable / doesn't contain a string `machineId`. */ declare function readMenubarMachineId(): string | undefined; /** * Persist `id` to `/.hq/machine-id`. Best-effort — failures are * silent so a read-only hqRoot (e.g. a CI mount) still gets a working id * for the current process, even if it can't be persisted for the next run. */ declare function persistMachineId(hqRoot: string, id: string): void; /** * Resolve or provision the machine id for this host, persisting it to * `/.hq/machine-id` so the result is stable across sync runs. * * Returns the full id (UUID-shaped on first generation, free-form when * migrated from a menubar.json that wrote something non-UUID). Use * {@link readShortMachineId} for the 6-char prefix used in conflict * filenames. */ export declare function getOrCreateMachineId(hqRoot: string): string; /** * Short form (six hex chars) for use in conflict filenames. The short * token is what gets stamped into `.conflict--.` — * see `buildConflictPath` in `./conflict-file.ts`. * * **Always returns `[a-f0-9]{6}`** so the resulting filename matches the * `EPHEMERAL_PATH_PATTERN` in `src/cli/share.ts`. Tier 1 (`HQ_MACHINE_ID`) * and tier 3 (legacy menubar values) can return arbitrary non-hex strings * — e.g. an env override of `"ci-runner-42"` or a menubar-written * `"menubar-legacy-id"`. Slicing those raw would produce `ci-run` or * `menuba`, which the ephemeral filter would refuse and the push walker * would round-trip to S3 — the exact litter-ratchet bug this module * exists to close. * * Normalization: if the first 6 chars of the resolved id are all hex * (the typical UUID / hex-id case), use them as-is so the short token * remains an intuitive prefix of the full id. Otherwise derive a * deterministic SHA-1 hash of the full id and take the first 6 chars — * stable across calls, attributable to the same machine, always hex. */ export declare function readShortMachineId(hqRoot: string): string; /** * Test-only exports. Mirrors the `_testing` namespace pattern used by * `src/cli/share.ts` so regression-critical helpers can be pinned by * direct unit tests without round-tripping through the public API. */ export declare const _testing: { menubarJsonPath: typeof menubarJsonPath; hqRootMachineIdPath: typeof hqRootMachineIdPath; readHqRootMachineId: typeof readHqRootMachineId; readMenubarMachineId: typeof readMenubarMachineId; persistMachineId: typeof persistMachineId; }; export {}; //# sourceMappingURL=machine-id.d.ts.map