import { createHash, randomBytes as createRandomBytes, randomUUID as createRandomUUID, } from "node:crypto"; import { spawn } from "node:child_process"; import * as defaultFileSystem from "node:fs/promises"; import { homedir } from "node:os"; import { basename, dirname, isAbsolute, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import packageManifest from "../../package.json" with { type: "json" }; import { lockDownLocalPath } from "../infrastructure/local-process.js"; import { isPrivateBrowserLaunchUrl } from "../browser.js"; import { getLocalProcessIdentity } from "../infrastructure/process-identity.js"; import { acquireLocalIntegrationLifecycleLock } from "./local-integration-lifecycle-lock.js"; const CONTROL_DIRECTORY = "control"; const PUBLICATION_FILE = "dashboard.json"; const CONTROL_KEY_FILE = "control.key"; const BROWSER_KEY_FILE = "browser.key"; const BROWSER_LAUNCH_DIRECTORY = "browser-launches"; const CONTROL_STATE_PREFIX = ".state-v1-"; const CONTROL_PUBLISHING_PREFIX = ".publishing-v1-"; const CONTROL_FINALIZING_PREFIX = ".finalizing-v1-"; const RETIRING_DIRECTORY = "retiring"; const RETIREMENT_PAYLOAD_FILE = "payload"; const ROOT_MARKER_FILE = ".managed-by-relmio-root.json"; const LOCK_DIRECTORY = "dashboard.lock"; const ROOT_MARKER_KEYS = Object.freeze(["kind", "schemaVersion"]); const PUBLICATION_KEYS = Object.freeze([ "instanceId", "kind", "origin", "packageVersion", "pid", "processStartIdentity", "protocolVersion", "publishedAtMs", "schemaVersion", ]); const ROOT_MARKER = Object.freeze({ schemaVersion: 1, kind: "relmio-local-root" }); const PUBLICATION_SCHEMA_VERSION = 1; const CONTROL_PROTOCOL_VERSION = 1; const CONTROL_KIND = "relmio-dashboard-control"; const PACKAGE_VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:(?:0|[1-9]\d*)|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:(?:0|[1-9]\d*)|\d*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u; const CURRENT_PACKAGE_VERSION = packageManifest.version; if (!PACKAGE_VERSION_PATTERN.test(CURRENT_PACKAGE_VERSION)) { throw new TypeError("The Relmio package version is invalid."); } const MAX_PUBLICATION_BYTES = 4 * 1024; const MAX_MARKER_BYTES = 1024; const MAX_PROCESS_ID = 2_147_483_647; const MAX_IDENTITY_BYTES = 512; const SESSION_TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/u; const CONTROL_TOKEN_PATTERN = /^[A-P][A-Za-z0-9_-]{42}$/u; const BROWSER_TOKEN_PATTERN = /^[w-z0-9_-][A-Za-z0-9_-]{42}$/u; const INSTANCE_ID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/iu; const CONTENT_DIGEST_PATTERN = /^[A-Za-z0-9_-]{43}$/u; const CONTROL_STATE_PATTERN = /^\.state-v1-([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})-([A-Za-z0-9_-]{43})-([A-Za-z0-9_-]{43})-([A-Za-z0-9_-]{43})$/iu; const CONTROL_PUBLISHING_PATTERN = /^\.publishing-v1-([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})-([A-Za-z0-9_-]{43})-([A-Za-z0-9_-]{43})-([A-Za-z0-9_-]{43})$/iu; const CONTROL_FINALIZING_PATTERN = /^\.finalizing-v1-([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})-([A-Za-z0-9_-]{43})-([A-Za-z0-9_-]{43})-([A-Za-z0-9_-]{43})$/iu; const RETIREMENT_SLOT_PATTERN = /^\.slot-v1-(root|publication|control|browser)-([0-9]+)-([0-9]+)-([0-9]+)-([A-Za-z0-9_-]{43})$/u; const HEALTH_PATH = "/__relmio/control/status"; const STOP_PATH = "/__relmio/control/stop"; const BROWSER_PREPARE_PATH = "/__relmio/browser/prepare"; const DEFAULT_REQUEST_TIMEOUT_MS = 3_000; const DEFAULT_STARTUP_TIMEOUT_MS = 10_000; const PRIVATE_DAEMON_COMMAND = "__relmio-dashboard-daemon"; const DEFAULT_CLI_PATH = fileURLToPath(new URL("../cli.js", import.meta.url)); const DAEMON_ENVIRONMENT_NAMES = new Set([ "PATH", "Path", "HOME", "USERPROFILE", "HOMEDRIVE", "HOMEPATH", "LOCALAPPDATA", "APPDATA", "TMPDIR", "TMP", "TEMP", "SystemRoot", "SYSTEMROOT", "WINDIR", "COMSPEC", "ComSpec", "PATHEXT", "LANG", "TZ", "RELMIO_HOME", "CODEX_HOME", "N8N_OPENAI_OAUTH_HOME", "SSH_AUTH_SOCK", "DOCKER_HOST", "DOCKER_CONTEXT", "DOCKER_CONFIG", "DOCKER_TLS_VERIFY", "DOCKER_CERT_PATH", "BUILDKIT_HOST", ]); const LOCALE_ENVIRONMENT_NAME = /^LC_(?:ALL|COLLATE|CTYPE|MESSAGES|MONETARY|NUMERIC|TIME)$/u; function fail(message) { return new Error(`Relmio ${message}.`); } function isMissing(error) { return error?.code === "ENOENT"; } function exactKeys(value, expected) { return value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).sort().join("\0") === [...expected].sort().join("\0"); } function validateManagedHome(value) { if ( typeof value !== "string" || value.trim() === "" || value.includes("\0") || !isAbsolute(value) ) { throw new TypeError("Relmio local storage path is invalid."); } const normalized = resolve(value); if (basename(normalized) !== ".relmio") { throw new TypeError("Relmio local storage path is invalid."); } return normalized; } async function resolveControlPaths({ env, homeDirectory, fileSystem }) { if (!env || typeof env !== "object" || typeof homeDirectory !== "string") { throw new TypeError("The local dashboard control adapter is invalid."); } const usesCustomRoot = typeof env.RELMIO_HOME === "string" && env.RELMIO_HOME.trim() !== ""; const requested = validateManagedHome( usesCustomRoot ? env.RELMIO_HOME : resolve(homeDirectory, ".relmio"), ); let canonicalParent; try { canonicalParent = await fileSystem.realpath(dirname(requested)); } catch { throw fail("could not verify the parent of its local storage directory"); } if (canonicalParent !== resolve(dirname(requested))) { throw fail("refuses a local storage path with a symbolic-link ancestor"); } const relmioHome = join(canonicalParent, ".relmio"); const controlRoot = join(relmioHome, CONTROL_DIRECTORY); return Object.freeze({ relmioHome, rootMarkerPath: join(relmioHome, ROOT_MARKER_FILE), controlRoot, publicationPath: join(controlRoot, PUBLICATION_FILE), controlKeyPath: join(controlRoot, CONTROL_KEY_FILE), browserKeyPath: join(controlRoot, BROWSER_KEY_FILE), browserLaunchRoot: join(relmioHome, BROWSER_LAUNCH_DIRECTORY), lockPath: join(relmioHome, `${CONTROL_DIRECTORY}.lock`), stagingRoot: join(relmioHome, `${CONTROL_DIRECTORY}.staging`), retiredRoot: join(relmioHome, `${CONTROL_DIRECTORY}.retired`), changedMarkerPath: join(relmioHome, `${CONTROL_DIRECTORY}.changed`), bootstrapRoot: join(canonicalParent, ".relmio.bootstrap"), bootstrapLockPath: join(canonicalParent, ".relmio.bootstrap.lock"), parentPath: canonicalParent, requirePrivateParentAcl: usesCustomRoot, }); } async function lstatIfExists(fileSystem, path) { try { return await fileSystem.lstat(path, { bigint: true }); } catch (error) { if (isMissing(error)) return null; throw fail("could not inspect its local dashboard control state"); } } function isExactFileSystemInteger(value, { minimum = 0, maximum = null } = {}) { if (typeof value === "bigint") { return value >= BigInt(minimum) && (maximum === null || value <= BigInt(maximum)); } return Number.isSafeInteger(value) && value >= minimum && (maximum === null || value <= maximum); } function exactMode(metadata, mask) { if (typeof metadata?.mode === "bigint") { return Number(metadata.mode & BigInt(mask)); } return Number.isInteger(metadata?.mode) ? metadata.mode & mask : null; } function exactAccountIdMatches(value, expected) { if (expected === null) return true; if (typeof value === "bigint") return value === BigInt(expected); return Number.isSafeInteger(value) && value === expected; } function exactFileSystemIntegerEquals(value, expected) { if (typeof value === "bigint") return value === BigInt(expected); return Number.isSafeInteger(value) && value === expected; } function exactFileSystemTimestamp(metadata, name) { const nanoseconds = metadata?.[`${name}Ns`]; if (typeof nanoseconds === "bigint") return nanoseconds; if (nanoseconds !== undefined) return null; const milliseconds = metadata?.[`${name}Ms`]; if (typeof milliseconds !== "number" || !Number.isFinite(milliseconds)) return null; return milliseconds; } function sameFileSystemTimestamp(left, right) { return left !== null && right !== null && typeof left === typeof right && left === right; } function assertPrivateMetadata(metadata, { kind, platform, maxBytes, expectedUid }) { const expectedType = kind === "directory" ? metadata?.isDirectory?.() : metadata?.isFile?.(); const expectedMode = kind === "directory" ? 0o700 : 0o600; if ( !expectedType || metadata.isSymbolicLink?.() || (kind === "file" && ( !isExactFileSystemInteger(metadata.size, { maximum: maxBytes }) )) || (platform !== "win32" && ( exactMode(metadata, 0o777) !== expectedMode || !exactAccountIdMatches(metadata.uid, expectedUid) )) ) { throw fail("refuses unsafe local dashboard control state"); } } function fingerprint(metadata, raw) { const identity = pathFingerprint(metadata); const modifiedAt = exactFileSystemTimestamp(metadata, "mtime"); const changedAt = exactFileSystemTimestamp(metadata, "ctime"); if ( !isExactFileSystemInteger(metadata?.size) || modifiedAt === null || changedAt === null ) { throw fail("could not fingerprint local dashboard control state"); } return Object.freeze({ raw, ...identity, size: metadata.size, modifiedAt, changedAt, }); } function sameFingerprint(left, right) { return left.raw === right.raw && left.dev === right.dev && left.ino === right.ino && left.size === right.size && sameFileSystemTimestamp(left.modifiedAt, right.modifiedAt) && sameFileSystemTimestamp(left.changedAt, right.changedAt); } function sameMovedFingerprint(left, right) { return left.raw === right.raw && left.dev === right.dev && left.ino === right.ino && left.size === right.size && sameFileSystemTimestamp(left.modifiedAt, right.modifiedAt); } function pathFingerprint(metadata) { if ( !isExactFileSystemInteger(metadata?.dev) || !isExactFileSystemInteger(metadata?.ino, { minimum: 1 }) ) { throw fail("could not fingerprint local dashboard control state"); } return Object.freeze({ dev: metadata.dev, ino: metadata.ino }); } function samePathFingerprint(left, right) { return left?.dev === right?.dev && left?.ino === right?.ino; } function sameOpenFile(metadata, other) { return metadata?.dev === other?.dev && metadata?.ino === other?.ino && metadata?.size === other?.size && sameFileSystemTimestamp( exactFileSystemTimestamp(metadata, "mtime"), exactFileSystemTimestamp(other, "mtime"), ) && sameFileSystemTimestamp( exactFileSystemTimestamp(metadata, "ctime"), exactFileSystemTimestamp(other, "ctime"), ); } async function inspectPrivatePath({ fileSystem, path, kind, platform, lockDownPath, maxBytes, expectedUid, verifyEffectiveOwnerOnly = false, }) { let metadata = await lstatIfExists(fileSystem, path); if (!metadata) return null; assertPrivateMetadata(metadata, { kind, platform, maxBytes, expectedUid }); if (platform === "win32") { await lockDownPath(path, { platform, ...(kind === "file" ? { kind: "file" } : {}), verifyOnly: true, ...(verifyEffectiveOwnerOnly ? { verifyEffectiveOwnerOnly: true } : {}), }); metadata = await lstatIfExists(fileSystem, path); assertPrivateMetadata(metadata, { kind, platform, maxBytes, expectedUid }); } return metadata; } async function verifyParentBoundary({ fileSystem, path, platform, lockDownPath, expectedUid, requirePrivateAcl = false, }) { // The signed-in OS account and local Administrators are trust anchors. Windows // default profile directories legitimately grant SYSTEM/Administrators access, // so strict owner-only ACL verification starts at the managed .relmio root. // A caller-selected parent must itself meet that stricter ACL contract. let metadata = await lstatIfExists(fileSystem, path); if (!metadata?.isDirectory?.() || metadata.isSymbolicLink?.()) { throw fail("refuses an unsafe local dashboard storage parent"); } if (platform === "win32") { if (requirePrivateAcl) { await lockDownPath(path, { platform, verifyOnly: true }); metadata = await lstatIfExists(fileSystem, path); if (!metadata?.isDirectory?.() || metadata.isSymbolicLink?.()) { throw fail("refuses an unsafe local dashboard storage parent"); } } } else { const mode = exactMode(metadata, 0o7777); if (mode === null) throw fail("refuses an unsafe local dashboard storage parent"); const writableByOthers = (mode & 0o022) !== 0; const sticky = (mode & 0o1000) !== 0; if ( !exactAccountIdMatches(metadata.uid, expectedUid) || (writableByOthers && !sticky) ) throw fail("refuses an unsafe local dashboard storage parent"); } return pathFingerprint(metadata); } async function captureDirectoryAnchor({ fileSystem, path, platform, lockDownPath, expectedUid, }) { const metadata = await inspectPrivatePath({ fileSystem, path, kind: "directory", platform, lockDownPath, expectedUid, }); if (!metadata) throw fail("detected a missing local dashboard storage boundary"); return Object.freeze({ path, fingerprint: pathFingerprint(metadata) }); } async function assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }) { if (!Array.isArray(anchors) || anchors.length === 0) { throw new TypeError("The local dashboard storage anchors are invalid."); } for (const anchor of anchors) { let currentFingerprint; if (anchor.kind === "parent") { currentFingerprint = await verifyParentBoundary({ fileSystem, path: anchor.path, platform, lockDownPath, expectedUid, requirePrivateAcl: anchor.requirePrivateAcl, }); } else { const metadata = await inspectPrivatePath({ fileSystem, path: anchor.path, kind: "directory", platform, lockDownPath, expectedUid, }); if (!metadata) throw fail("detected a missing local dashboard storage boundary"); currentFingerprint = pathFingerprint(metadata); } if (!samePathFingerprint(currentFingerprint, anchor.fingerprint)) { throw fail("detected a changed local dashboard storage boundary"); } } } async function readPrivateFile(options) { const { fileSystem, path, platform, lockDownPath, maxBytes, expectedUid, verifyEffectiveOwnerOnly = false, } = options; const before = await inspectPrivatePath({ fileSystem, path, kind: "file", platform, lockDownPath, maxBytes, expectedUid, verifyEffectiveOwnerOnly, }); if (!before) return null; let handle; let openedBefore; let openedAfter; let raw; try { handle = await fileSystem.open(path, "r"); openedBefore = await handle.stat({ bigint: true }); assertPrivateMetadata(openedBefore, { kind: "file", platform, maxBytes, expectedUid, }); if (!sameOpenFile(before, openedBefore)) throw new TypeError(); raw = await handle.readFile("utf8"); openedAfter = await handle.stat({ bigint: true }); if (!sameOpenFile(openedBefore, openedAfter)) throw new TypeError(); } catch { throw fail("could not safely read its local dashboard control state"); } finally { try { await handle?.close(); } catch { /* A later path check still fails closed. */ } } const rawBytes = Buffer.byteLength(raw); if (rawBytes > maxBytes || !exactFileSystemIntegerEquals(openedAfter.size, rawBytes)) { throw fail("refuses oversized or changed local dashboard control state"); } const after = await inspectPrivatePath({ fileSystem, path, kind: "file", platform, lockDownPath, maxBytes, expectedUid, verifyEffectiveOwnerOnly, }); if ( !after || !sameOpenFile(before, after) || !sameFingerprint(fingerprint(before, raw), fingerprint(after, raw)) ) { throw fail("detected changed local dashboard control state"); } return Object.freeze({ raw, fingerprint: fingerprint(after, raw) }); } function validateOrigin(origin) { if (typeof origin !== "string" || origin.length > 64) throw new TypeError(); const match = /^http:\/\/127\.0\.0\.1:([1-9][0-9]{0,4})$/u.exec(origin); if (!match) throw new TypeError(); const port = Number(match[1]); if (!Number.isInteger(port) || port > 65_535) throw new TypeError(); const parsed = new URL(origin); if ( parsed.protocol !== "http:" || parsed.hostname !== "127.0.0.1" || parsed.pathname !== "/" || parsed.search || parsed.hash || parsed.username || parsed.password ) throw new TypeError(); return origin; } function validatePublication(value) { try { if ( !exactKeys(value, PUBLICATION_KEYS) || value.schemaVersion !== PUBLICATION_SCHEMA_VERSION || value.kind !== CONTROL_KIND || value.protocolVersion !== CONTROL_PROTOCOL_VERSION || !PACKAGE_VERSION_PATTERN.test(value.packageVersion) || !Number.isSafeInteger(value.pid) || value.pid < 1 || value.pid > MAX_PROCESS_ID || typeof value.processStartIdentity !== "string" || value.processStartIdentity.length === 0 || Buffer.byteLength(value.processStartIdentity) > MAX_IDENTITY_BYTES || /[\0\r\n]/u.test(value.processStartIdentity) || !INSTANCE_ID_PATTERN.test(value.instanceId) || validateOrigin(value.origin) !== value.origin || !Number.isSafeInteger(value.publishedAtMs) || value.publishedAtMs < 1 ) throw new TypeError(); return Object.freeze({ ...value }); } catch { throw fail("refuses malformed local dashboard control state"); } } function parseExactJson(raw, keys, expected) { try { const value = JSON.parse(raw); if (!exactKeys(value, keys)) throw new TypeError(); for (const [key, expectedValue] of Object.entries(expected)) { if (value[key] !== expectedValue) throw new TypeError(); } return value; } catch { throw fail("refuses an invalid local managed-root marker"); } } function validateSecret(raw, role) { const rolePattern = role === "control" ? CONTROL_TOKEN_PATTERN : BROWSER_TOKEN_PATTERN; if (!SESSION_TOKEN_PATTERN.test(raw) || !rolePattern.test(raw)) { throw fail("refuses an invalid local dashboard control key"); } return raw; } function digestContent(raw) { return createHash("sha256").update(raw, "utf8").digest("base64url"); } function createControlStateDescriptor({ publicationRaw, controlToken, browserToken, instanceId }) { if (!INSTANCE_ID_PATTERN.test(instanceId)) { throw fail("could not create a dashboard state identity"); } const digests = [publicationRaw, controlToken, browserToken].map(digestContent); if (digests.some((digest) => !CONTENT_DIGEST_PATTERN.test(digest))) { throw fail("could not create dashboard state fingerprints"); } const name = `${CONTROL_STATE_PREFIX}${instanceId}-${digests.join("-")}`; const publishingName = `${CONTROL_PUBLISHING_PREFIX}${instanceId}-${digests.join("-")}`; const finalizingName = `${CONTROL_FINALIZING_PREFIX}${instanceId}-${digests.join("-")}`; return Object.freeze({ name, readyName: name, publishingName, finalizingName, instanceId, publicationDigest: digests[0], controlDigest: digests[1], browserDigest: digests[2], }); } function parseControlStateDescriptor(name, phase = "ready") { const pattern = phase === "publishing" ? CONTROL_PUBLISHING_PATTERN : phase === "finalizing" ? CONTROL_FINALIZING_PATTERN : CONTROL_STATE_PATTERN; const match = pattern.exec(name); if (!match) throw fail("refuses an invalid local dashboard state marker"); const suffix = `${match[1]}-${match[2]}-${match[3]}-${match[4]}`; return Object.freeze({ name, readyName: `${CONTROL_STATE_PREFIX}${suffix}`, publishingName: `${CONTROL_PUBLISHING_PREFIX}${suffix}`, finalizingName: `${CONTROL_FINALIZING_PREFIX}${suffix}`, instanceId: match[1], publicationDigest: match[2], controlDigest: match[3], browserDigest: match[4], }); } function sameControlStateDescriptor(left, right) { return Boolean(left && right && left.readyName === right.readyName); } const CONTROL_ENTRY_DETAILS = Object.freeze([ Object.freeze({ name: PUBLICATION_FILE, property: "publicationRecord", role: "publication", maxBytes: MAX_PUBLICATION_BYTES, digestProperty: "publicationDigest", }), Object.freeze({ name: CONTROL_KEY_FILE, property: "controlKeyRecord", role: "control", maxBytes: 43, digestProperty: "controlDigest", }), Object.freeze({ name: BROWSER_KEY_FILE, property: "browserKeyRecord", role: "browser", maxBytes: 43, digestProperty: "browserDigest", }), ]); function parseRetirementSlot(name) { const match = RETIREMENT_SLOT_PATTERN.exec(name); if (!match) throw fail("refuses changed local dashboard retirement state"); const dev = BigInt(match[2]); const ino = BigInt(match[3]); const size = BigInt(match[4]); if ( dev < 0n || ino < 1n || size < 0n ) throw fail("refuses changed local dashboard retirement state"); return Object.freeze({ name, role: match[1], dev, ino, size, digest: match[5], }); } function createRetirementSlotDescriptor(role, record) { const { dev, ino, size } = record?.fingerprint ?? {}; if ( !["root", "publication", "control", "browser"].includes(role) || !isExactFileSystemInteger(dev) || !isExactFileSystemInteger(ino, { minimum: 1 }) || !isExactFileSystemInteger(size) ) throw fail("could not reserve local dashboard retirement state"); const digest = digestContent(record.raw); return parseRetirementSlot(`.slot-v1-${role}-${dev}-${ino}-${size}-${digest}`); } function maxBytesForRetirementRole(role) { if (role === "root") return MAX_MARKER_BYTES; const detail = CONTROL_ENTRY_DETAILS.find((entry) => entry.role === role); if (!detail) throw fail("refuses changed local dashboard retirement state"); return detail.maxBytes; } function recordMatchesRetirementSlot(record, slot) { return Boolean( record && record.fingerprint.dev === slot.dev && record.fingerprint.ino === slot.ino && record.fingerprint.size === slot.size && digestContent(record.raw) === slot.digest ); } async function inspectRetirementSlots({ fileSystem, retiringPath, platform, lockDownPath, expectedUid, }) { const metadata = await inspectPrivatePath({ fileSystem, path: retiringPath, kind: "directory", platform, lockDownPath, expectedUid, }); if (!metadata) throw fail("refuses changed local dashboard retirement state"); let entries; try { entries = (await fileSystem.readdir(retiringPath)).sort(); } catch { throw fail("could not inspect its local dashboard retirement state"); } const slots = new Map(); for (const entry of entries) { const descriptor = parseRetirementSlot(entry); if (slots.has(descriptor.role)) { throw fail("refuses changed local dashboard retirement state"); } const slotPath = join(retiringPath, entry); await inspectPrivatePath({ fileSystem, path: slotPath, kind: "directory", platform, lockDownPath, expectedUid, }); let slotEntries; try { slotEntries = (await fileSystem.readdir(slotPath)).sort(); } catch { throw fail("could not inspect its local dashboard retirement state"); } if ( slotEntries.length > 1 || (slotEntries.length === 1 && slotEntries[0] !== RETIREMENT_PAYLOAD_FILE) ) throw fail("refuses changed local dashboard retirement state"); let payloadRecord = null; if (slotEntries.length === 1) { payloadRecord = await readPrivateFile({ fileSystem, path: join(slotPath, RETIREMENT_PAYLOAD_FILE), platform, lockDownPath, expectedUid, maxBytes: maxBytesForRetirementRole(descriptor.role), verifyEffectiveOwnerOnly: descriptor.role === "root", }); if (!recordMatchesRetirementSlot(payloadRecord, descriptor)) { throw fail("refuses changed local dashboard retirement state"); } } slots.set(descriptor.role, Object.freeze({ descriptor, slotPath, payloadPath: join(slotPath, RETIREMENT_PAYLOAD_FILE), payloadRecord, })); } return slots; } function safeResult(state, publication) { if (!publication) return Object.freeze({ state }); return Object.freeze({ state, pid: publication.pid, instanceId: publication.instanceId, origin: publication.origin, publishedAtMs: publication.publishedAtMs, packageVersion: publication.packageVersion, }); } function validIdentity(value) { return value && typeof value === "object" && !Array.isArray(value) && ( value.state === "dead" || value.state === "ambiguous" || ( value.state === "active" && typeof value.startIdentity === "string" && value.startIdentity.length > 0 && Buffer.byteLength(value.startIdentity) <= MAX_IDENTITY_BYTES && !/[\0\r\n]/u.test(value.startIdentity) ) ); } function exactHealth(value, publication) { return exactKeys(value, [ "instanceId", "kind", "origin", "packageVersion", "pid", "protocolVersion", ]) && value.kind === CONTROL_KIND && value.protocolVersion === CONTROL_PROTOCOL_VERSION && value.instanceId === publication.instanceId && value.pid === publication.pid && value.origin === publication.origin && value.packageVersion === publication.packageVersion; } async function fetchJson(fetchImpl, url, options, timeoutMs, expectedStatus = 200) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeoutMs); timer.unref?.(); try { const response = await fetchImpl(url, { ...options, signal: controller.signal, redirect: "error" }); if ( !response || response.status !== expectedStatus || response.ok !== true || typeof response.json !== "function" ) { return null; } return await response.json(); } finally { clearTimeout(timer); } } async function fetchStopResponse(fetchImpl, url, options, timeoutMs) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeoutMs); timer.unref?.(); try { const response = await fetchImpl(url, { ...options, signal: controller.signal, redirect: "error", }); if (response?.status === 409) return Object.freeze({ state: "busy" }); if ( !response || response.status !== 202 || response.ok !== true || typeof response.json !== "function" ) { return Object.freeze({ state: "invalid" }); } try { return Object.freeze({ state: "accepted", value: await response.json() }); } catch { return Object.freeze({ state: "invalid" }); } } finally { clearTimeout(timer); } } async function inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }) { const controlMetadata = await inspectPrivatePath({ fileSystem, path: paths.controlRoot, kind: "directory", platform, lockDownPath, expectedUid, }); if (!controlMetadata) return Object.freeze({ kind: "absent", paths }); let entries; try { entries = (await fileSystem.readdir(paths.controlRoot)).sort(); } catch { throw fail("could not inspect its local dashboard control directory"); } const controlDirectoryFingerprint = pathFingerprint(controlMetadata); if (entries.length === 0) { return Object.freeze({ kind: "incomplete", paths, controlDirectoryFingerprint, descriptor: null, }); } const readyMarkerNames = entries.filter((entry) => entry.startsWith(CONTROL_STATE_PREFIX)); const publishingMarkerNames = entries.filter((entry) => entry.startsWith(CONTROL_PUBLISHING_PREFIX)); const finalizingMarkerNames = entries.filter((entry) => entry.startsWith(CONTROL_FINALIZING_PREFIX)); const dataNames = new Set([PUBLICATION_FILE, CONTROL_KEY_FILE, BROWSER_KEY_FILE]); if ( readyMarkerNames.length > 1 || publishingMarkerNames.length > 1 || finalizingMarkerNames.length > 1 || readyMarkerNames.length + publishingMarkerNames.length + finalizingMarkerNames.length === 0 || entries.some((entry) => ( !dataNames.has(entry) && !readyMarkerNames.includes(entry) && !publishingMarkerNames.includes(entry) && !finalizingMarkerNames.includes(entry) )) ) { throw fail("refuses unexpected local dashboard control files"); } const readyDescriptor = readyMarkerNames.length === 1 ? parseControlStateDescriptor(readyMarkerNames[0], "ready") : null; const publishingDescriptor = publishingMarkerNames.length === 1 ? parseControlStateDescriptor(publishingMarkerNames[0], "publishing") : null; const finalizingDescriptor = finalizingMarkerNames.length === 1 ? parseControlStateDescriptor(finalizingMarkerNames[0], "finalizing") : null; const descriptors = [readyDescriptor, publishingDescriptor, finalizingDescriptor].filter(Boolean); if (descriptors.some((descriptor) => ( !sameControlStateDescriptor(descriptor, descriptors[0]) ))) throw fail("refuses mismatched local dashboard publication phases"); const inspectMarker = async (descriptor) => { if (!descriptor) return null; const markerPath = join(paths.controlRoot, descriptor.name); await inspectPrivatePath({ fileSystem, path: markerPath, kind: "directory", platform, lockDownPath, expectedUid, }); let markerEntries; try { markerEntries = (await fileSystem.readdir(markerPath)).sort(); } catch { throw fail("could not inspect its local dashboard state marker"); } if ( markerEntries.length > 1 || (markerEntries.length === 1 && markerEntries[0] !== RETIRING_DIRECTORY) ) throw fail("refuses unexpected local dashboard retirement state"); const retiringPath = markerEntries.length === 1 ? join(markerPath, RETIRING_DIRECTORY) : null; const retirementSlots = retiringPath ? await inspectRetirementSlots({ fileSystem, retiringPath, platform, lockDownPath, expectedUid, }) : new Map(); return Object.freeze({ markerPath, retiringPath, retirementSlots }); }; const readyMarker = await inspectMarker(readyDescriptor); const publishingMarker = await inspectMarker(publishingDescriptor); const finalizingMarker = await inspectMarker(finalizingDescriptor); if (finalizingMarker?.retiringPath) { throw fail("refuses changed local dashboard finalization state"); } if (readyMarker && publishingMarker?.retiringPath) { throw fail("refuses conflicting local dashboard publication phases"); } if (finalizingMarker && publishingMarker?.retiringPath) { throw fail("refuses conflicting local dashboard finalization state"); } const committed = Boolean(readyDescriptor || finalizingDescriptor); const descriptor = readyDescriptor ?? finalizingDescriptor ?? publishingDescriptor; const activeMarker = readyMarker ?? publishingMarker; const retiringPath = activeMarker?.retiringPath ?? null; const retirementSlots = activeMarker?.retirementSlots ?? new Map(); const retiring = Boolean(retiringPath || finalizingMarker); const records = {}; for (const { name, property, maxBytes, digestProperty } of CONTROL_ENTRY_DETAILS) { if (!entries.includes(name)) continue; const record = await readPrivateFile({ fileSystem, path: join(paths.controlRoot, name), platform, lockDownPath, expectedUid, maxBytes, }); if (!record || (committed && digestContent(record.raw) !== descriptor[digestProperty])) { throw fail("refuses changed local dashboard control state"); } records[property] = record; } let publication; if (committed && records.publicationRecord) { let parsed; try { parsed = JSON.parse(records.publicationRecord.raw); } catch { throw fail("refuses malformed local dashboard control state"); } publication = validatePublication(parsed); if (publication.instanceId !== descriptor.instanceId) { throw fail("refuses mismatched local dashboard state identity"); } } if (committed && records.controlKeyRecord) validateSecret(records.controlKeyRecord.raw, "control"); if (committed && records.browserKeyRecord) validateSecret(records.browserKeyRecord.raw, "browser"); if ( committed && records.controlKeyRecord && records.browserKeyRecord && records.controlKeyRecord.raw === records.browserKeyRecord.raw ) throw fail("refuses reused local dashboard control keys"); const complete = Boolean( records.publicationRecord && records.controlKeyRecord && records.browserKeyRecord, ); if (finalizingMarker && !retiringPath && Object.keys(records).length !== 0) { throw fail("refuses changed local dashboard finalization state"); } if (committed && !retiring && !complete) { throw fail("refuses incomplete committed local dashboard control state"); } if (retiring) { for (const slot of retirementSlots.values()) { if (slot.descriptor.role === "root") { throw fail("refuses changed local dashboard retirement state"); } const detail = CONTROL_ENTRY_DETAILS.find(({ role }) => role === slot.descriptor.role); const record = detail ? records[detail.property] : null; if (record && slot.payloadRecord) { throw fail("refuses changed local dashboard retirement state"); } if (record && !slot.payloadRecord && !recordMatchesRetirementSlot(record, slot.descriptor)) { throw fail("refuses changed local dashboard retirement state"); } if (committed && slot.descriptor.digest !== descriptor[detail.digestProperty]) { throw fail("refuses changed local dashboard retirement state"); } } } return Object.freeze({ kind: retiring ? "retiring" : committed ? "ready" : "publishing", paths, controlDirectoryFingerprint, descriptor, markerPath: activeMarker?.markerPath ?? finalizingMarker.markerPath, readyMarkerPath: readyMarker?.markerPath ?? null, finalizingMarkerPath: finalizingMarker?.markerPath ?? null, retiringPath, retirementSlots, publishingMarkerPath: publishingMarker?.markerPath ?? null, publication, ...records, }); } async function inspectInternal({ env, homeDirectory, fileSystem, platform, lockDownPath, getProcessIdentity, fetchImpl, requestTimeoutMs, expectedUid, }) { const paths = await resolveControlPaths({ env, homeDirectory, fileSystem }); await verifyParentBoundary({ fileSystem, path: paths.parentPath, platform, lockDownPath, expectedUid, requirePrivateAcl: paths.requirePrivateParentAcl, }); const homeMetadata = await inspectPrivatePath({ fileSystem, path: paths.relmioHome, kind: "directory", platform, lockDownPath, expectedUid, }); if (!homeMetadata) return Object.freeze({ state: "absent", paths }); const markerRecord = await readPrivateFile({ fileSystem, path: paths.rootMarkerPath, platform, lockDownPath, maxBytes: MAX_MARKER_BYTES, expectedUid, verifyEffectiveOwnerOnly: true, }); if (!markerRecord) throw fail("refuses a local storage directory without its managed-root marker"); parseExactJson(markerRecord.raw, ROOT_MARKER_KEYS, ROOT_MARKER); const layout = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if (layout.kind === "absent") return Object.freeze({ state: "absent", paths }); if ( layout.kind === "incomplete" || layout.kind === "publishing" || layout.kind === "retiring" ) { return Object.freeze({ state: layout.kind, ...layout }); } const { publication, publicationRecord, controlKeyRecord, browserKeyRecord, controlDirectoryFingerprint, descriptor, markerPath, } = layout; const controlToken = controlKeyRecord.raw; let identity; try { identity = await getProcessIdentity(publication.pid); } catch { identity = null; } const details = { paths, controlDirectoryFingerprint, descriptor, markerPath, publication, publicationRecord, controlKeyRecord, browserKeyRecord, }; if (!validIdentity(identity) || identity.state === "ambiguous") { return Object.freeze({ ...safeResult("ambiguous", publication), ...details }); } if (identity.state === "dead") { return Object.freeze({ ...safeResult("dead", publication), ...details }); } if (identity.startIdentity !== publication.processStartIdentity) { return Object.freeze({ ...safeResult("pid-reused", publication), ...details }); } let response = null; try { response = await fetchJson(fetchImpl, `${publication.origin}${HEALTH_PATH}`, { method: "GET", headers: { "X-Relmio-Control": controlToken }, }, requestTimeoutMs); } catch { /* An active process without an exact response is unresponsive. */ } const state = exactHealth(response, publication) ? publication.packageVersion === CURRENT_PACKAGE_VERSION ? "healthy" : "version-mismatch" : "unresponsive"; return Object.freeze({ ...safeResult(state, publication), ...details }); } function currentUid(platform, getUid) { if (platform === "win32" || getUid === undefined) return null; if (typeof getUid !== "function") { throw new TypeError("The local dashboard control adapter is invalid."); } const uid = getUid(); if (!Number.isSafeInteger(uid) || uid < 0) { throw new TypeError("The local dashboard control adapter is invalid."); } return uid; } function validateAdapters({ fileSystem, lockDownPath, getProcessIdentity, fetchImpl, requestTimeoutMs, platform }) { if ( !fileSystem || typeof fileSystem.realpath !== "function" || typeof fileSystem.lstat !== "function" || typeof fileSystem.open !== "function" || typeof fileSystem.readFile !== "function" || typeof lockDownPath !== "function" || typeof getProcessIdentity !== "function" || typeof fetchImpl !== "function" || !Number.isSafeInteger(requestTimeoutMs) || requestTimeoutMs < 1 || requestTimeoutMs > 30_000 || typeof platform !== "string" || platform.length === 0 ) { throw new TypeError("The local dashboard control adapter is invalid."); } } export async function inspectLocalDashboardControlPlane({ env = process.env, homeDirectory = homedir(), fileSystem = defaultFileSystem, platform = process.platform, lockDownPath = lockDownLocalPath, getProcessIdentity = getLocalProcessIdentity, fetchImpl = fetch, requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS, getUid = process.getuid?.bind(process), } = {}) { validateAdapters({ fileSystem, lockDownPath, getProcessIdentity, fetchImpl, requestTimeoutMs, platform }); const expectedUid = currentUid(platform, getUid); const result = await inspectInternal({ env, homeDirectory, fileSystem, platform, lockDownPath, getProcessIdentity, fetchImpl, requestTimeoutMs, expectedUid, }); return safeResult(result.state, result.publication); } async function createPrivateDirectory({ fileSystem, path, platform, lockDownPath, expectedUid, anchors = null, requireNew = false, }) { if (anchors) { await assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }); } let created = false; try { await fileSystem.mkdir(path, { mode: 0o700 }); created = true; } catch (error) { if (error?.code !== "EEXIST") { throw fail("could not create its private dashboard control directory"); } if (requireNew) { throw fail("refuses to overwrite an existing dashboard control destination"); } } if (created) { try { await fileSystem.chmod(path, 0o700); await lockDownPath(path, { platform }); } catch { try { await fileSystem.rmdir(path); } catch { /* Preserve any changed/non-empty path. */ } throw fail("could not protect its private dashboard control directory"); } } await inspectPrivatePath({ fileSystem, path, kind: "directory", platform, lockDownPath, expectedUid, }); if (anchors) { await assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }); } return created; } async function writePrivateFile({ fileSystem, path, raw, platform, lockDownPath, expectedUid, maxBytes, anchors, }) { if ( typeof raw !== "string" || Buffer.byteLength(raw) > maxBytes || !Array.isArray(anchors) || anchors.length === 0 ) { throw new TypeError("The local dashboard private file is invalid."); } await assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }); let handle; let createdMetadata; try { handle = await fileSystem.open(path, "wx", 0o600); await handle.chmod(0o600); createdMetadata = await handle.stat({ bigint: true }); assertPrivateMetadata(createdMetadata, { kind: "file", platform, maxBytes, expectedUid, }); await assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }); await lockDownPath(path, { platform, kind: "file" }); const protectedMetadata = await inspectPrivatePath({ fileSystem, path, kind: "file", platform, lockDownPath, maxBytes, expectedUid, }); if ( !protectedMetadata || !samePathFingerprint(pathFingerprint(createdMetadata), pathFingerprint(protectedMetadata)) ) { throw fail("detected a replaced private dashboard control file"); } await assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }); await handle.writeFile(raw, "utf8"); await handle.sync?.(); const writtenMetadata = await handle.stat({ bigint: true }); if ( writtenMetadata.dev !== createdMetadata.dev || writtenMetadata.ino !== createdMetadata.ino || !exactFileSystemIntegerEquals(writtenMetadata.size, Buffer.byteLength(raw)) ) { throw fail("could not verify its private dashboard control write"); } await assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }); } catch (error) { if (error?.code === "EEXIST") throw fail("refuses to overwrite existing local dashboard control state"); try { await handle?.close(); } catch { /* Preserve the original failure. */ } // Leave the file inside its durable publishing directory. Recovery moves // that reserved entry before deleting it, so a partial write is retryable // without a check-then-unlink race against a final pathname. if (error?.message?.startsWith("Relmio ")) throw error; throw fail("could not publish its private dashboard control state"); } try { await handle.close(); } catch { throw fail("could not close its private dashboard control state"); } const record = await readPrivateFile({ fileSystem, path, platform, lockDownPath, maxBytes, expectedUid, }); if (!record || record.raw !== raw) throw fail("could not verify its private dashboard control state"); return record; } async function finishRetirementSlot({ fileSystem, sourcePath, expectedRecord, slot, platform, lockDownPath, expectedUid, maxBytes, anchors, verifyEffectiveOwnerOnly = false, }) { let payloadRecord = slot.payloadRecord; let sourceRecord = await readPrivateFile({ fileSystem, path: sourcePath, platform, lockDownPath, expectedUid, maxBytes, verifyEffectiveOwnerOnly, }); if (sourceRecord && expectedRecord && !sameFingerprint( sourceRecord.fingerprint, expectedRecord.fingerprint, )) throw fail("refuses to retire changed local dashboard control state"); if (sourceRecord && !recordMatchesRetirementSlot(sourceRecord, slot.descriptor)) { throw fail("refuses to retire changed local dashboard control state"); } if (sourceRecord && payloadRecord) { throw fail("refuses changed local dashboard retirement state"); } const slotAnchor = await captureDirectoryAnchor({ fileSystem, path: slot.slotPath, platform, lockDownPath, expectedUid, }); const guardedAnchors = [...anchors, slotAnchor]; if (sourceRecord) { await assertDirectoryAnchors({ fileSystem, anchors: guardedAnchors, platform, lockDownPath, expectedUid, }); try { await fileSystem.rename(sourcePath, slot.payloadPath); } catch { throw fail("could not move verified local dashboard state into retirement"); } await assertDirectoryAnchors({ fileSystem, anchors: guardedAnchors, platform, lockDownPath, expectedUid, }); payloadRecord = await readPrivateFile({ fileSystem, path: slot.payloadPath, platform, lockDownPath, expectedUid, maxBytes, verifyEffectiveOwnerOnly, }); if ( !recordMatchesRetirementSlot(payloadRecord, slot.descriptor) || !sameMovedFingerprint(sourceRecord.fingerprint, payloadRecord.fingerprint) ) { // Preserve the moved replacement for inspection. The signed-in account is // the local trust boundary; the lifecycle lock excludes every conforming // same-account writer, and Node has no portable unlink-by-handle primitive. throw fail("detected changed local dashboard state while moving it into retirement"); } if (await lstatIfExists(fileSystem, sourcePath)) { throw fail("detected replaced local dashboard control state after retirement move"); } } if (payloadRecord) { const verifiedPayload = await readPrivateFile({ fileSystem, path: slot.payloadPath, platform, lockDownPath, expectedUid, maxBytes, verifyEffectiveOwnerOnly, }); if ( !recordMatchesRetirementSlot(verifiedPayload, slot.descriptor) || !sameFingerprint(verifiedPayload.fingerprint, payloadRecord.fingerprint) ) throw fail("refuses to remove changed local dashboard retirement payload"); await assertDirectoryAnchors({ fileSystem, anchors: guardedAnchors, platform, lockDownPath, expectedUid, }); try { await fileSystem.unlink(slot.payloadPath); } catch { throw fail("could not remove verified local dashboard retirement payload"); } if (await lstatIfExists(fileSystem, slot.payloadPath)) { throw fail("detected replaced local dashboard retirement payload after removal"); } } await assertDirectoryAnchors({ fileSystem, anchors, platform, lockDownPath, expectedUid, }); try { await fileSystem.rmdir(slot.slotPath); } catch { throw fail("could not finish local dashboard retirement slot"); } } async function retirePrivateFile({ fileSystem, sourcePath, expectedRecord, role, retiringPath, existingSlot = null, platform, lockDownPath, expectedUid, maxBytes, anchors, verifyEffectiveOwnerOnly = false, }) { let slot = existingSlot; if (!slot) { if (!expectedRecord) return; const descriptor = createRetirementSlotDescriptor(role, expectedRecord); const slotPath = join(retiringPath, descriptor.name); await createPrivateDirectory({ fileSystem, path: slotPath, platform, lockDownPath, expectedUid, anchors, requireNew: true, }); slot = Object.freeze({ descriptor, slotPath, payloadPath: join(slotPath, RETIREMENT_PAYLOAD_FILE), payloadRecord: null, }); } if (slot.descriptor.role !== role) { throw fail("refuses changed local dashboard retirement state"); } await finishRetirementSlot({ fileSystem, sourcePath, expectedRecord, slot, platform, lockDownPath, expectedUid, maxBytes, anchors, verifyEffectiveOwnerOnly, }); } async function directoryEntries(fileSystem, path, message) { try { return (await fileSystem.readdir(path)).sort(); } catch { throw fail(message); } } async function finishRootRetirement({ paths, fileSystem, platform, lockDownPath, expectedUid, parentAnchor, bootstrapAnchor, sourcePath, sourceRecord, removeHome, }) { const retiringPath = join(paths.bootstrapRoot, RETIRING_DIRECTORY); const retiringMetadata = await inspectPrivatePath({ fileSystem, path: retiringPath, kind: "directory", platform, lockDownPath, expectedUid, }); if (!retiringMetadata) { await createPrivateDirectory({ fileSystem, path: retiringPath, platform, lockDownPath, expectedUid, anchors: [parentAnchor, bootstrapAnchor], requireNew: true, }); } const retiringAnchor = await captureDirectoryAnchor({ fileSystem, path: retiringPath, platform, lockDownPath, expectedUid, }); const slots = await inspectRetirementSlots({ fileSystem, retiringPath, platform, lockDownPath, expectedUid, }); if (slots.size > 1 || (slots.size === 1 && !slots.has("root"))) { throw fail("refuses changed dashboard root bootstrap retirement state"); } const anchors = [parentAnchor, bootstrapAnchor, retiringAnchor]; if (removeHome) { const homeMetadata = await inspectPrivatePath({ fileSystem, path: paths.relmioHome, kind: "directory", platform, lockDownPath, expectedUid, }); if (homeMetadata) { anchors.push(await captureDirectoryAnchor({ fileSystem, path: paths.relmioHome, platform, lockDownPath, expectedUid, })); } } await retirePrivateFile({ fileSystem, sourcePath, expectedRecord: sourceRecord, role: "root", retiringPath, existingSlot: slots.get("root") ?? null, platform, lockDownPath, expectedUid, maxBytes: MAX_MARKER_BYTES, anchors, verifyEffectiveOwnerOnly: true, }); if (removeHome && await lstatIfExists(fileSystem, paths.relmioHome)) { const entries = await directoryEntries( fileSystem, paths.relmioHome, "could not inspect its incomplete local storage directory", ); if (entries.length !== 0) { throw fail("refuses changed dashboard root bootstrap state"); } try { await fileSystem.rmdir(paths.relmioHome); } catch { throw fail("could not recover its incomplete local storage directory"); } } try { await fileSystem.rmdir(retiringPath); } catch { throw fail("could not finish dashboard root bootstrap retirement"); } try { await fileSystem.rmdir(paths.bootstrapRoot); } catch { throw fail("could not finish legacy dashboard root bootstrap recovery"); } } async function recoverRootBootstrap({ paths, fileSystem, platform, lockDownPath, expectedUid, parentAnchor, }) { const metadata = await inspectPrivatePath({ fileSystem, path: paths.bootstrapRoot, kind: "directory", platform, lockDownPath, expectedUid, }); if (!metadata) return; const bootstrapAnchor = Object.freeze({ path: paths.bootstrapRoot, fingerprint: pathFingerprint(metadata), }); const entries = await directoryEntries( fileSystem, paths.bootstrapRoot, "could not inspect dashboard root bootstrap state", ); const legacyNames = [ROOT_MARKER_FILE, `${ROOT_MARKER_FILE}.retired`]; const directMarkers = entries.filter((entry) => legacyNames.includes(entry)); if ( directMarkers.length > 1 || entries.some((entry) => entry !== RETIRING_DIRECTORY && !legacyNames.includes(entry)) || (directMarkers.length === 1 && entries.length > 2) ) throw fail("refuses unexpected dashboard root bootstrap state"); if (directMarkers.length === 1) { const sourcePath = join(paths.bootstrapRoot, directMarkers[0]); const sourceRecord = await readPrivateFile({ fileSystem, path: sourcePath, platform, lockDownPath, expectedUid, maxBytes: MAX_MARKER_BYTES, verifyEffectiveOwnerOnly: true, }); if (!sourceRecord) throw fail("refuses changed dashboard root bootstrap state"); parseExactJson(sourceRecord.raw, ROOT_MARKER_KEYS, ROOT_MARKER); await finishRootRetirement({ paths, fileSystem, platform, lockDownPath, expectedUid, parentAnchor, bootstrapAnchor, sourcePath, sourceRecord, removeHome: false, }); return; } const retiring = entries.includes(RETIRING_DIRECTORY); const homeMetadata = await inspectPrivatePath({ fileSystem, path: paths.relmioHome, kind: "directory", platform, lockDownPath, expectedUid, }); let homeEntries = []; let rootRecord = null; if (homeMetadata) { homeEntries = await directoryEntries( fileSystem, paths.relmioHome, "could not inspect its incomplete local storage directory", ); if (homeEntries.some((entry) => entry !== ROOT_MARKER_FILE) || homeEntries.length > 1) { throw fail("refuses changed dashboard root bootstrap state"); } if (homeEntries.includes(ROOT_MARKER_FILE)) { rootRecord = await readPrivateFile({ fileSystem, path: paths.rootMarkerPath, platform, lockDownPath, expectedUid, maxBytes: MAX_MARKER_BYTES, verifyEffectiveOwnerOnly: true, }); if (!rootRecord) throw fail("refuses changed dashboard root bootstrap state"); } } if (!retiring && rootRecord) { let complete = false; try { parseExactJson(rootRecord.raw, ROOT_MARKER_KEYS, ROOT_MARKER); complete = true; } catch (error) { if (!error?.message?.startsWith("Relmio refuses an invalid local managed-root marker")) { throw error; } // A malformed marker is retryable only while this exclusive bootstrap // phase proves that the first publication never committed. } if (complete) { await assertDirectoryAnchors({ fileSystem, anchors: [parentAnchor, bootstrapAnchor], platform, lockDownPath, expectedUid, }); try { await fileSystem.rmdir(paths.bootstrapRoot); } catch { throw fail("could not commit its local managed-root marker"); } return; } } if (!retiring && !homeMetadata) { try { await fileSystem.rmdir(paths.bootstrapRoot); } catch { throw fail("could not finish dashboard root bootstrap recovery"); } return; } await finishRootRetirement({ paths, fileSystem, platform, lockDownPath, expectedUid, parentAnchor, bootstrapAnchor, sourcePath: paths.rootMarkerPath, sourceRecord: rootRecord, removeHome: true, }); } async function ensureManagedControlRoot({ env, homeDirectory, fileSystem, platform, lockDownPath, expectedUid, getProcessIdentity, now, }) { const paths = await resolveControlPaths({ env, homeDirectory, fileSystem }); const initialParentFingerprint = await verifyParentBoundary({ fileSystem, path: paths.parentPath, platform, lockDownPath, expectedUid, requirePrivateAcl: paths.requirePrivateParentAcl, }); const parentAnchor = Object.freeze({ kind: "parent", path: paths.parentPath, fingerprint: initialParentFingerprint, requirePrivateAcl: paths.requirePrivateParentAcl, }); let releaseBootstrapLock; try { releaseBootstrapLock = await acquireLocalIntegrationLifecycleLock({ fileSystem, getProcessIdentity, lockDownPath, lockPath: paths.bootstrapLockPath, now, platform, label: "local dashboard root bootstrap lock", }); await assertDirectoryAnchors({ fileSystem, anchors: [parentAnchor], platform, lockDownPath, expectedUid, }); await recoverRootBootstrap({ paths, fileSystem, platform, lockDownPath, expectedUid, parentAnchor, }); let homeMetadata = await inspectPrivatePath({ fileSystem, path: paths.relmioHome, kind: "directory", platform, lockDownPath, expectedUid, }); if (homeMetadata) { const marker = await readPrivateFile({ fileSystem, path: paths.rootMarkerPath, platform, lockDownPath, expectedUid, maxBytes: MAX_MARKER_BYTES, verifyEffectiveOwnerOnly: true, }); if (!marker) { let entries; try { entries = await fileSystem.readdir(paths.relmioHome); } catch { throw fail("could not inspect its incomplete local storage directory"); } if (entries.length !== 0) { throw fail("refuses a local storage directory without its managed-root marker"); } await assertDirectoryAnchors({ fileSystem, anchors: [parentAnchor], platform, lockDownPath, expectedUid, }); try { await fileSystem.rmdir(paths.relmioHome); } catch { throw fail("could not recover its empty local storage directory"); } homeMetadata = null; } else { parseExactJson(marker.raw, ROOT_MARKER_KEYS, ROOT_MARKER); } } if (!homeMetadata) { await createPrivateDirectory({ fileSystem, path: paths.bootstrapRoot, platform, lockDownPath, expectedUid, anchors: [parentAnchor], requireNew: true, }); const bootstrapAnchor = await captureDirectoryAnchor({ fileSystem, path: paths.bootstrapRoot, platform, lockDownPath, expectedUid, }); await createPrivateDirectory({ fileSystem, path: paths.relmioHome, platform, lockDownPath, expectedUid, anchors: [parentAnchor], requireNew: true, }); const homeAnchor = await captureDirectoryAnchor({ fileSystem, path: paths.relmioHome, platform, lockDownPath, expectedUid, }); try { const marker = await writePrivateFile({ fileSystem, path: paths.rootMarkerPath, raw: `${JSON.stringify(ROOT_MARKER)}\n`, platform, lockDownPath, expectedUid, maxBytes: MAX_MARKER_BYTES, anchors: [parentAnchor, bootstrapAnchor, homeAnchor], }); parseExactJson(marker.raw, ROOT_MARKER_KEYS, ROOT_MARKER); } catch (error) { throw error; } await assertDirectoryAnchors({ fileSystem, anchors: [parentAnchor, bootstrapAnchor, homeAnchor], platform, lockDownPath, expectedUid, }); try { await fileSystem.rmdir(paths.bootstrapRoot); } catch { throw fail("could not commit its local managed-root marker"); } } const finalHomeAnchor = await captureDirectoryAnchor({ fileSystem, path: paths.relmioHome, platform, lockDownPath, expectedUid, }); await assertDirectoryAnchors({ fileSystem, anchors: [parentAnchor, finalHomeAnchor], platform, lockDownPath, expectedUid, }); } catch (error) { try { await releaseBootstrapLock?.(); } catch { /* Preserve the root failure. */ } throw error; } await releaseBootstrapLock(); return paths; } async function ensurePrivateBrowserLaunchRoot({ paths, fileSystem, platform, lockDownPath, expectedUid, }) { const homeAnchor = await captureDirectoryAnchor({ fileSystem, path: paths.relmioHome, platform, lockDownPath, expectedUid, }); await createPrivateDirectory({ fileSystem, path: paths.browserLaunchRoot, platform, lockDownPath, expectedUid, anchors: [homeAnchor], }); await assertDirectoryAnchors({ fileSystem, anchors: [homeAnchor], platform, lockDownPath, expectedUid, }); return paths.browserLaunchRoot; } function createRoleToken(randomBytes, role) { let bytes; try { bytes = Buffer.from(randomBytes(32)); } catch { throw fail("could not create a strong dashboard control key"); } if (bytes.length !== 32) throw fail("could not create a strong dashboard control key"); bytes[0] = role === "control" ? bytes[0] & 0x3f : bytes[0] | 0xc0; return validateSecret(bytes.toString("base64url"), role); } async function cleanupLegacyControlArtifacts(options) { const { paths, fileSystem } = options; for (const path of [ paths.changedMarkerPath, paths.retiredRoot, paths.stagingRoot, `${paths.stagingRoot}.retired`, ]) { if (await lstatIfExists(fileSystem, path)) { // These names came from an unreleased rename-based prototype. There is no // durable content fingerprint to distinguish its crash residue from // same-account replacement, so preserving it is the only safe recovery. throw fail("refuses unsupported legacy dashboard control state"); } } } async function removeExactControlState(state, options) { const { fileSystem, platform, lockDownPath, expectedUid } = options; const paths = state.paths; let current = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if (current.kind === "absent") return; if ( state.controlDirectoryFingerprint && !samePathFingerprint(current.controlDirectoryFingerprint, state.controlDirectoryFingerprint) ) { throw fail("refuses to remove replaced local dashboard control state"); } if (state.descriptor && !sameControlStateDescriptor(current.descriptor, state.descriptor)) { throw fail("refuses to remove replaced local dashboard state marker"); } if (!current.descriptor) { try { await fileSystem.rmdir(paths.controlRoot); } catch { throw fail("refuses changed incomplete local dashboard control state"); } return; } const homeAnchor = await captureDirectoryAnchor({ fileSystem, path: paths.relmioHome, platform, lockDownPath, expectedUid, }); const controlAnchor = Object.freeze({ path: paths.controlRoot, fingerprint: current.controlDirectoryFingerprint, }); const markerAnchor = await captureDirectoryAnchor({ fileSystem, path: current.markerPath, platform, lockDownPath, expectedUid, }); const requestedRetiringPath = join(current.markerPath, RETIRING_DIRECTORY); if (current.kind !== "retiring") { await createPrivateDirectory({ fileSystem, path: requestedRetiringPath, platform, lockDownPath, expectedUid, anchors: [homeAnchor, controlAnchor, markerAnchor], requireNew: true, }); } current = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if ( current.kind !== "retiring" || !sameControlStateDescriptor(current.descriptor, state.descriptor) || !samePathFingerprint(current.controlDirectoryFingerprint, controlAnchor.fingerprint) ) { throw fail("refuses changed local dashboard retirement state"); } if (current.retiringPath) { const retiringAnchor = await captureDirectoryAnchor({ fileSystem, path: current.retiringPath, platform, lockDownPath, expectedUid, }); const retirementAnchors = [homeAnchor, controlAnchor, markerAnchor, retiringAnchor]; for (const { name, property, role, maxBytes } of CONTROL_ENTRY_DETAILS) { const record = current[property] ?? null; const slot = current.retirementSlots.get(role) ?? null; if (!record && !slot) continue; await retirePrivateFile({ fileSystem, sourcePath: join(paths.controlRoot, name), expectedRecord: record, role, retiringPath: current.retiringPath, existingSlot: slot, platform, lockDownPath, expectedUid, maxBytes, anchors: retirementAnchors, }); } } const committed = Boolean(current.readyMarkerPath || current.finalizingMarkerPath); let finalizingMarkerPath = current.finalizingMarkerPath; if (committed && !finalizingMarkerPath) { finalizingMarkerPath = join(paths.controlRoot, current.descriptor.finalizingName); await createPrivateDirectory({ fileSystem, path: finalizingMarkerPath, platform, lockDownPath, expectedUid, anchors: [homeAnchor, controlAnchor, markerAnchor], requireNew: true, }); const finalizingState = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if ( finalizingState.kind !== "retiring" || finalizingState.finalizingMarkerPath !== finalizingMarkerPath || !sameControlStateDescriptor(finalizingState.descriptor, current.descriptor) ) throw fail("could not verify local dashboard finalization state"); } if (current.retiringPath) { try { await fileSystem.rmdir(current.retiringPath); } catch { throw fail("could not finish dashboard retirement cleanup"); } } const markerPaths = [current.publishingMarkerPath, current.readyMarkerPath] .filter((path, index, pathsToRemove) => ( path && path !== finalizingMarkerPath && pathsToRemove.indexOf(path) === index )); for (const markerPath of markerPaths) { const markerToRemoveAnchor = await captureDirectoryAnchor({ fileSystem, path: markerPath, platform, lockDownPath, expectedUid, }); await assertDirectoryAnchors({ fileSystem, anchors: [homeAnchor, controlAnchor, markerToRemoveAnchor], platform, lockDownPath, expectedUid, }); try { await fileSystem.rmdir(markerPath); } catch { throw fail("refuses changed local dashboard state marker"); } } if (finalizingMarkerPath) { const finalizingAnchor = await captureDirectoryAnchor({ fileSystem, path: finalizingMarkerPath, platform, lockDownPath, expectedUid, }); await assertDirectoryAnchors({ fileSystem, anchors: [homeAnchor, controlAnchor, finalizingAnchor], platform, lockDownPath, expectedUid, }); try { await fileSystem.rmdir(finalizingMarkerPath); } catch { throw fail("refuses changed local dashboard finalization state"); } } try { await fileSystem.rmdir(paths.controlRoot); } catch { throw fail("refuses changed local dashboard control directory"); } } async function publishControlState({ paths, publication, controlToken, browserToken, fileSystem, platform, lockDownPath, expectedUid, }) { await cleanupLegacyControlArtifacts({ paths, fileSystem, platform, lockDownPath, expectedUid, }); const existing = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if (existing.kind !== "absent") { if (existing.kind === "ready") { throw fail("refuses to replace existing local dashboard control state"); } await removeExactControlState(existing, { fileSystem, platform, lockDownPath, expectedUid, }); } const parentFingerprint = await verifyParentBoundary({ fileSystem, path: paths.parentPath, platform, lockDownPath, expectedUid, requirePrivateAcl: paths.requirePrivateParentAcl, }); const parentAnchor = Object.freeze({ kind: "parent", path: paths.parentPath, fingerprint: parentFingerprint, requirePrivateAcl: paths.requirePrivateParentAcl, }); const homeAnchor = await captureDirectoryAnchor({ fileSystem, path: paths.relmioHome, platform, lockDownPath, expectedUid, }); await createPrivateDirectory({ fileSystem, path: paths.controlRoot, platform, lockDownPath, expectedUid, anchors: [parentAnchor, homeAnchor], requireNew: true, }); const controlAnchor = await captureDirectoryAnchor({ fileSystem, path: paths.controlRoot, platform, lockDownPath, expectedUid, }); const publicationRaw = `${JSON.stringify(publication)}\n`; const descriptor = createControlStateDescriptor({ publicationRaw, controlToken, browserToken, instanceId: publication.instanceId, }); const publishingMarkerPath = join(paths.controlRoot, descriptor.publishingName); await createPrivateDirectory({ fileSystem, path: publishingMarkerPath, platform, lockDownPath, expectedUid, anchors: [parentAnchor, homeAnchor, controlAnchor], requireNew: true, }); const publishingAnchor = await captureDirectoryAnchor({ fileSystem, path: publishingMarkerPath, platform, lockDownPath, expectedUid, }); const publishingAnchors = [parentAnchor, homeAnchor, controlAnchor, publishingAnchor]; try { await writePrivateFile({ fileSystem, path: paths.controlKeyPath, raw: controlToken, platform, lockDownPath, expectedUid, maxBytes: 43, anchors: publishingAnchors, }); await writePrivateFile({ fileSystem, path: paths.browserKeyPath, raw: browserToken, platform, lockDownPath, expectedUid, maxBytes: 43, anchors: publishingAnchors, }); await writePrivateFile({ fileSystem, path: paths.publicationPath, raw: publicationRaw, platform, lockDownPath, expectedUid, maxBytes: MAX_PUBLICATION_BYTES, anchors: publishingAnchors, }); const completePublishing = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if ( completePublishing.kind !== "publishing" || !sameControlStateDescriptor(completePublishing.descriptor, descriptor) || digestContent(completePublishing.publicationRecord?.raw ?? "") !== descriptor.publicationDigest || digestContent(completePublishing.controlKeyRecord?.raw ?? "") !== descriptor.controlDigest || digestContent(completePublishing.browserKeyRecord?.raw ?? "") !== descriptor.browserDigest ) { throw fail("could not verify its complete dashboard control publication"); } const readyMarkerPath = join(paths.controlRoot, descriptor.readyName); await createPrivateDirectory({ fileSystem, path: readyMarkerPath, platform, lockDownPath, expectedUid, anchors: publishingAnchors, requireNew: true, }); const ready = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if (ready.kind !== "ready" || !sameControlStateDescriptor(ready.descriptor, descriptor)) { throw fail("could not verify its committed dashboard control publication"); } try { await fileSystem.rmdir(publishingMarkerPath); } catch { // The ready marker is the exclusive commit point. An empty publishing // phase left by interruption is harmless and is recognized on recovery. } return Object.freeze(ready); } catch (error) { try { const partial = await inspectControlLayout({ paths, fileSystem, platform, lockDownPath, expectedUid, }); if ( partial.kind !== "absent" && sameControlStateDescriptor(partial.descriptor, descriptor) ) { await removeExactControlState(partial, { fileSystem, platform, lockDownPath, expectedUid, }); } } catch { /* Preserve any changed canonical state. */ } throw error; } } function safeDaemonError() { return "Relmio dashboard daemon could not start."; } /** * Owns the control-plane lock for the life of one loopback dashboard daemon. * The caller keeps the returned completion promise alive until a signal or the * authenticated control callback requests shutdown. */ export async function runLocalDashboardDaemon({ env = process.env, homeDirectory = homedir(), fileSystem = defaultFileSystem, platform = process.platform, lockDownPath = lockDownLocalPath, getProcessIdentity = getLocalProcessIdentity, getUid = process.getuid?.bind(process), fetchImpl = fetch, requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS, randomBytes = createRandomBytes, randomUUID = createRandomUUID, now = Date.now, startServer, sendMessage = process.send?.bind(process), scheduleStop = (callback) => setImmediate(callback), signalTarget = process, } = {}) { validateAdapters({ fileSystem, lockDownPath, getProcessIdentity, fetchImpl, requestTimeoutMs, platform }); if ( typeof startServer !== "function" || typeof randomBytes !== "function" || typeof randomUUID !== "function" || typeof now !== "function" || (sendMessage !== undefined && typeof sendMessage !== "function") || typeof scheduleStop !== "function" || !signalTarget || typeof signalTarget.once !== "function" || typeof signalTarget.removeListener !== "function" ) throw new TypeError("The local dashboard daemon adapter is invalid."); const expectedUid = currentUid(platform, getUid); const paths = await ensureManagedControlRoot({ env, homeDirectory, fileSystem, platform, lockDownPath, expectedUid, getProcessIdentity, now, }); await ensurePrivateBrowserLaunchRoot({ paths, fileSystem, platform, lockDownPath, expectedUid, }); let releaseLock; let wizard; let ownedState; let stopPromise; let completionResolve; let completionReject; const completion = new Promise((resolveCompletion, rejectCompletion) => { completionResolve = resolveCompletion; completionReject = rejectCompletion; }); completion.catch(() => {}); const stop = () => { if (stopPromise) return stopPromise; stopPromise = (async () => { try { await wizard?.close(); } catch (error) { signalTarget.removeListener("SIGINT", onSignal); signalTarget.removeListener("SIGTERM", onSignal); completionReject(error); throw error; } try { if (ownedState) { await removeExactControlState(ownedState, { fileSystem, platform, lockDownPath, expectedUid, }); } } catch (error) { signalTarget.removeListener("SIGINT", onSignal); signalTarget.removeListener("SIGTERM", onSignal); completionReject(error); throw error; } try { await releaseLock?.(); } catch (error) { signalTarget.removeListener("SIGINT", onSignal); signalTarget.removeListener("SIGTERM", onSignal); completionReject(error); throw error; } signalTarget.removeListener("SIGINT", onSignal); signalTarget.removeListener("SIGTERM", onSignal); completionResolve(); })(); return stopPromise; }; const onSignal = () => { void stop().catch(() => {}); }; try { releaseLock = await acquireLocalIntegrationLifecycleLock({ fileSystem, getProcessIdentity, lockDownPath, lockPath: paths.lockPath, now, platform, label: "local dashboard lifetime lock", }); const prior = await inspectInternal({ env, homeDirectory, fileSystem, platform, lockDownPath, expectedUid, getProcessIdentity, fetchImpl, requestTimeoutMs, }); if ( prior.state === "dead" || prior.state === "pid-reused" || prior.state === "incomplete" || prior.state === "publishing" || prior.state === "retiring" ) { await removeExactControlState(prior, { fileSystem, platform, lockDownPath, expectedUid, }); } else if (prior.state !== "absent") { throw fail("refuses to replace an active or ambiguous dashboard daemon"); } const controlToken = createRoleToken(randomBytes, "control"); const browserToken = createRoleToken(randomBytes, "browser"); if (controlToken === browserToken) throw fail("could not create separated dashboard control keys"); const instanceId = randomUUID(); if (!INSTANCE_ID_PATTERN.test(instanceId)) throw fail("could not create a dashboard instance identity"); const publishedAtMs = now(); if (!Number.isSafeInteger(publishedAtMs) || publishedAtMs < 1) { throw fail("could not create a dashboard publication time"); } const selfIdentity = await getProcessIdentity(process.pid); if (!validIdentity(selfIdentity) || selfIdentity.state !== "active") { throw fail("could not verify the dashboard daemon process identity"); } const onControlStop = () => { scheduleStop(() => { void stop().catch(() => {}); }); return Object.freeze({ stopping: true, instanceId }); }; wizard = await startServer({ sessionToken: browserToken, controlToken, controlInstanceId: instanceId, onControlStop, browserHandoffRoot: paths.browserLaunchRoot, }); const publication = validatePublication({ schemaVersion: PUBLICATION_SCHEMA_VERSION, kind: CONTROL_KIND, protocolVersion: CONTROL_PROTOCOL_VERSION, packageVersion: CURRENT_PACKAGE_VERSION, pid: process.pid, processStartIdentity: selfIdentity.startIdentity, instanceId, origin: wizard?.origin, publishedAtMs, }); ownedState = await publishControlState({ paths, publication, controlToken, browserToken, fileSystem, platform, lockDownPath, expectedUid, }); signalTarget.once("SIGINT", onSignal); signalTarget.once("SIGTERM", onSignal); sendMessage?.(Object.freeze({ type: "ready" })); return Object.freeze({ publication: safeResult("healthy", publication), stop, completion, }); } catch (error) { try { await wizard?.close(); } catch { /* Preserve the startup failure. */ } try { if (ownedState) { await removeExactControlState(ownedState, { fileSystem, platform, lockDownPath, expectedUid, }); } } catch { /* Never remove changed state during failed startup cleanup. */ } try { await releaseLock?.(); } catch { /* Preserve the startup failure. */ } sendMessage?.(Object.freeze({ type: "error", message: safeDaemonError() })); completionReject(error); throw error; } } function privateDaemonEnvironment(environment) { if (!environment || typeof environment !== "object" || Array.isArray(environment)) { throw new TypeError("The local dashboard daemon environment is invalid."); } const selected = {}; for (const [name, value] of Object.entries(environment)) { if (typeof value !== "string") continue; if (!DAEMON_ENVIRONMENT_NAMES.has(name) && !LOCALE_ENVIRONMENT_NAME.test(name)) continue; if ( SESSION_TOKEN_PATTERN.test(value) && (CONTROL_TOKEN_PATTERN.test(value) || BROWSER_TOKEN_PATTERN.test(value)) ) { throw new Error("Relmio refuses to pass a dashboard key through the daemon environment."); } if (/\0|\r|\n/u.test(value) || Buffer.byteLength(value) > 32 * 1024) { throw new TypeError("The local dashboard daemon environment is invalid."); } selected[name] = value; } return selected; } function validateExecutablePath(value) { return typeof value === "string" && isAbsolute(value) && !/[\0\r\n]/u.test(value); } /** Spawn the package CLI in its private daemon mode and await IPC readiness. */ export function spawnLocalDashboardDaemon({ spawnProcess = spawn, execPath = process.execPath, cliPath = DEFAULT_CLI_PATH, environment = process.env, startupTimeoutMs = DEFAULT_STARTUP_TIMEOUT_MS, } = {}) { if ( typeof spawnProcess !== "function" || !validateExecutablePath(execPath) || !validateExecutablePath(cliPath) || !Number.isSafeInteger(startupTimeoutMs) || startupTimeoutMs < 1 || startupTimeoutMs > 60_000 ) { throw new TypeError("The local dashboard daemon spawn adapter is invalid."); } const childEnvironment = privateDaemonEnvironment(environment); return new Promise((resolveReady, rejectReady) => { let child; let settled = false; let timer; const settle = (error) => { if (settled) return; settled = true; clearTimeout(timer); child?.removeListener?.("message", onMessage); child?.removeListener?.("error", onError); child?.removeListener?.("exit", onExit); child?.removeListener?.("disconnect", onDisconnect); try { if (child?.connected) child.disconnect(); } catch { /* Readiness remains bounded. */ } try { child?.unref?.(); } catch { /* Detachment is already requested at spawn. */ } if (error) rejectReady(error); else resolveReady(Object.freeze({ state: "ready" })); }; const onError = () => settle(fail("dashboard daemon could not start")); const onExit = () => settle(fail("dashboard daemon exited before readiness")); const onDisconnect = () => settle(fail("dashboard daemon disconnected before readiness")); const onMessage = (message) => { if (exactKeys(message, ["type"]) && message.type === "ready") { settle(); return; } if ( exactKeys(message, ["message", "type"]) && message.type === "error" && message.message === safeDaemonError() ) { settle(new Error(message.message)); return; } settle(fail("received an invalid readiness message from the dashboard daemon")); }; try { child = spawnProcess(execPath, [cliPath, PRIVATE_DAEMON_COMMAND], { cwd: dirname(execPath), detached: true, shell: false, windowsHide: true, stdio: ["ignore", "ignore", "ignore", "ipc"], env: childEnvironment, }); } catch { rejectReady(fail("dashboard daemon could not start")); return; } if ( !child || typeof child.once !== "function" || typeof child.removeListener !== "function" || typeof child.disconnect !== "function" || typeof child.unref !== "function" ) { settle(fail("dashboard daemon could not start")); return; } child.once("message", onMessage); child.once("error", onError); child.once("exit", onExit); child.once("disconnect", onDisconnect); timer = setTimeout( () => settle(fail("dashboard daemon readiness timed out")), startupTimeoutMs, ); }); } function runtimeOptions(options = {}) { const resolved = { env: options.env ?? process.env, homeDirectory: options.homeDirectory ?? homedir(), fileSystem: options.fileSystem ?? defaultFileSystem, platform: options.platform ?? process.platform, lockDownPath: options.lockDownPath ?? lockDownLocalPath, getProcessIdentity: options.getProcessIdentity ?? getLocalProcessIdentity, fetchImpl: options.fetchImpl ?? fetch, requestTimeoutMs: options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS, getUid: options.getUid ?? process.getuid?.bind(process), now: options.now ?? Date.now, }; validateAdapters(resolved); if (typeof resolved.now !== "function") { throw new TypeError("The local dashboard control adapter is invalid."); } resolved.expectedUid = currentUid(resolved.platform, resolved.getUid); return resolved; } /** Ensure the browser handoff parent exists beneath Relmio's verified private root. */ export async function ensureLocalDashboardBrowserLaunchRoot(options = {}) { const runtime = runtimeOptions(options); const paths = await ensureManagedControlRoot(runtime); return await ensurePrivateBrowserLaunchRoot({ paths, ...runtime }); } async function inspectRuntime(options) { return inspectInternal({ env: options.env, homeDirectory: options.homeDirectory, fileSystem: options.fileSystem, platform: options.platform, lockDownPath: options.lockDownPath, expectedUid: options.expectedUid, getProcessIdentity: options.getProcessIdentity, fetchImpl: options.fetchImpl, requestTimeoutMs: options.requestTimeoutMs, }); } async function recoverStaleRuntime(options) { let releaseLock; let result; let failure; try { const paths = await resolveControlPaths(options); releaseLock = await acquireLocalIntegrationLifecycleLock({ fileSystem: options.fileSystem, getProcessIdentity: options.getProcessIdentity, lockDownPath: options.lockDownPath, lockPath: paths.lockPath, now: options.now, platform: options.platform, label: "local dashboard lifetime lock", }); const current = await inspectRuntime(options); if ( current.state === "dead" || current.state === "pid-reused" || current.state === "incomplete" || current.state === "publishing" || current.state === "retiring" ) { await removeExactControlState(current, { fileSystem: options.fileSystem, platform: options.platform, lockDownPath: options.lockDownPath, expectedUid: options.expectedUid, }); result = "recovered"; } else if (current.state === "absent") { result = "absent"; } else { throw fail("refuses to replace active, unresponsive, or ambiguous dashboard state"); } } catch (error) { failure = error; } try { await releaseLock?.(); } catch (error) { failure ??= error; } if (failure) throw failure; return result; } /** Start the persistent dashboard, returning only non-secret status metadata. */ export async function startLocalDashboardControlPlane(options = {}) { const runtime = runtimeOptions(options); const spawnDaemon = options.spawnDaemon ?? spawnLocalDashboardDaemon; if (typeof spawnDaemon !== "function") { throw new TypeError("The local dashboard control adapter is invalid."); } let current = await inspectRuntime(runtime); if (current.state === "healthy") return safeResult("existing", current.publication); if (current.state === "version-mismatch") { throw fail("found a dashboard from another Relmio version; run relmio stop, then retry"); } if (current.state === "ambiguous" || current.state === "unresponsive") { throw fail(`refuses ${current.state} local dashboard state`); } if ( current.state === "dead" || current.state === "pid-reused" || current.state === "incomplete" || current.state === "publishing" || current.state === "retiring" ) { await recoverStaleRuntime(runtime); } const spawnOptions = { environment: runtime.env }; for (const name of ["execPath", "cliPath", "spawnProcess", "startupTimeoutMs"]) { if (options[name] !== undefined) spawnOptions[name] = options[name]; } try { await spawnDaemon(spawnOptions); } catch (error) { current = await inspectRuntime(runtime); if (current.state === "healthy") return safeResult("existing", current.publication); throw error; } current = await inspectRuntime(runtime); if (current.state !== "healthy") { throw fail("could not verify the dashboard daemon after readiness"); } return safeResult("started", current.publication); } /** Re-read the protected browser capability immediately before opening it. */ export async function readLocalDashboardBrowserUrl(options = {}) { const runtime = runtimeOptions(options); const route = options.route ?? "/local"; if (!["/", "/assistant", "/local", "/supergrok-vps", "/claude-vps", "/local-model-vps"].includes(route)) { throw new TypeError("Relmio dashboard route is invalid."); } const current = await inspectRuntime(runtime); if (current.state !== "healthy") { throw fail("cannot open a dashboard that is not healthy"); } let response; try { response = await fetchJson( runtime.fetchImpl, `${current.publication.origin}${BROWSER_PREPARE_PATH}`, { method: "POST", headers: { "Content-Type": "application/json", "Origin": current.publication.origin, "X-Setup-Token": current.browserKeyRecord.raw, }, body: JSON.stringify({ route }), }, runtime.requestTimeoutMs, 201, ); } catch { throw fail("could not prepare a private dashboard browser launch"); } if ( !exactKeys(response, ["launchUrl"]) || !isPrivateBrowserLaunchUrl(response.launchUrl) ) { throw fail("received an invalid private dashboard browser launch"); } return response.launchUrl; } function exactStopResponse(value, publication) { return exactKeys(value, ["instanceId", "stopping"]) && value.stopping === true && value.instanceId === publication.instanceId; } function defaultSleep(milliseconds) { return new Promise((resolveSleep) => { setTimeout(resolveSleep, milliseconds); }); } /** Stop only the exact authenticated daemon; never fall back to a PID kill. */ export async function stopLocalDashboardControlPlane(options = {}) { const runtime = runtimeOptions(options); const sleep = options.sleep ?? defaultSleep; const stopChecks = options.stopChecks ?? 100; const stopPollMs = options.stopPollMs ?? 50; if ( typeof sleep !== "function" || !Number.isSafeInteger(stopChecks) || stopChecks < 1 || stopChecks > 1_000 || !Number.isSafeInteger(stopPollMs) || stopPollMs < 0 || stopPollMs > 1_000 ) throw new TypeError("The local dashboard stop adapter is invalid."); let current = await inspectRuntime(runtime); if (current.state === "absent") return Object.freeze({ state: "absent" }); if ( current.state === "dead" || current.state === "pid-reused" || current.state === "incomplete" || current.state === "publishing" || current.state === "retiring" ) { await recoverStaleRuntime(runtime); return Object.freeze({ state: "stopped" }); } if (current.state !== "healthy" && current.state !== "version-mismatch") { throw fail(`refuses to stop ${current.state} local dashboard state`); } const targetInstanceId = current.publication.instanceId; let response; try { response = await fetchStopResponse( runtime.fetchImpl, `${current.publication.origin}${STOP_PATH}`, { method: "POST", headers: { "X-Relmio-Control": current.controlKeyRecord.raw }, }, runtime.requestTimeoutMs, ); } catch { throw fail("could not authenticate a dashboard stop request"); } if (response.state === "busy") { throw fail("dashboard is busy; wait for active work to finish, then retry"); } if (response.state !== "accepted" || !exactStopResponse(response.value, current.publication)) { throw fail("refuses an invalid dashboard stop response"); } for (let check = 0; check < stopChecks; check += 1) { try { current = await inspectRuntime(runtime); } catch (error) { // This poll holds no lock while the acknowledged daemon moves its files // into retirement, so one pass can list an entry that is gone by the time // it is read. Reread; state that stays inconsistent is still refused. if (check + 1 >= stopChecks) throw error; await sleep(stopPollMs); continue; } if (current.state === "absent") return Object.freeze({ state: "stopped" }); if (current.state === "retiring" || current.state === "incomplete") { const retiringInstanceId = current.descriptor?.instanceId; if (retiringInstanceId && retiringInstanceId !== targetInstanceId) { throw fail("refuses to follow a replaced dashboard during stop"); } if (check + 1 < stopChecks) await sleep(stopPollMs); continue; } if (current.instanceId !== targetInstanceId) { throw fail("refuses to follow a replaced dashboard during stop"); } if (current.state === "dead" || current.state === "pid-reused") { await recoverStaleRuntime(runtime); return Object.freeze({ state: "stopped" }); } if (current.state === "ambiguous") { throw fail("could not verify dashboard identity during stop"); } if (check + 1 < stopChecks) await sleep(stopPollMs); } throw fail("dashboard stop timed out while the exact process remained active"); } export const LOCAL_DASHBOARD_CONTROL_PATHS = Object.freeze({ browserPrepare: BROWSER_PREPARE_PATH, health: HEALTH_PATH, stop: STOP_PATH, }); export const LOCAL_DASHBOARD_DAEMON_COMMAND = PRIVATE_DAEMON_COMMAND;