@saptools/cf-debugger 0.1.15 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/regions.ts","../src/cloud-foundry/execute.ts","../src/cloud-foundry/commands.ts","../src/cloud-foundry/node-process.ts","../src/cloud-foundry/ssh.ts","../src/session-state/store.ts","../src/debug-session/constants.ts","../src/debug-session/process-identity.ts","../src/lock.ts","../src/paths.ts","../src/session-state/decoder.ts","../src/session-state/health.ts","../src/network/ports.ts","../src/session-state/stop-intent.ts","../src/cli-errors.ts","../src/debug-session/lifecycle.ts","../src/debug-session/processes.ts","../src/debug-session/session-home.ts","../src/debug-session/startup-deadline.ts","../src/debug-session/start.ts","../src/debug-session/orphans.ts","../src/debug-session/startup-cancellation.ts","../src/debug-session/startup-remote.ts","../src/debug-session/startup-tunnel.ts","../src/debug-session/doctor.ts","../src/debug-session/sessions.ts"],"sourcesContent":["export interface SessionKey {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n /** Cloud Foundry process name (for example `web`), not an operating-system process. */\n readonly process?: string;\n readonly instance?: number;\n readonly apiEndpoint?: string;\n readonly nodePid?: number;\n}\n\nexport interface ResolvedSessionKey extends SessionKey {\n readonly process: string;\n readonly instance: number;\n}\n\nexport type SessionStatus =\n | \"starting\"\n | \"logging-in\"\n | \"targeting\"\n | \"ssh-enabling\"\n | \"ssh-restarting\"\n | \"signaling\"\n | \"tunneling\"\n | \"ready\"\n | \"stopping\"\n | \"stopped\"\n | \"error\";\n\nexport interface ActiveSession extends SessionKey {\n readonly sessionId: string;\n /** Compatibility alias for the currently active controller or tunnel PID. */\n readonly pid: number;\n readonly controllerPid?: number;\n /** Optional OS process birth token; absent records retain PID-only compatibility. */\n readonly controllerProcessIdentity?: string;\n readonly tunnelPid?: number;\n /** Optional OS process birth token; absent records retain PID-only compatibility. */\n readonly tunnelProcessIdentity?: string;\n readonly hostname: string;\n readonly localPort: number;\n readonly remotePort: number;\n readonly apiEndpoint: string;\n readonly cfHomeDir: string;\n readonly startedAt: string;\n readonly status: SessionStatus;\n readonly remoteNodePid?: number;\n /** Startup budget used for stale-session evaluation; absent records use the supported maximum. */\n readonly startupTimeoutMs?: number;\n readonly stopRequestedAt?: string;\n readonly message?: string;\n}\n\nexport interface StartDebuggerOptions extends SessionKey {\n readonly email?: string;\n readonly password?: string;\n readonly preferredPort?: number;\n readonly remotePort?: number;\n readonly tunnelReadyTimeoutMs?: number;\n readonly startupTimeoutMs?: number;\n /** Set true to permit app-level SSH enablement and an app restart. Defaults to false. */\n readonly allowSshEnableRestart?: boolean;\n readonly verbose?: boolean;\n readonly onStatus?: (status: SessionStatus, message?: string) => void;\n readonly signal?: AbortSignal;\n}\n\nexport interface DebuggerHandle {\n readonly session: ActiveSession;\n dispose(): Promise<void>;\n waitForExit(): Promise<number | null>;\n}\n\nexport interface StateFile {\n readonly version: \"2\";\n readonly sessions: readonly ActiveSession[];\n}\n\nexport class CfDebuggerError extends Error {\n public readonly code: string;\n public readonly stderr?: string;\n\n public constructor(code: string, message: string, stderr?: string) {\n super(message);\n this.name = \"CfDebuggerError\";\n this.code = code;\n if (stderr !== undefined) {\n this.stderr = stderr;\n }\n }\n}\n","import { CfDebuggerError } from \"./types.js\";\n\nexport interface RegionInfo {\n readonly key: string;\n readonly apiEndpoint: string;\n}\n\nconst REGION_KEY_PATTERN = /^[a-z]{2}\\d{2}(?:-\\d{3})?$/;\n\nconst REGION_API_ENDPOINTS: Readonly<Record<string, string>> = {\n ae01: \"https://api.cf.ae01.hana.ondemand.com\",\n ap01: \"https://api.cf.ap01.hana.ondemand.com\",\n ap10: \"https://api.cf.ap10.hana.ondemand.com\",\n ap11: \"https://api.cf.ap11.hana.ondemand.com\",\n ap12: \"https://api.cf.ap12.hana.ondemand.com\",\n ap20: \"https://api.cf.ap20.hana.ondemand.com\",\n ap21: \"https://api.cf.ap21.hana.ondemand.com\",\n ap30: \"https://api.cf.ap30.hana.ondemand.com\",\n ap31: \"https://api.cf.ap31.hana.ondemand.com\",\n br10: \"https://api.cf.br10.hana.ondemand.com\",\n br20: \"https://api.cf.br20.hana.ondemand.com\",\n br30: \"https://api.cf.br30.hana.ondemand.com\",\n ca10: \"https://api.cf.ca10.hana.ondemand.com\",\n ca20: \"https://api.cf.ca20.hana.ondemand.com\",\n ch20: \"https://api.cf.ch20.hana.ondemand.com\",\n cn20: \"https://api.cf.cn20.platform.sapcloud.cn\",\n cn40: \"https://api.cf.cn40.platform.sapcloud.cn\",\n eu01: \"https://api.cf.eu01.hana.ondemand.com\",\n eu02: \"https://api.cf.eu02.hana.ondemand.com\",\n eu10: \"https://api.cf.eu10.hana.ondemand.com\",\n \"eu10-002\": \"https://api.cf.eu10-002.hana.ondemand.com\",\n \"eu10-003\": \"https://api.cf.eu10-003.hana.ondemand.com\",\n \"eu10-004\": \"https://api.cf.eu10-004.hana.ondemand.com\",\n \"eu10-005\": \"https://api.cf.eu10-005.hana.ondemand.com\",\n \"eu10-006\": \"https://api.cf.eu10-006.hana.ondemand.com\",\n eu11: \"https://api.cf.eu11.hana.ondemand.com\",\n eu12: \"https://api.cf.eu12.hana.ondemand.com\",\n eu13: \"https://api.cf.eu13.hana.ondemand.com\",\n eu20: \"https://api.cf.eu20.hana.ondemand.com\",\n \"eu20-001\": \"https://api.cf.eu20-001.hana.ondemand.com\",\n \"eu20-002\": \"https://api.cf.eu20-002.hana.ondemand.com\",\n eu21: \"https://api.cf.eu21.hana.ondemand.com\",\n eu22: \"https://api.cf.eu22.hana.ondemand.com\",\n eu30: \"https://api.cf.eu30.hana.ondemand.com\",\n eu31: \"https://api.cf.eu31.hana.ondemand.com\",\n il30: \"https://api.cf.il30.hana.ondemand.com\",\n in30: \"https://api.cf.in30.hana.ondemand.com\",\n jp01: \"https://api.cf.jp01.hana.ondemand.com\",\n jp10: \"https://api.cf.jp10.hana.ondemand.com\",\n jp20: \"https://api.cf.jp20.hana.ondemand.com\",\n jp30: \"https://api.cf.jp30.hana.ondemand.com\",\n jp31: \"https://api.cf.jp31.hana.ondemand.com\",\n kr30: \"https://api.cf.kr30.hana.ondemand.com\",\n sa30: \"https://api.cf.sa30.hana.ondemand.com\",\n sa31: \"https://api.cf.sa31.hana.ondemand.com\",\n uk20: \"https://api.cf.uk20.hana.ondemand.com\",\n us01: \"https://api.cf.us01.hana.ondemand.com\",\n us02: \"https://api.cf.us02.hana.ondemand.com\",\n us10: \"https://api.cf.us10.hana.ondemand.com\",\n \"us10-001\": \"https://api.cf.us10-001.hana.ondemand.com\",\n \"us10-002\": \"https://api.cf.us10-002.hana.ondemand.com\",\n \"us10-003\": \"https://api.cf.us10-003.hana.ondemand.com\",\n us11: \"https://api.cf.us11.hana.ondemand.com\",\n us20: \"https://api.cf.us20.hana.ondemand.com\",\n us21: \"https://api.cf.us21.hana.ondemand.com\",\n \"us21-001\": \"https://api.cf.us21-001.hana.ondemand.com\",\n us22: \"https://api.cf.us22.hana.ondemand.com\",\n us30: \"https://api.cf.us30.hana.ondemand.com\",\n us31: \"https://api.cf.us31.hana.ondemand.com\",\n us32: \"https://api.cf.us32.hana.ondemand.com\",\n};\n\nfunction synthesizeApiEndpoint(regionKey: string): string {\n const domain = regionKey.startsWith(\"cn\")\n ? \"platform.sapcloud.cn\"\n : \"hana.ondemand.com\";\n return `https://api.cf.${regionKey}.${domain}`;\n}\n\nexport function resolveApiEndpoint(\n regionKey: string,\n override?: string,\n onWarning?: (warning: string) => void,\n): string {\n if (override !== undefined && override !== \"\") {\n return override;\n }\n if (!REGION_KEY_PATTERN.test(regionKey)) {\n throw new CfDebuggerError(\n \"UNKNOWN_REGION\",\n `Unknown region key: ${JSON.stringify(regionKey)}. Expected a key matching aa00 or aa00-000, or pass --api-endpoint <url>.`,\n );\n }\n const endpoint = Object.hasOwn(REGION_API_ENDPOINTS, regionKey)\n ? REGION_API_ENDPOINTS[regionKey]\n : undefined;\n if (endpoint !== undefined) {\n return endpoint;\n }\n const synthesized = synthesizeApiEndpoint(regionKey);\n onWarning?.(\n `Region key ${regionKey} is not in the curated region list; using synthesized API endpoint ${synthesized}. Verify it or pass --api-endpoint <url>.`,\n );\n return synthesized;\n}\n\nexport function listKnownRegionKeys(): readonly string[] {\n return Object.keys(REGION_API_ENDPOINTS);\n}\n","import { execFile } from \"node:child_process\";\nimport type {\n ChildProcess,\n ExecFileException,\n} from \"node:child_process\";\nimport nodeProcess from \"node:process\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nconst MAX_BUFFER = 16 * 1024 * 1024;\nexport const DEFAULT_CF_COMMAND_TIMEOUT_MS = 60_000;\nexport const DEFAULT_CF_OPERATION_TIMEOUT_MS = 300_000;\nconst REDACTED_ARG = \"<redacted>\";\nconst MAX_RETRY_DELAY_MS = 10_000;\n\nexport interface CfRetryStatus {\n readonly attempt: number;\n readonly command: string;\n readonly delayMs: number;\n readonly remainingMs: number;\n}\n\nexport interface CfExecContext {\n readonly cfHome: string;\n readonly command?: string;\n readonly signal?: AbortSignal;\n readonly deadlineAt?: number;\n readonly startupTimeoutMs?: number;\n readonly phase?: string;\n readonly onRetry?: (status: CfRetryStatus) => void;\n readonly sensitiveValues?: readonly string[];\n readonly onTunnelOutput?: (stream: \"stderr\" | \"stdout\", text: string) => void;\n}\n\nexport interface CfRunOptions {\n readonly env?: NodeJS.ProcessEnv;\n readonly sensitiveValues?: readonly string[];\n /** Maximum duration of one child execution. */\n readonly timeoutMs?: number;\n /** Overall budget when no startup deadline is supplied. */\n readonly retryBudgetMs?: number;\n}\n\ninterface CfFailureDetails {\n readonly code: string | undefined;\n readonly killed: boolean;\n readonly message: string;\n readonly stderr: string | undefined;\n}\n\ninterface ResolvedCfRunOptions {\n readonly env: NodeJS.ProcessEnv | undefined;\n readonly redactionValues: readonly string[];\n readonly attemptTimeoutMs: number;\n readonly deadlineAt: number;\n}\n\nexport interface BoundedExecFileOptions {\n readonly env: NodeJS.ProcessEnv;\n readonly maxBuffer?: number;\n readonly signal?: AbortSignal;\n readonly timeoutMs: number;\n}\n\nexport function buildEnv(cfHome: string): NodeJS.ProcessEnv {\n return { ...nodeProcess.env, CF_COLOR: \"false\", CF_HOME: cfHome };\n}\n\nexport function resolveBin(context: CfExecContext): string {\n return context.command ?? nodeProcess.env[\"CF_DEBUGGER_CF_BIN\"] ?? \"cf\";\n}\n\nexport function redactSensitiveText(text: string, values: readonly string[]): string {\n return normalizeSensitiveValues(values)\n .reduce((current, value) => current.split(value).join(REDACTED_ARG), text);\n}\n\nexport function normalizeSensitiveValues(values: readonly string[]): readonly string[] {\n return [...new Set(values.filter((value) => value.length > 0))]\n .sort((left, right) => right.length - left.length);\n}\n\nfunction abortError(context: CfExecContext): CfDebuggerError {\n if (context.deadlineAt !== undefined && Date.now() >= context.deadlineAt) {\n const timeoutMs = context.startupTimeoutMs;\n const duration = timeoutMs === undefined ? \"configured\" : `${(timeoutMs / 1000).toString()}s`;\n return new CfDebuggerError(\n \"STARTUP_TIMEOUT\",\n `Debugger startup exceeded its ${duration} deadline during ${context.phase ?? \"a CF command\"}.`,\n );\n }\n return new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n}\n\nfunction waitForRetry(\n delayMs: number,\n context: CfExecContext,\n): Promise<void> {\n if (context.signal?.aborted) {\n return Promise.reject(abortError(context));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(abortError(context));\n };\n const timer = setTimeout(() => {\n context.signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, delayMs);\n context.signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction formatArgsForError(\n args: readonly string[],\n sensitiveValues: readonly string[],\n): string {\n // Authentication secrets are intentionally supplied only through the child environment.\n return redactSensitiveText(args.join(\" \"), sensitiveValues);\n}\n\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction readFailureDetails(error: unknown): CfFailureDetails {\n const object = typeof error === \"object\" && error !== null ? error : undefined;\n const field = (key: string): unknown => object === undefined ? undefined : Reflect.get(object, key);\n return {\n code: optionalString(field(\"code\")),\n killed: field(\"killed\") === true,\n message: error instanceof Error ? error.message : String(error),\n stderr: optionalString(field(\"stderr\")),\n };\n}\n\nfunction hasTransientDiagnostic(error: CfFailureDetails): boolean {\n // CF CLI transport failures sometimes have no errno. Inspect stderr only:\n // stdout can contain app names or payloads that merely mention these phrases.\n const diagnostic = error.stderr?.toLowerCase() ?? \"\";\n const phrases = [\n \"error performing request\",\n \"connection reset by peer\",\n \"service unavailable\",\n \"bad gateway\",\n \"gateway timeout\",\n \"dial tcp\",\n \"i/o timeout\",\n ];\n return phrases.some((phrase) => diagnostic.includes(phrase));\n}\n\nfunction isCredentialRejection(\n args: readonly string[],\n error: CfFailureDetails,\n): boolean {\n if (args[0] !== \"auth\") {\n return false;\n }\n const diagnostic = `${error.stderr ?? \"\"} ${error.message}`.toLowerCase();\n const phrases = [\n \"authentication failed\",\n \"credentials were rejected\",\n \"invalid credentials\",\n \"invalid email\",\n \"invalid password\",\n \"invalid username\",\n \"incorrect password\",\n \"not authorized\",\n \"unauthorized\",\n ];\n return phrases.some((phrase) => diagnostic.includes(phrase)) ||\n /\\b(?:401|403)\\b/.test(diagnostic);\n}\n\nfunction isTransientNetworkError(\n error: CfFailureDetails,\n attemptTimedOut: boolean,\n): boolean {\n if (attemptTimedOut) {\n // This is tied to our own execFile timeout, not arbitrary output mentioning a timeout.\n return true;\n }\n const networkCodes = [\n \"ETIMEDOUT\",\n \"ECONNRESET\",\n \"ENOTFOUND\",\n \"ECONNREFUSED\",\n \"EHOSTUNREACH\",\n \"ENETUNREACH\",\n ];\n return (error.code !== undefined && networkCodes.includes(error.code)) ||\n hasTransientDiagnostic(error);\n}\n\nfunction requirePositiveMilliseconds(value: number, name: string): number {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n `${name} must be a positive safe integer.`,\n );\n }\n return value;\n}\n\nfunction resolveRunOptions(\n context: CfExecContext,\n input: number | CfRunOptions,\n): ResolvedCfRunOptions {\n const options = typeof input === \"number\" ? { timeoutMs: input } : input;\n const retryBudgetMs = requirePositiveMilliseconds(\n options.retryBudgetMs ?? DEFAULT_CF_OPERATION_TIMEOUT_MS,\n \"retryBudgetMs\",\n );\n const attemptTimeoutMs = requirePositiveMilliseconds(\n options.timeoutMs ?? DEFAULT_CF_COMMAND_TIMEOUT_MS,\n \"timeoutMs\",\n );\n const deadlineAt = context.deadlineAt ?? Date.now() + retryBudgetMs;\n if (!Number.isSafeInteger(deadlineAt) || deadlineAt <= 0) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"deadlineAt must be a positive safe integer timestamp.\",\n );\n }\n return {\n env: options.env,\n redactionValues: normalizeSensitiveValues([\n ...(context.sensitiveValues ?? []),\n ...(options.sensitiveValues ?? []),\n ]),\n attemptTimeoutMs,\n deadlineAt,\n };\n}\n\nasync function executeCfAttempt(\n args: readonly string[],\n context: CfExecContext,\n options: ResolvedCfRunOptions,\n timeoutMs: number,\n): Promise<string> {\n const result = await executeFileBounded(resolveBin(context), args, {\n env: {\n ...buildEnv(context.cfHome),\n ...options.env,\n CF_COLOR: \"false\",\n CF_HOME: context.cfHome,\n },\n maxBuffer: MAX_BUFFER,\n timeoutMs,\n ...(context.signal === undefined ? {} : { signal: context.signal }),\n });\n return result.stdout;\n}\n\nfunction signalCfChild(child: ChildProcess, signal: NodeJS.Signals): void {\n try {\n child.kill(signal);\n } catch {\n // The command already exited.\n }\n}\n\nexport async function executeFileBounded(\n command: string,\n args: readonly string[],\n options: BoundedExecFileOptions,\n): Promise<{ readonly stderr: string; readonly stdout: string }> {\n return await new Promise((resolve, reject) => {\n let settled = false;\n const cleanup = (): void => {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onAbort);\n };\n const rejectOnce = (error: Error): void => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n reject(error);\n };\n const child = execFile(command, [...args], {\n env: options.env,\n maxBuffer: options.maxBuffer ?? MAX_BUFFER,\n encoding: \"utf8\",\n }, (error: ExecFileException | null, stdout: string, stderr: string) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n if (error === null && options.signal?.aborted !== true) {\n resolve({ stderr, stdout });\n return;\n }\n const failure = error ?? new Error(\"Command was aborted.\");\n Reflect.set(failure, \"stderr\", stderr);\n reject(failure);\n });\n const terminateAndReject = (code: \"ABORT_ERR\" | \"ETIMEDOUT\", message: string): void => {\n if (settled) {\n return;\n }\n signalCfChild(child, \"SIGKILL\");\n child.stdout?.destroy();\n child.stderr?.destroy();\n const failure = new Error(message);\n Reflect.set(failure, \"code\", code);\n Reflect.set(failure, \"killed\", true);\n Reflect.set(failure, \"stderr\", \"\");\n rejectOnce(failure);\n };\n const onAbort = (): void => {\n terminateAndReject(\"ABORT_ERR\", \"Command was aborted.\");\n };\n const timer = setTimeout(() => {\n terminateAndReject(\"ETIMEDOUT\", \"Command exceeded its execution deadline.\");\n }, options.timeoutMs);\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (options.signal?.aborted) {\n onAbort();\n }\n });\n}\n\nfunction retryDelayMs(attempt: number): number {\n return Math.min(1000 * (2 ** Math.min(attempt - 1, 10)), MAX_RETRY_DELAY_MS);\n}\n\nfunction createCfCliError(\n args: readonly string[],\n failure: CfFailureDetails,\n redactionValues: readonly string[],\n): CfDebuggerError {\n const stderr = redactSensitiveText(failure.stderr?.trim() ?? \"\", redactionValues);\n const fallback = redactSensitiveText(failure.message, redactionValues);\n const detail = stderr.length > 0 ? stderr : fallback;\n return new CfDebuggerError(\n \"CF_CLI_FAILED\",\n `cf ${formatArgsForError(args, redactionValues)} failed: ${detail}`,\n stderr,\n );\n}\n\nfunction timeoutError(\n context: CfExecContext,\n args: readonly string[],\n redactionValues: readonly string[],\n): CfDebuggerError {\n if (context.deadlineAt !== undefined) {\n const timeoutMs = context.startupTimeoutMs;\n const duration = timeoutMs === undefined ? \"configured\" : `${(timeoutMs / 1000).toString()}s`;\n return new CfDebuggerError(\n \"STARTUP_TIMEOUT\",\n `Debugger startup could not complete within its ${duration} deadline during ` +\n `${context.phase ?? \"a CF command\"}.`,\n );\n }\n return new CfDebuggerError(\n \"CF_CLI_TIMEOUT\",\n `cf ${formatArgsForError(args, redactionValues)} exceeded its overall retry budget.`,\n );\n}\n\nfunction reportRetry(\n context: CfExecContext,\n args: readonly string[],\n attempt: number,\n delayMs: number,\n remainingMs: number,\n redactionValues: readonly string[],\n): void {\n context.onRetry?.({\n attempt,\n command: `cf ${formatArgsForError(args, redactionValues)}`,\n delayMs,\n remainingMs,\n });\n}\n\nexport async function runCf(\n args: readonly string[],\n context: CfExecContext,\n input: number | CfRunOptions = {},\n): Promise<string> {\n if (context.signal?.aborted) {\n throw abortError(context);\n }\n const options = resolveRunOptions(context, input);\n let attempt = 0;\n\n for (;;) {\n const remainingMs = options.deadlineAt - Date.now();\n if (remainingMs <= 0) {\n throw timeoutError(context, args, options.redactionValues);\n }\n attempt += 1;\n const attemptTimeoutMs = Math.max(1, Math.min(options.attemptTimeoutMs, remainingMs));\n const startedAt = Date.now();\n try {\n return await executeCfAttempt(args, context, options, attemptTimeoutMs);\n } catch (error: unknown) {\n const failure = readFailureDetails(error);\n if (context.signal?.aborted || failure.code === \"ABORT_ERR\") {\n throw abortError(context);\n }\n const elapsedMs = Date.now() - startedAt;\n const attemptTimedOut = failure.killed &&\n elapsedMs + 100 >= attemptTimeoutMs;\n if (\n isCredentialRejection(args, failure) ||\n !isTransientNetworkError(failure, attemptTimedOut)\n ) {\n throw createCfCliError(args, failure, options.redactionValues);\n }\n const delayMs = retryDelayMs(attempt);\n const afterFailureMs = options.deadlineAt - Date.now();\n if (afterFailureMs <= delayMs) {\n throw timeoutError(context, args, options.redactionValues);\n }\n reportRetry(\n context,\n args,\n attempt,\n delayMs,\n afterFailureMs,\n options.redactionValues,\n );\n await waitForRetry(delayMs, context);\n }\n }\n}\n","import { listKnownRegionKeys, resolveApiEndpoint } from \"../regions.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport {\n type CfExecContext,\n executeFileBounded,\n runCf,\n} from \"./execute.js\";\n\nconst CURRENT_TARGET_TIMEOUT_MS = 30_000;\n\nfunction rethrowControlFlowError(error: unknown): void {\n if (\n error instanceof CfDebuggerError &&\n (error.code === \"ABORTED\" || error.code === \"STARTUP_TIMEOUT\")\n ) {\n throw error;\n }\n}\n\nexport interface CurrentCfTargetReadOptions {\n readonly command?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly signal?: AbortSignal;\n readonly timeoutMs?: number;\n}\n\nexport interface CurrentCfTarget {\n readonly apiEndpoint: string;\n readonly region?: string;\n readonly org: string;\n readonly space: string;\n}\n\nexport async function cfApi(apiEndpoint: string, context: CfExecContext): Promise<void> {\n await runCf([\"api\", apiEndpoint], context);\n}\n\nexport async function cfAuth(\n email: string,\n password: string,\n context: CfExecContext,\n): Promise<void> {\n try {\n await runCf([\"auth\"], context, {\n env: { CF_PASSWORD: password, CF_USERNAME: email },\n sensitiveValues: [email, password],\n });\n } catch (error: unknown) {\n rethrowControlFlowError(error);\n if (error instanceof CfDebuggerError) {\n throw new CfDebuggerError(\n \"CF_AUTH_FAILED\",\n `${error.message}. Check SAP_EMAIL and SAP_PASSWORD before retrying.`,\n error.stderr,\n );\n }\n throw error;\n }\n}\n\nexport async function cfLogin(\n apiEndpoint: string,\n email: string,\n password: string,\n context: CfExecContext,\n): Promise<void> {\n try {\n await cfApi(apiEndpoint, context);\n } catch (error: unknown) {\n rethrowControlFlowError(error);\n if (error instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"CF_LOGIN_FAILED\", error.message, error.stderr);\n }\n throw error;\n }\n await cfAuth(email, password, context);\n}\n\nexport async function cfTarget(\n org: string,\n space: string,\n context: CfExecContext,\n): Promise<void> {\n try {\n await runCf([\"target\", \"-o\", org, \"-s\", space], context);\n } catch (err: unknown) {\n rethrowControlFlowError(err);\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"CF_TARGET_FAILED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfAppExists(appName: string, context: CfExecContext): Promise<boolean> {\n try {\n await runCf([\"app\", appName], context);\n return true;\n } catch (err: unknown) {\n rethrowControlFlowError(err);\n const stderr = err instanceof CfDebuggerError ? err.stderr ?? \"\" : \"\";\n if (stderr.toLowerCase().includes(\"not found\")) {\n return false;\n }\n throw err;\n }\n}\n\nexport type SshEnablementState = \"disabled\" | \"enabled\" | \"unknown\";\n\nexport async function cfSshEnabled(\n appName: string,\n context: CfExecContext,\n): Promise<SshEnablementState> {\n try {\n const stdout = await runCf([\"ssh-enabled\", appName], context);\n const normalized = stdout.toLowerCase();\n if (normalized.includes(\"ssh support is enabled\")) {\n return \"enabled\";\n }\n if (normalized.includes(\"ssh support is disabled\")) {\n return \"disabled\";\n }\n return \"unknown\";\n } catch (err: unknown) {\n rethrowControlFlowError(err);\n return \"unknown\";\n }\n}\n\nexport async function cfEnableSsh(appName: string, context: CfExecContext): Promise<void> {\n try {\n await runCf([\"enable-ssh\", appName], context);\n } catch (err: unknown) {\n rethrowControlFlowError(err);\n if (err instanceof CfDebuggerError) {\n throw new CfDebuggerError(\"SSH_NOT_ENABLED\", err.message, err.stderr);\n }\n throw err;\n }\n}\n\nexport async function cfRestartApp(appName: string, context: CfExecContext): Promise<void> {\n await runCf([\"restart\", appName], context);\n}\n\nexport async function readCurrentCfTarget(\n options: CurrentCfTargetReadOptions = {},\n): Promise<CurrentCfTarget | undefined> {\n try {\n const { stdout } = await executeFileBounded(\n options.command ?? process.env[\"CF_DEBUGGER_CF_BIN\"] ?? \"cf\",\n [\"target\"],\n {\n env: { ...process.env, ...options.env, CF_COLOR: \"false\" },\n maxBuffer: 16 * 1024 * 1024,\n timeoutMs: options.timeoutMs ?? CURRENT_TARGET_TIMEOUT_MS,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n },\n );\n return parseCurrentCfTarget(stdout);\n } catch (error: unknown) {\n if (\n options.signal?.aborted === true ||\n (typeof error === \"object\" && error !== null && Reflect.get(error, \"code\") === \"ABORT_ERR\")\n ) {\n throw new CfDebuggerError(\"ABORTED\", \"Current CF target discovery was aborted.\");\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new CfDebuggerError(\"CF_TARGET_FAILED\", `cf target failed: ${message}`);\n }\n}\n\nexport function parseCurrentCfTarget(stdout: string): CurrentCfTarget | undefined {\n const fields = parseTargetFields(stdout);\n const apiEndpoint = fields.get(\"api endpoint\");\n const org = fields.get(\"org\");\n const space = fields.get(\"space\");\n if (!isPresent(apiEndpoint) || !isPresent(org) || !isPresent(space)) {\n return undefined;\n }\n\n const region = regionKeyForApiEndpoint(apiEndpoint);\n return {\n apiEndpoint,\n ...(region === undefined ? {} : { region }),\n org,\n space,\n };\n}\n\nexport function requireCurrentCfRegion(\n target: Pick<CurrentCfTarget, \"apiEndpoint\" | \"region\">,\n instruction = \"Pass --region explicitly.\",\n): string {\n if (target.region !== undefined) {\n return target.region;\n }\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n `Current CF API endpoint \"${target.apiEndpoint}\" does not match a known SAP region. ${instruction}`,\n );\n}\n\nfunction parseTargetFields(stdout: string): Map<string, string> {\n return new Map(\n stdout\n .split(\"\\n\")\n .map((line): readonly [string, string] | undefined => {\n const separator = line.indexOf(\":\");\n if (separator < 0) {\n return undefined;\n }\n return [\n line.slice(0, separator).trim().toLowerCase(),\n line.slice(separator + 1).trim(),\n ];\n })\n .filter((field): field is readonly [string, string] => field !== undefined),\n );\n}\n\nexport function regionKeyForApiEndpoint(apiEndpoint: string): string | undefined {\n const normalized = normalizeApiEndpoint(apiEndpoint);\n const known = listKnownRegionKeys().find((key) => normalizeApiEndpoint(resolveApiEndpoint(key)) === normalized);\n if (known !== undefined) {\n return known;\n }\n return regionKeyFromSapApiEndpoint(normalized);\n}\n\nfunction normalizeApiEndpoint(apiEndpoint: string): string {\n return apiEndpoint.trim().replace(/\\/+$/, \"\").toLowerCase();\n}\n\nexport function regionKeyFromSapApiEndpoint(apiEndpoint: string): string | undefined {\n const match = /^https:\\/\\/api\\.cf\\.([a-z]{2}\\d{2}(?:-\\d{3})?)\\.(hana\\.ondemand\\.com|platform\\.sapcloud\\.cn)$/.exec(apiEndpoint);\n const regionKey = match?.[1];\n const domain = match?.[2];\n if (regionKey === undefined || domain === undefined) {\n return undefined;\n }\n const expectedDomain = regionKey.startsWith(\"cn\")\n ? \"platform.sapcloud.cn\"\n : \"hana.ondemand.com\";\n return domain === expectedDomain ? regionKey : undefined;\n}\n\nfunction isPresent(value: string | undefined): value is string {\n return value !== undefined && value.length > 0;\n}\n","import { CfDebuggerError } from \"../types.js\";\n\nexport const DEFAULT_CF_PROCESS = \"web\";\nexport const DEFAULT_CF_INSTANCE = 0;\nexport const DEFAULT_NODE_INSPECTOR_PORT = 9229;\n\nconst MAX_MARKER_BYTES = 65_536;\nconst PID_LIST_PATTERN = /^\\d+(?:,\\d+)*$/;\nconst PID_PATTERN = /^\\d+$/;\n\nexport interface NodeTargetSelectors {\n readonly process?: string;\n readonly instance?: number;\n readonly nodePid?: number;\n}\n\nexport interface ResolvedNodeTarget {\n readonly process: string;\n readonly instance: number;\n readonly nodePid?: number;\n}\n\nexport interface NodeProcessSelection {\n readonly remoteNodePid: number;\n}\n\nfunction validateProcessName(processName: string): void {\n if (processName.length === 0 || processName.startsWith(\"-\") || hasControlCharacter(processName)) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"process must be non-empty, must not start with a hyphen, and must contain no control characters.\",\n );\n }\n}\n\nfunction validateInstance(instance: number): void {\n if (!Number.isSafeInteger(instance) || instance < 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"instance must be a non-negative safe integer.\");\n }\n}\n\nfunction validateNodePid(nodePid: number | undefined): void {\n if (nodePid !== undefined && (!Number.isSafeInteger(nodePid) || nodePid <= 0)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"nodePid must be a positive safe integer.\");\n }\n}\n\nfunction validateRemotePort(remotePort: number): void {\n if (!Number.isSafeInteger(remotePort) || remotePort < 1 || remotePort > 65_535) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"remotePort must be an integer between 1 and 65535.\");\n }\n}\n\nexport function resolveNodeTarget(input: NodeTargetSelectors): ResolvedNodeTarget {\n const processName = (input.process ?? DEFAULT_CF_PROCESS).trim();\n const instance = input.instance ?? DEFAULT_CF_INSTANCE;\n validateProcessName(processName);\n validateInstance(instance);\n validateNodePid(input.nodePid);\n return input.nodePid === undefined\n ? { process: processName, instance }\n : { process: processName, instance, nodePid: input.nodePid };\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code < 32 || code === 127) {\n return true;\n }\n }\n return false;\n}\n\nexport function buildNodeInspectorCommand(\n nodePid?: number,\n remotePort = DEFAULT_NODE_INSPECTOR_PORT,\n): string {\n validateNodePid(nodePid);\n validateRemotePort(remotePort);\n const remotePortHex = remotePort.toString(16).toUpperCase().padStart(4, \"0\");\n return NODE_INSPECTOR_SCRIPT\n .replace(\"__REQUESTED_NODE_PID__\", nodePid?.toString() ?? \"\")\n .replaceAll(\"__INSPECTOR_PORT_HEX__\", remotePortHex);\n}\n\nexport function parseNodeInspectorMarkers(\n stdout: string,\n remotePort = DEFAULT_NODE_INSPECTOR_PORT,\n): NodeProcessSelection {\n validateRemotePort(remotePort);\n if (Buffer.byteLength(stdout, \"utf8\") > MAX_MARKER_BYTES) {\n throw new CfDebuggerError(\"INSPECTOR_OUTPUT_TOO_LARGE\", \"Inspector startup output exceeded 65536 bytes.\");\n }\n const markers = parseMarkers(stdout);\n throwForFailureMarker(markers, remotePort);\n const remoteNodePid = readMarkerPid(markers, \"saptools-inspector-node-pid\");\n const ownerPid = readMarkerPid(markers, \"saptools-inspector-owner-pid\");\n if (!markers.has(\"saptools-inspector-ready\") || remoteNodePid === undefined || ownerPid !== remoteNodePid) {\n throw new CfDebuggerError(\"INSPECTOR_NOT_READY\", \"Remote Node inspector did not report a verified owner.\");\n }\n return { remoteNodePid };\n}\n\nfunction parseMarkers(stdout: string): ReadonlyMap<string, string> {\n const markers = new Map<string, string>();\n for (const rawLine of stdout.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line.startsWith(\"saptools-inspector-\")) {\n continue;\n }\n const separator = line.indexOf(\"=\");\n markers.set(separator < 0 ? line : line.slice(0, separator), separator < 0 ? \"\" : line.slice(separator + 1));\n }\n return markers;\n}\n\nfunction throwForFailureMarker(markers: ReadonlyMap<string, string>, remotePort: number): void {\n if (markers.has(\"saptools-inspector-node-not-found\")) {\n throw new CfDebuggerError(\"NODE_PROCESS_NOT_FOUND\", \"No Node.js process was found in the selected CF instance.\");\n }\n const ambiguous = markers.get(\"saptools-inspector-node-ambiguous\");\n if (ambiguous !== undefined) {\n const candidates = PID_LIST_PATTERN.test(ambiguous) ? ambiguous.split(\",\").join(\", \") : \"unknown\";\n throw new CfDebuggerError(\"NODE_PROCESS_AMBIGUOUS\", `Multiple Node.js processes were found: ${candidates}. Pass nodePid explicitly.`);\n }\n const invalid = markers.get(\"saptools-inspector-node-invalid\");\n if (invalid !== undefined) {\n throw new CfDebuggerError(\"NODE_PID_INVALID\", `Remote PID ${safePidText(invalid)} is not a Node.js process.`);\n }\n throwForRuntimeFailure(markers, remotePort);\n}\n\nfunction throwForRuntimeFailure(markers: ReadonlyMap<string, string>, remotePort: number): void {\n const mismatch = markers.get(\"saptools-inspector-owner-mismatch\");\n if (mismatch !== undefined) {\n const [selected = \"unknown\", owner = \"unknown\"] = mismatch.split(\":\", 2).map(safePidText);\n throw new CfDebuggerError(\n \"INSPECTOR_OWNER_MISMATCH\",\n `Selected Node PID ${selected}, but inspector port ${remotePort.toString()} is owned by PID ${owner}.`,\n );\n }\n const signalFailed = markers.get(\"saptools-inspector-signal-failed\");\n if (signalFailed !== undefined) {\n throw new CfDebuggerError(\"USR1_SIGNAL_FAILED\", `Failed to signal remote Node PID ${safePidText(signalFailed)}.`);\n }\n if (markers.has(\"saptools-inspector-not-ready\")) {\n throw new CfDebuggerError(\n \"INSPECTOR_NOT_READY\",\n `Remote Node inspector did not become ready on port ${remotePort.toString()}.`,\n );\n }\n}\n\nfunction readMarkerPid(markers: ReadonlyMap<string, string>, name: string): number | undefined {\n const raw = markers.get(name);\n if (raw === undefined || !PID_PATTERN.test(raw)) {\n return undefined;\n }\n const value = Number.parseInt(raw, 10);\n return Number.isSafeInteger(value) && value > 0 ? value : undefined;\n}\n\nfunction safePidText(raw: string): string {\n return PID_PATTERN.test(raw) ? raw : \"unknown\";\n}\n\nconst NODE_INSPECTOR_SCRIPT = [\n \"requested_node_pid=__REQUESTED_NODE_PID__\",\n \"inspector_port_hex=__INSPECTOR_PORT_HEX__\",\n \"is_node_pid() {\",\n \" candidate_pid=\\\"$1\\\"\",\n \" candidate_exe=\\\"$(readlink \\\"/proc/$candidate_pid/exe\\\" 2>/dev/null || true)\\\"\",\n \" [ \\\"${candidate_exe##*/}\\\" = node ] || [ \\\"${candidate_exe##*/}\\\" = nodejs ]\",\n \"}\",\n \"find_listener_inode() {\",\n \" listener_hex=\\\"$1\\\"\",\n \" [ -n \\\"$listener_hex\\\" ] || return 0\",\n \" awk -v ph=\\\":$listener_hex\\\" '$4 == \\\"0A\\\" && $2 ~ (ph \\\"$\\\") { print $10; exit }' /proc/net/tcp /proc/net/tcp6 2>/dev/null\",\n \"}\",\n \"find_inode_owner_fallback() {\",\n \" socket_inode=\\\"$1\\\"\",\n \" [ -n \\\"$socket_inode\\\" ] || return 0\",\n \" for pid_dir in /proc/[0-9]*; do\",\n \" [ -d \\\"$pid_dir/fd\\\" ] || continue\",\n \" for fd_path in \\\"$pid_dir\\\"/fd/*; do\",\n \" fd_target=\\\"$(readlink \\\"$fd_path\\\" 2>/dev/null || true)\\\"\",\n \" if [ \\\"$fd_target\\\" = \\\"socket:[$socket_inode]\\\" ]; then\",\n \" printf '%s' \\\"${pid_dir##*/}\\\"\",\n \" return 0\",\n \" fi\",\n \" done\",\n \" done\",\n \"}\",\n \"find_inode_owner() {\",\n \" socket_inode=\\\"$1\\\"\",\n \" [ -n \\\"$socket_inode\\\" ] || return 0\",\n \" if [ \\\"$find_supports_lname\\\" = true ]; then\",\n \" fd_path=\\\"$(find /proc/[0-9]*/fd -lname \\\"socket:\\\\[$socket_inode\\\\]\\\" -print -quit 2>/dev/null || true)\\\"\",\n \" [ -n \\\"$fd_path\\\" ] || return 0\",\n \" pid_path=\\\"${fd_path#/proc/}\\\"\",\n \" printf '%s' \\\"${pid_path%%/*}\\\"\",\n \" return 0\",\n \" fi\",\n \" find_inode_owner_fallback \\\"$socket_inode\\\"\",\n \"}\",\n \"pid_owns_inode() {\",\n \" candidate_pid=\\\"$1\\\"\",\n \" socket_inode=\\\"$2\\\"\",\n \" [ -d \\\"/proc/$candidate_pid/fd\\\" ] || return 1\",\n \" if [ \\\"$find_supports_lname\\\" = true ]; then\",\n \" fd_path=\\\"$(find \\\"/proc/$candidate_pid/fd\\\" -lname \\\"socket:\\\\[$socket_inode\\\\]\\\" -print -quit 2>/dev/null || true)\\\"\",\n \" [ -n \\\"$fd_path\\\" ]\",\n \" return\",\n \" fi\",\n \" for fd_path in \\\"/proc/$candidate_pid/fd\\\"/*; do\",\n \" fd_target=\\\"$(readlink \\\"$fd_path\\\" 2>/dev/null || true)\\\"\",\n \" [ \\\"$fd_target\\\" = \\\"socket:[$socket_inode]\\\" ] && return 0\",\n \" done\",\n \" return 1\",\n \"}\",\n \"find_listener_pid() {\",\n \" socket_inode=\\\"$(find_listener_inode \\\"$1\\\")\\\"\",\n \" find_inode_owner \\\"$socket_inode\\\"\",\n \"}\",\n \"find_inspector_owner() {\",\n \" find_listener_pid \\\"$inspector_port_hex\\\"\",\n \"}\",\n \"find_selected_inspector_owner() {\",\n \" candidate_pid=\\\"$1\\\"\",\n \" socket_inode=\\\"$(find_listener_inode \\\"$inspector_port_hex\\\")\\\"\",\n \" [ -n \\\"$socket_inode\\\" ] || return 0\",\n \" if pid_owns_inode \\\"$candidate_pid\\\" \\\"$socket_inode\\\"; then\",\n \" printf '%s' \\\"$candidate_pid\\\"\",\n \" return 0\",\n \" fi\",\n \" find_inode_owner \\\"$socket_inode\\\"\",\n \"}\",\n \"find_app_port_listener() {\",\n \" [ -n \\\"${PORT:-}\\\" ] || return 0\",\n \" app_port_hex=\\\"$(printf '%04X' \\\"$PORT\\\" 2>/dev/null || true)\\\"\",\n \" find_listener_pid \\\"$app_port_hex\\\"\",\n \"}\",\n \"find_supports_lname=false\",\n \"if find /proc/self/fd -lname __saptools_no_match__ -print -quit >/dev/null 2>&1; then\",\n \" find_supports_lname=true\",\n \"fi\",\n \"owner_pid=\\\"$(find_inspector_owner)\\\"\",\n \"selected_pid=\\\"\\\"\",\n \"if [ -n \\\"$requested_node_pid\\\" ]; then\",\n \" if ! is_node_pid \\\"$requested_node_pid\\\"; then\",\n \" echo \\\"saptools-inspector-node-invalid=$requested_node_pid\\\"\",\n \" exit 0\",\n \" fi\",\n \" selected_pid=\\\"$requested_node_pid\\\"\",\n \"elif [ -n \\\"$owner_pid\\\" ] && is_node_pid \\\"$owner_pid\\\"; then\",\n \" selected_pid=\\\"$owner_pid\\\"\",\n \"else\",\n \" candidate_pids=\\\"\\\"\",\n \" candidate_count=0\",\n \" for pid_dir in /proc/[0-9]*; do\",\n \" candidate_pid=\\\"${pid_dir##*/}\\\"\",\n \" is_node_pid \\\"$candidate_pid\\\" || continue\",\n \" candidate_count=$((candidate_count + 1))\",\n \" candidate_pids=\\\"${candidate_pids}${candidate_pids:+,}$candidate_pid\\\"\",\n \" selected_pid=\\\"$candidate_pid\\\"\",\n \" done\",\n \" if [ \\\"$candidate_count\\\" -eq 0 ]; then echo saptools-inspector-node-not-found; exit 0; fi\",\n \" if [ \\\"$candidate_count\\\" -ne 1 ]; then\",\n \" app_port_pid=\\\"$(find_app_port_listener)\\\"\",\n \" if [ -n \\\"$app_port_pid\\\" ] && is_node_pid \\\"$app_port_pid\\\"; then\",\n \" selected_pid=\\\"$app_port_pid\\\"\",\n \" else\",\n \" echo \\\"saptools-inspector-node-ambiguous=$candidate_pids\\\"; exit 0\",\n \" fi\",\n \" fi\",\n \"fi\",\n \"if [ -n \\\"$owner_pid\\\" ]; then\",\n \" if [ \\\"$owner_pid\\\" != \\\"$selected_pid\\\" ]; then echo \\\"saptools-inspector-owner-mismatch=$selected_pid:$owner_pid\\\"; exit 0; fi\",\n \" echo \\\"saptools-inspector-node-pid=$selected_pid\\\"\",\n \" echo \\\"saptools-inspector-owner-pid=$owner_pid\\\"\",\n \" echo saptools-inspector-ready\",\n \" exit 0\",\n \"fi\",\n \"if ! kill -USR1 \\\"$selected_pid\\\" 2>/dev/null; then echo \\\"saptools-inspector-signal-failed=$selected_pid\\\"; exit 0; fi\",\n \"attempt=0\",\n \"while [ \\\"$attempt\\\" -lt 20 ]; do\",\n \" owner_pid=\\\"$(find_selected_inspector_owner \\\"$selected_pid\\\")\\\"\",\n \" if [ -n \\\"$owner_pid\\\" ]; then\",\n \" if [ \\\"$owner_pid\\\" != \\\"$selected_pid\\\" ]; then echo \\\"saptools-inspector-owner-mismatch=$selected_pid:$owner_pid\\\"; exit 0; fi\",\n \" echo \\\"saptools-inspector-node-pid=$selected_pid\\\"\",\n \" echo \\\"saptools-inspector-owner-pid=$owner_pid\\\"\",\n \" echo saptools-inspector-ready\",\n \" exit 0\",\n \" fi\",\n \" attempt=$((attempt + 1))\",\n // CF Linux stacks accept fractional sleep; retain a one-second POSIX fallback.\n \" sleep 0.25 2>/dev/null || sleep 1\",\n \"done\",\n \"echo \\\"saptools-inspector-not-ready=$selected_pid\\\"\",\n].join(\"\\n\");\n","import { spawn, type ChildProcess, type ChildProcessByStdio } from \"node:child_process\";\nimport nodeProcess from \"node:process\";\nimport type { Readable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nimport {\n buildEnv,\n DEFAULT_CF_COMMAND_TIMEOUT_MS,\n normalizeSensitiveValues,\n redactSensitiveText,\n resolveBin,\n type CfExecContext,\n} from \"./execute.js\";\nimport {\n DEFAULT_CF_PROCESS,\n resolveNodeTarget,\n type NodeTargetSelectors,\n} from \"./node-process.js\";\n\nconst DEFAULT_MAX_OUTPUT_BYTES = 65_536;\nconst LIVE_LINE_LIMIT_BYTES = 65_536;\nconst MAX_REDACTION_OVERLAP_BYTES = 4096;\nconst SENSITIVE_OUTPUT_OMITTED = \"[diagnostic output omitted to protect a sensitive value]\";\n\nexport interface CfSshSignalResult {\n readonly exitCode: number | null;\n readonly stdout: string;\n readonly stderr: string;\n /** Compatibility aggregate; parsing decisions should use the stream-specific fields. */\n readonly outputTruncated: boolean;\n readonly stdoutTruncated: boolean;\n readonly stderrTruncated: boolean;\n readonly signal?: NodeJS.Signals;\n readonly timedOutAfterMs?: number;\n}\n\nexport interface TunnelDiagnostics {\n readonly stdout: string;\n readonly stderr: string;\n readonly stdoutTruncated: boolean;\n readonly stderrTruncated: boolean;\n}\n\nexport interface CfSshOptions extends NodeTargetSelectors {\n readonly timeoutMs?: number;\n readonly maxOutputBytes?: number;\n}\n\ninterface ResolvedSshOptions {\n readonly target: NodeTargetSelectors;\n readonly timeoutMs: number;\n readonly maxOutputBytes: number;\n}\n\ninterface BoundedOutput {\n chunks: Buffer[];\n bytes: number;\n truncated: boolean;\n}\n\ninterface RedactionPolicy {\n readonly safeToSurface: boolean;\n readonly sensitiveValues: readonly string[];\n readonly overlapBytes: number;\n}\n\ninterface SshExecutionState {\n readonly stdout: BoundedOutput;\n readonly stderr: BoundedOutput;\n readonly outputLimit: number;\n readonly retainedLimit: number;\n readonly redaction: RedactionPolicy;\n settled: boolean;\n aborted: boolean;\n timedOut: boolean;\n timeoutTimer?: NodeJS.Timeout;\n forceKillTimer?: NodeJS.Timeout;\n}\n\ninterface TunnelCapture {\n readonly stdout: BoundedOutput;\n readonly stderr: BoundedOutput;\n readonly outputLimit: number;\n readonly retainedLimit: number;\n readonly redaction: RedactionPolicy;\n readonly stderrDecoder: StringDecoder;\n readonly stdoutDecoder: StringDecoder;\n stdoutCarry: string;\n stdoutSuppressed: boolean;\n stderrCarry: string;\n stderrSuppressed: boolean;\n}\n\nconst tunnelCaptures = new WeakMap<ChildProcess, TunnelCapture>();\n\nexport function buildCfSshArgs(\n appName: string,\n target: NodeTargetSelectors,\n tail: readonly string[],\n): readonly string[] {\n const resolved = resolveNodeTarget(target);\n const processArgs = resolved.process === DEFAULT_CF_PROCESS\n ? []\n : [\"--process\", resolved.process];\n return [\n \"ssh\",\n appName,\n ...processArgs,\n \"-i\",\n resolved.instance.toString(),\n ...tail,\n ];\n}\n\nexport async function cfSshOneShot(\n appName: string,\n command: string,\n context: CfExecContext,\n rawOptions: number | CfSshOptions = DEFAULT_CF_COMMAND_TIMEOUT_MS,\n): Promise<CfSshSignalResult> {\n if (context.signal?.aborted || isDeadlineExpired(context)) {\n throw sshAbortError(context);\n }\n const options = resolveSshOptions(rawOptions, context);\n const args = buildCfSshArgs(appName, options.target, [\n \"--disable-pseudo-tty\",\n \"-c\",\n command,\n ]);\n return await runSshOneShot(args, context, options);\n}\n\nfunction resolveSshOptions(\n raw: number | CfSshOptions,\n context: CfExecContext,\n): ResolvedSshOptions {\n const input = typeof raw === \"number\" ? { timeoutMs: raw } : raw;\n const requestedTimeoutMs = input.timeoutMs ?? DEFAULT_CF_COMMAND_TIMEOUT_MS;\n const maxOutputBytes = input.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;\n if (!Number.isSafeInteger(requestedTimeoutMs) || requestedTimeoutMs <= 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"timeoutMs must be a positive safe integer.\");\n }\n if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes <= 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"maxOutputBytes must be a positive safe integer.\");\n }\n const remainingMs = context.deadlineAt === undefined\n ? requestedTimeoutMs\n : Math.max(1, context.deadlineAt - Date.now());\n return {\n target: input,\n timeoutMs: Math.min(requestedTimeoutMs, remainingMs),\n maxOutputBytes,\n };\n}\n\nfunction createBoundedOutput(): BoundedOutput {\n return { chunks: [], bytes: 0, truncated: false };\n}\n\nfunction appendHead(\n output: BoundedOutput,\n data: Buffer | string,\n outputLimit: number,\n retainedLimit: number,\n): void {\n const incoming = Buffer.isBuffer(data) ? data : Buffer.from(data);\n if (incoming.byteLength === 0) {\n return;\n }\n output.truncated ||= output.bytes + incoming.byteLength > outputLimit;\n const remaining = Math.max(0, retainedLimit - output.bytes);\n if (remaining === 0) {\n return;\n }\n const next = incoming.byteLength <= remaining\n ? incoming\n : Buffer.from(incoming.subarray(0, remaining));\n output.chunks.push(next);\n output.bytes += next.byteLength;\n}\n\nfunction appendTail(\n output: BoundedOutput,\n data: Buffer | string,\n outputLimit: number,\n retainedLimit: number,\n): void {\n const incoming = Buffer.isBuffer(data) ? data : Buffer.from(data);\n if (incoming.byteLength === 0) {\n return;\n }\n output.chunks.push(incoming);\n output.bytes += incoming.byteLength;\n output.truncated ||= output.bytes > outputLimit;\n while (output.bytes > retainedLimit && output.chunks.length > 0) {\n const first = output.chunks[0];\n if (first === undefined) {\n break;\n }\n const excess = output.bytes - retainedLimit;\n if (first.byteLength <= excess) {\n output.chunks.shift();\n output.bytes -= first.byteLength;\n } else {\n output.chunks[0] = Buffer.from(first.subarray(excess));\n output.bytes -= excess;\n }\n }\n}\n\nfunction outputText(output: BoundedOutput): string {\n return Buffer.concat(output.chunks, output.bytes).toString(\"utf8\");\n}\n\nfunction createRedactionPolicy(values: readonly string[]): RedactionPolicy {\n const sensitiveValues = normalizeSensitiveValues(values);\n const overlapBytes = sensitiveValues.reduce(\n (largest, value) => Math.max(largest, Buffer.byteLength(value)),\n 0,\n );\n return {\n safeToSurface: overlapBytes <= MAX_REDACTION_OVERLAP_BYTES &&\n !sensitiveValues.some((value) => /[\\r\\n]/.test(value)),\n sensitiveValues,\n overlapBytes: Math.min(overlapBytes, MAX_REDACTION_OVERLAP_BYTES),\n };\n}\n\nfunction limitText(text: string, limit: number, keep: \"head\" | \"tail\"): string {\n const buffer = Buffer.from(text);\n if (buffer.byteLength <= limit) {\n return text;\n }\n const limited = keep === \"head\"\n ? buffer.subarray(0, limit)\n : buffer.subarray(buffer.byteLength - limit);\n return limited.toString(\"utf8\");\n}\n\nfunction safeOutputText(\n output: BoundedOutput,\n policy: RedactionPolicy,\n limit: number,\n keep: \"head\" | \"tail\",\n): string {\n if (!policy.safeToSurface && output.bytes > 0) {\n return SENSITIVE_OUTPUT_OMITTED;\n }\n const redacted = redactSensitiveText(outputText(output), policy.sensitiveValues);\n return limitText(redacted, limit, keep);\n}\n\nfunction createResult(\n exitCode: number | null,\n state: SshExecutionState,\n): CfSshSignalResult {\n const stdout = safeOutputText(state.stdout, state.redaction, state.outputLimit, \"head\");\n const stderr = safeOutputText(state.stderr, state.redaction, state.outputLimit, \"head\");\n return {\n exitCode,\n stdout,\n stderr,\n outputTruncated: state.stdout.truncated || state.stderr.truncated,\n stdoutTruncated: state.stdout.truncated,\n stderrTruncated: state.stderr.truncated,\n };\n}\n\nfunction createSshExecutionState(\n context: CfExecContext,\n outputLimit: number,\n): SshExecutionState {\n const redaction = createRedactionPolicy(context.sensitiveValues ?? []);\n return {\n stdout: createBoundedOutput(),\n stderr: createBoundedOutput(),\n outputLimit,\n retainedLimit: outputLimit + redaction.overlapBytes,\n redaction,\n settled: false,\n aborted: false,\n timedOut: false,\n };\n}\n\nfunction terminateSshExecution(child: ReturnType<typeof spawn>, state: SshExecutionState): void {\n signalChild(child, \"SIGTERM\");\n state.forceKillTimer ??= setTimeout(() => {\n signalChild(child, \"SIGKILL\");\n }, 1000);\n}\n\nfunction sshAbortError(context: CfExecContext): CfDebuggerError {\n if (context.deadlineAt !== undefined && Date.now() >= context.deadlineAt) {\n return new CfDebuggerError(\n \"STARTUP_TIMEOUT\",\n `Debugger startup exceeded its configured deadline during ${context.phase ?? \"remote signalling\"}.`,\n );\n }\n return new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n}\n\nfunction isDeadlineExpired(context: CfExecContext): boolean {\n return context.deadlineAt !== undefined && Date.now() >= context.deadlineAt;\n}\n\nfunction createSshSettler(\n state: SshExecutionState,\n options: ResolvedSshOptions,\n context: CfExecContext,\n onAbort: () => void,\n resolve: (result: CfSshSignalResult) => void,\n reject: (reason?: unknown) => void,\n): (result: CfSshSignalResult) => void {\n return (result): void => {\n if (state.settled) {\n return;\n }\n state.settled = true;\n clearTimeout(state.timeoutTimer);\n clearTimeout(state.forceKillTimer);\n context.signal?.removeEventListener(\"abort\", onAbort);\n if (state.aborted) {\n reject(sshAbortError(context));\n return;\n }\n resolve(state.timedOut ? { ...result, timedOutAfterMs: options.timeoutMs } : result);\n };\n}\n\nfunction attachSshExecution(\n child: ChildProcessByStdio<null, Readable, Readable>,\n context: CfExecContext,\n options: ResolvedSshOptions,\n resolve: (result: CfSshSignalResult) => void,\n reject: (reason?: unknown) => void,\n): void {\n const state = createSshExecutionState(context, options.maxOutputBytes);\n const onAbort = (): void => {\n state.aborted = true;\n terminateSshExecution(child, state);\n };\n const settle = createSshSettler(state, options, context, onAbort, resolve, reject);\n state.timeoutTimer = setTimeout(() => {\n state.timedOut = true;\n terminateSshExecution(child, state);\n }, options.timeoutMs);\n if (context.signal?.aborted) {\n onAbort();\n } else {\n context.signal?.addEventListener(\"abort\", onAbort, { once: true });\n }\n child.stdout.on(\"data\", (data: Buffer | string) => {\n appendHead(state.stdout, data, state.outputLimit, state.retainedLimit);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n appendHead(state.stderr, data, state.outputLimit, state.retainedLimit);\n });\n child.on(\"close\", (code, signal) => {\n const base = createResult(code, state);\n settle(state.timedOut || signal === null ? base : { ...base, signal });\n });\n child.on(\"error\", (error: Error) => {\n appendHead(state.stderr, error.message, state.outputLimit, state.retainedLimit);\n settle(createResult(null, state));\n });\n}\n\nfunction runSshOneShot(\n args: readonly string[],\n context: CfExecContext,\n options: ResolvedSshOptions,\n): Promise<CfSshSignalResult> {\n if (context.signal?.aborted || isDeadlineExpired(context)) {\n return Promise.reject(sshAbortError(context));\n }\n return new Promise<CfSshSignalResult>((resolve, reject) => {\n const child = spawn(resolveBin(context), [...args], {\n env: buildEnv(context.cfHome),\n detached: nodeProcess.platform !== \"win32\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n attachSshExecution(child, context, options, resolve, reject);\n });\n}\n\nfunction signalChild(child: ReturnType<typeof spawn>, signal: NodeJS.Signals): void {\n if (nodeProcess.platform !== \"win32\" && child.pid !== undefined) {\n try {\n nodeProcess.kill(-child.pid, signal);\n return;\n } catch {\n // The process may not have established its group before termination.\n }\n }\n try {\n child.kill(signal);\n } catch {\n // The child already exited between the termination request and signal.\n }\n}\n\nexport function isSshDisabledError(stderr: string): boolean {\n return stderr.toLowerCase().includes(\"ssh support is disabled\");\n}\n\nexport function isSshPermissionError(stderr: string): boolean {\n return stderr.toLowerCase().includes(\"not authorized\");\n}\n\nfunction liveOutputText(capture: TunnelCapture, line: string): string {\n if (!capture.redaction.safeToSurface && line.length > 0) {\n return SENSITIVE_OUTPUT_OMITTED;\n }\n if (Buffer.byteLength(line) > LIVE_LINE_LIMIT_BYTES) {\n return \"[output line omitted: exceeded live diagnostic limit]\";\n }\n return redactSensitiveText(line, capture.redaction.sensitiveValues);\n}\n\nfunction skipSuppressedLine(\n capture: TunnelCapture,\n stream: \"stderr\" | \"stdout\",\n text: string,\n): string {\n const suppressedKey = stream === \"stdout\"\n ? \"stdoutSuppressed\"\n : \"stderrSuppressed\";\n if (!capture[suppressedKey]) {\n return text;\n }\n const newline = text.indexOf(\"\\n\");\n if (newline < 0) {\n return \"\";\n }\n capture[suppressedKey] = false;\n return text.slice(newline + 1);\n}\n\nfunction emitCompleteLines(\n capture: TunnelCapture,\n stream: \"stderr\" | \"stdout\",\n data: Buffer | string,\n emit: CfExecContext[\"onTunnelOutput\"],\n): void {\n if (emit === undefined) {\n return;\n }\n const key = stream === \"stdout\" ? \"stdoutCarry\" : \"stderrCarry\";\n const suppressedKey = stream === \"stdout\"\n ? \"stdoutSuppressed\"\n : \"stderrSuppressed\";\n const decoder = stream === \"stdout\" ? capture.stdoutDecoder : capture.stderrDecoder;\n const incoming = decoder.write(Buffer.isBuffer(data) ? data : Buffer.from(data));\n const combined = `${capture[key]}${skipSuppressedLine(capture, stream, incoming)}`;\n const lines = combined.split(\"\\n\");\n capture[key] = lines.pop() ?? \"\";\n for (const line of lines) {\n emit(stream, liveOutputText(capture, line.endsWith(\"\\r\") ? line.slice(0, -1) : line));\n }\n if (Buffer.byteLength(capture[key]) > LIVE_LINE_LIMIT_BYTES) {\n capture[key] = \"\";\n capture[suppressedKey] = true;\n emit(stream, \"[output line omitted: exceeded live diagnostic limit]\");\n }\n}\n\nfunction flushLiveCarry(\n capture: TunnelCapture,\n stream: \"stderr\" | \"stdout\",\n emit: CfExecContext[\"onTunnelOutput\"],\n): void {\n if (emit === undefined) {\n return;\n }\n const key = stream === \"stdout\" ? \"stdoutCarry\" : \"stderrCarry\";\n const suppressedKey = stream === \"stdout\"\n ? \"stdoutSuppressed\"\n : \"stderrSuppressed\";\n if (capture[suppressedKey]) {\n capture[suppressedKey] = false;\n capture[key] = \"\";\n return;\n }\n if (capture[key].length === 0) {\n return;\n }\n emit(stream, liveOutputText(capture, capture[key]));\n capture[key] = \"\";\n}\n\nfunction attachTunnelCapture(\n child: ChildProcessByStdio<null, Readable, Readable>,\n context: CfExecContext,\n): void {\n const redaction = createRedactionPolicy(context.sensitiveValues ?? []);\n const capture: TunnelCapture = {\n stdout: createBoundedOutput(),\n stderr: createBoundedOutput(),\n outputLimit: DEFAULT_MAX_OUTPUT_BYTES,\n retainedLimit: DEFAULT_MAX_OUTPUT_BYTES + redaction.overlapBytes,\n redaction,\n stderrDecoder: new StringDecoder(\"utf8\"),\n stdoutDecoder: new StringDecoder(\"utf8\"),\n stdoutCarry: \"\",\n stdoutSuppressed: false,\n stderrCarry: \"\",\n stderrSuppressed: false,\n };\n tunnelCaptures.set(child, capture);\n child.stdout.on(\"data\", (data: Buffer | string) => {\n appendTail(capture.stdout, data, capture.outputLimit, capture.retainedLimit);\n emitCompleteLines(capture, \"stdout\", data, context.onTunnelOutput);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n appendTail(capture.stderr, data, capture.outputLimit, capture.retainedLimit);\n emitCompleteLines(capture, \"stderr\", data, context.onTunnelOutput);\n });\n child.on(\"error\", (error: Error) => {\n const diagnostic = `${error.message}\\n`;\n appendTail(capture.stderr, diagnostic, capture.outputLimit, capture.retainedLimit);\n emitCompleteLines(capture, \"stderr\", diagnostic, context.onTunnelOutput);\n });\n child.once(\"close\", () => {\n emitCompleteLines(\n capture,\n \"stdout\",\n capture.stdoutDecoder.end(),\n context.onTunnelOutput,\n );\n emitCompleteLines(\n capture,\n \"stderr\",\n capture.stderrDecoder.end(),\n context.onTunnelOutput,\n );\n flushLiveCarry(capture, \"stdout\", context.onTunnelOutput);\n flushLiveCarry(capture, \"stderr\", context.onTunnelOutput);\n });\n}\n\nexport function getTunnelDiagnostics(child: ChildProcess): TunnelDiagnostics {\n const capture = tunnelCaptures.get(child);\n if (capture === undefined) {\n return {\n stdout: \"\",\n stderr: \"\",\n stdoutTruncated: false,\n stderrTruncated: false,\n };\n }\n return {\n stdout: safeOutputText(\n capture.stdout,\n capture.redaction,\n capture.outputLimit,\n \"tail\",\n ),\n stderr: safeOutputText(\n capture.stderr,\n capture.redaction,\n capture.outputLimit,\n \"tail\",\n ),\n stdoutTruncated: capture.stdout.truncated,\n stderrTruncated: capture.stderr.truncated,\n };\n}\n\nexport function formatTunnelDiagnostics(\n diagnostics: TunnelDiagnostics,\n): string | undefined {\n const sections: string[] = [];\n const stdout = diagnostics.stdout.trim();\n const stderr = diagnostics.stderr.trim();\n if (stdout.length > 0) {\n sections.push(`[tunnel stdout]\\n${stdout}`);\n }\n if (diagnostics.stdoutTruncated) {\n sections.push(\"[tunnel stdout tail was truncated]\");\n }\n if (stderr.length > 0) {\n sections.push(`[tunnel stderr]\\n${stderr}`);\n }\n if (diagnostics.stderrTruncated) {\n sections.push(\"[tunnel stderr tail was truncated]\");\n }\n return sections.length === 0 ? undefined : sections.join(\"\\n\");\n}\n\nexport function spawnSshTunnel(\n appName: string,\n localPort: number,\n remotePort: number,\n context: CfExecContext,\n target: NodeTargetSelectors = {},\n): ReturnType<typeof spawn> {\n if (context.signal?.aborted || isDeadlineExpired(context)) {\n throw sshAbortError(context);\n }\n const tunnelArg = `${localPort.toString()}:localhost:${remotePort.toString()}`;\n const args = buildCfSshArgs(appName, target, [\"-N\", \"-L\", tunnelArg]);\n const child = spawn(resolveBin(context), [...args], {\n env: buildEnv(context.cfHome),\n detached: nodeProcess.platform !== \"win32\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n attachTunnelCapture(child, context);\n return child;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { chmod, mkdir, readFile, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { hostname as getHostname } from \"node:os\";\nimport { dirname, isAbsolute } from \"node:path\";\nimport nodeProcess from \"node:process\";\n\nimport {\n DEFAULT_NODE_INSPECTOR_PORT,\n resolveNodeTarget,\n} from \"../cloud-foundry/node-process.js\";\nimport { MAX_STARTUP_TIMEOUT_MS } from \"../debug-session/constants.js\";\nimport { readProcessIdentity } from \"../debug-session/process-identity.js\";\nimport { withFileLock } from \"../lock.js\";\nimport {\n isSafeSessionId,\n stateFilePath,\n stateLockPath,\n} from \"../paths.js\";\nimport { CfDebuggerError } from \"../types.js\";\nimport type { ActiveSession, SessionKey, StateFile } from \"../types.js\";\n\nimport { decodeStateFileDetailed } from \"./decoder.js\";\nimport { filterStaleSessions } from \"./health.js\";\nimport { writeSessionStopIntent } from \"./stop-intent.js\";\n\nexport {\n inspectSessionHealth,\n isPidAlive,\n isPidOrGroupAlive,\n isProcessGroupAlive,\n} from \"./health.js\";\nexport type {\n SessionHealthStatus,\n SessionHealthVerdict,\n} from \"./health.js\";\n\nconst DEFAULT_BASE_PORT = 20_000;\nconst DEFAULT_MAX_PORT = 20_999;\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const code: unknown = Reflect.get(error, \"code\");\n return typeof code === \"string\" ? code : undefined;\n}\n\nasync function readFileIfPresent(path: string): Promise<string | undefined> {\n try {\n await chmod(path, 0o600);\n return await readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nasync function writeJsonFileAtomic(path: string, value: unknown): Promise<void> {\n const tempPath = `${path}.${randomUUID()}.tmp`;\n const parentDir = dirname(path);\n await mkdir(parentDir, { recursive: true, mode: 0o700 });\n await chmod(parentDir, 0o700);\n let renamed = false;\n try {\n await writeFile(tempPath, `${JSON.stringify(value, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\",\n mode: 0o600,\n });\n // Atomicity is required here; crash durability across power loss is not.\n await rename(tempPath, path);\n renamed = true;\n await chmod(path, 0o600);\n } finally {\n if (!renamed) {\n await unlink(tempPath).catch(() => false);\n }\n }\n}\n\nfunction emptyState(): StateFile {\n return { version: \"2\", sessions: [] };\n}\n\nfunction corruptBackupPath(path: string): string {\n const timestamp = new Date().toISOString().replaceAll(\":\", \"-\");\n return `${path}.corrupt-${timestamp}-${randomUUID()}`;\n}\n\nasync function preserveCorruptState(path: string, reason: string): Promise<string> {\n const backup = corruptBackupPath(path);\n await rename(path, backup);\n await chmod(backup, 0o600);\n nodeProcess.stderr.write(\n `[cf-debugger] warning: preserved invalid state at ${backup} (${reason}).\\n`,\n );\n return backup;\n}\n\nasync function resetInvalidState(path: string, reason: string): Promise<StateFile> {\n await preserveCorruptState(path, reason);\n const state = emptyState();\n await writeJsonFileAtomic(path, state);\n return state;\n}\n\nasync function readStateRaw(): Promise<StateFile> {\n const path = stateFilePath();\n const raw = await readFileIfPresent(path);\n if (raw === undefined) {\n return emptyState();\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch {\n return await resetInvalidState(path, \"invalid JSON\");\n }\n const decoded = decodeStateFileDetailed(parsed);\n if (decoded.kind === \"invalid-file\") {\n return await resetInvalidState(path, decoded.reason);\n }\n if (decoded.dropped.length > 0) {\n await preserveCorruptState(path, decoded.dropped.join(\"; \"));\n await writeJsonFileAtomic(path, decoded.state);\n nodeProcess.stderr.write(\n `[cf-debugger] warning: dropped ${decoded.dropped.length.toString()} invalid state ` +\n `entr${decoded.dropped.length === 1 ? \"y\" : \"ies\"}; valid sessions were retained.\\n`,\n );\n }\n return decoded.state;\n}\n\nasync function writeState(state: StateFile): Promise<void> {\n await writeJsonFileAtomic(stateFilePath(), state);\n}\n\nexport interface StateReaderResult {\n readonly sessions: readonly ActiveSession[];\n readonly removed: readonly ActiveSession[];\n}\n\nexport interface StateAccessOptions {\n readonly signal?: AbortSignal;\n readonly timeoutMs?: number;\n}\n\ninterface PrunedState extends StateReaderResult {\n readonly persisted: StateFile;\n}\n\nasync function readAndPruneLocked(signal?: AbortSignal): Promise<PrunedState> {\n const raw = await readStateRaw();\n const host = getHostname();\n const remote = raw.sessions.filter((session) => session.hostname !== host);\n const local = raw.sessions.filter((session) => session.hostname === host);\n const sessions = await filterStaleSessions(local, signal);\n const activeIds = new Set(sessions.map((session) => session.sessionId));\n const removed = local.filter((session) => !activeIds.has(session.sessionId));\n const persisted: StateFile = { version: \"2\", sessions: [...remote, ...sessions] };\n if (removed.length > 0) {\n await writeState(persisted);\n }\n return { sessions, removed, persisted };\n}\n\nexport async function readActiveSessions(): Promise<readonly ActiveSession[]> {\n const result = await withFileLock(stateLockPath(), readAndPruneLocked);\n return result.sessions;\n}\n\nexport async function readSessionSnapshot(\n options?: StateAccessOptions,\n): Promise<readonly ActiveSession[]> {\n return await withFileLock(stateLockPath(), async (): Promise<readonly ActiveSession[]> => {\n return (await readStateRaw()).sessions;\n }, options);\n}\n\nexport async function readAndPruneActiveSessions(\n options?: StateAccessOptions,\n): Promise<StateReaderResult> {\n const result = await withFileLock(\n stateLockPath(),\n async (): Promise<PrunedState> => await readAndPruneLocked(options?.signal),\n options,\n );\n return { sessions: result.sessions, removed: result.removed };\n}\n\nexport function sessionKeyString(key: SessionKey): string {\n const base = `${key.region}:${key.org}:${key.space}:${key.app}`;\n if (key.process === undefined && key.instance === undefined) {\n return base;\n }\n const target = resolveNodeTarget(key);\n return `${base}:${target.process}:${target.instance.toString()}`;\n}\n\nfunction matchesSelectedNodePid(\n session: SessionKey,\n requestedNodePid: number | undefined,\n): boolean {\n if (requestedNodePid === undefined) {\n return true;\n }\n const remoteNodePid: unknown = Reflect.get(session, \"remoteNodePid\");\n return session.nodePid === requestedNodePid || remoteNodePid === requestedNodePid;\n}\n\nexport function matchesKey(session: SessionKey, key: SessionKey): boolean {\n const sessionTarget = resolveNodeTarget(session);\n const keyTarget = resolveNodeTarget(key);\n return (\n session.region === key.region &&\n session.org === key.org &&\n session.space === key.space &&\n session.app === key.app &&\n sessionTarget.process === keyTarget.process &&\n sessionTarget.instance === keyTarget.instance &&\n (key.apiEndpoint === undefined || session.apiEndpoint === key.apiEndpoint) &&\n matchesSelectedNodePid(session, keyTarget.nodePid)\n );\n}\n\nfunction matchesRegistrationTarget(\n session: ActiveSession,\n input: RegisterSessionInput,\n target: ReturnType<typeof resolveNodeTarget>,\n): boolean {\n return matchesKey(session, {\n region: input.region,\n org: input.org,\n space: input.space,\n app: input.app,\n process: target.process,\n instance: target.instance,\n apiEndpoint: input.apiEndpoint,\n });\n}\n\nexport interface RegisterSessionResult {\n readonly session: ActiveSession;\n readonly existing?: ActiveSession;\n}\n\nexport interface RegisterSessionInput extends SessionKey {\n readonly apiEndpoint: string;\n readonly preferredPort?: number;\n readonly remotePort?: number;\n readonly startupTimeoutMs?: number;\n readonly portProbe: (port: number) => Promise<boolean>;\n readonly sessionIdFactory?: () => string;\n readonly cfHomeForSession: (sessionId: string) => string;\n readonly basePort?: number;\n readonly maxPort?: number;\n readonly stateAccess?: StateAccessOptions;\n}\n\nasync function pickPort(\n preferred: number | undefined,\n reserved: ReadonlySet<number>,\n probe: (port: number) => Promise<boolean>,\n basePort: number,\n maxPort: number,\n): Promise<number> {\n const candidates = preferred === undefined\n ? []\n : [preferred];\n for (let port = basePort; port <= maxPort; port += 1) {\n if (port !== preferred) {\n candidates.push(port);\n }\n }\n for (const port of candidates) {\n if (!reserved.has(port) && await probe(port)) {\n return port;\n }\n }\n throw new CfDebuggerError(\n \"PORT_UNAVAILABLE\",\n `No free local port available in range ${basePort.toString()}–${maxPort.toString()}`,\n );\n}\n\ninterface RegistrationCandidate {\n readonly candidate?: number;\n readonly existing?: ActiveSession;\n}\n\nasync function selectRegistrationCandidate(\n input: RegisterSessionInput,\n target: ReturnType<typeof resolveNodeTarget>,\n excluded: ReadonlySet<number>,\n): Promise<RegistrationCandidate> {\n return await withFileLock(stateLockPath(), async (): Promise<RegistrationCandidate> => {\n const current = await readAndPruneLocked(input.stateAccess?.signal);\n const existing = current.sessions.find((session) =>\n matchesRegistrationTarget(session, input, target)\n );\n if (existing !== undefined) {\n return { existing };\n }\n const reserved = new Set([\n ...current.sessions.map((session) => session.localPort),\n ...excluded,\n ]);\n return {\n candidate: await pickPort(\n input.preferredPort,\n reserved,\n (): Promise<boolean> => Promise.resolve(true),\n input.basePort ?? DEFAULT_BASE_PORT,\n input.maxPort ?? DEFAULT_MAX_PORT,\n ),\n };\n }, input.stateAccess);\n}\n\nfunction validateSessionInput(input: RegisterSessionInput): void {\n const remotePort = input.remotePort ?? DEFAULT_NODE_INSPECTOR_PORT;\n if (!Number.isSafeInteger(remotePort) || remotePort <= 0 || remotePort > 65_535) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Remote inspector port must be from 1 to 65535.\");\n }\n if (\n input.startupTimeoutMs !== undefined &&\n (\n !Number.isSafeInteger(input.startupTimeoutMs) ||\n input.startupTimeoutMs <= 0 ||\n input.startupTimeoutMs > MAX_STARTUP_TIMEOUT_MS\n )\n ) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Persisted startup timeout is outside the supported range.\");\n }\n}\n\nfunction createRegisteredSession(\n input: RegisterSessionInput,\n target: ReturnType<typeof resolveNodeTarget>,\n localPort: number,\n controllerProcessIdentity: string | undefined,\n): ActiveSession {\n const sessionId = (input.sessionIdFactory ?? randomUUID)();\n if (!isSafeSessionId(sessionId)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Generated debugger session ID is invalid.\");\n }\n const cfHomeDir = input.cfHomeForSession(sessionId);\n if (!isAbsolute(cfHomeDir)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Debugger CF home must be an absolute path.\");\n }\n return {\n sessionId,\n pid: nodeProcess.pid,\n controllerPid: nodeProcess.pid,\n ...(controllerProcessIdentity === undefined ? {} : { controllerProcessIdentity }),\n hostname: getHostname(),\n region: input.region,\n org: input.org,\n space: input.space,\n app: input.app,\n process: target.process,\n instance: target.instance,\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n apiEndpoint: input.apiEndpoint,\n localPort,\n remotePort: input.remotePort ?? DEFAULT_NODE_INSPECTOR_PORT,\n cfHomeDir,\n startedAt: new Date().toISOString(),\n status: \"starting\",\n ...(input.startupTimeoutMs === undefined ? {} : { startupTimeoutMs: input.startupTimeoutMs }),\n };\n}\n\nasync function persistRegistration(\n input: RegisterSessionInput,\n target: ReturnType<typeof resolveNodeTarget>,\n candidate: number,\n controllerProcessIdentity: string | undefined,\n): Promise<RegisterSessionResult | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<RegisterSessionResult | undefined> => {\n const current = await readAndPruneLocked(input.stateAccess?.signal);\n const existing = current.sessions.find((session) =>\n matchesRegistrationTarget(session, input, target)\n );\n if (existing !== undefined) {\n return { session: existing, existing };\n }\n const reserved = current.sessions.some((session) => session.localPort === candidate);\n if (reserved || !(await input.portProbe(candidate))) {\n return undefined;\n }\n const session = createRegisteredSession(input, target, candidate, controllerProcessIdentity);\n await writeState({\n version: \"2\",\n sessions: [...current.persisted.sessions, session],\n });\n return { session };\n }, input.stateAccess);\n}\n\nexport async function registerNewSession(\n input: RegisterSessionInput,\n): Promise<RegisterSessionResult> {\n validateSessionInput(input);\n const target = resolveNodeTarget(input);\n const controllerIdentity = await readProcessIdentity(\n nodeProcess.pid,\n input.stateAccess?.signal,\n );\n const excluded = new Set<number>();\n const maximumAttempts = (input.maxPort ?? DEFAULT_MAX_PORT) -\n (input.basePort ?? DEFAULT_BASE_PORT) + 2;\n for (let attempt = 0; attempt < maximumAttempts; attempt += 1) {\n const selection = await selectRegistrationCandidate(input, target, excluded);\n if (selection.existing !== undefined) {\n return { session: selection.existing, existing: selection.existing };\n }\n const candidate = selection.candidate;\n if (candidate === undefined || !(await input.portProbe(candidate))) {\n if (candidate !== undefined) {\n excluded.add(candidate);\n }\n continue;\n }\n const result = await persistRegistration(input, target, candidate, controllerIdentity);\n if (result !== undefined) {\n return result;\n }\n excluded.add(candidate);\n }\n throw new CfDebuggerError(\"PORT_UNAVAILABLE\", \"No free local debugger port remained available.\");\n}\n\nfunction withoutMessage(session: ActiveSession): ActiveSession {\n const { message, ...clone } = session;\n void message;\n return clone;\n}\n\nfunction startupMutationBlocked(session: ActiveSession): boolean {\n return session.status === \"stopping\" || session.stopRequestedAt !== undefined;\n}\n\nfunction replaceSession(\n sessions: readonly ActiveSession[],\n replacement: ActiveSession,\n): readonly ActiveSession[] {\n return sessions.map((session) =>\n session.sessionId === replacement.sessionId ? replacement : session\n );\n}\n\nexport async function updateSessionStatus(\n sessionId: string,\n status: ActiveSession[\"status\"],\n message?: string,\n access?: StateAccessOptions,\n): Promise<ActiveSession | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (target === undefined || (status !== \"stopping\" && startupMutationBlocked(target))) {\n return target;\n }\n if (status === \"ready\" && target.tunnelPid === undefined) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n \"A debugger session cannot become ready before its tunnel PID is recorded.\",\n );\n }\n const base = withoutMessage(target);\n const next: ActiveSession = message === undefined\n ? { ...base, status }\n : { ...base, status, message };\n if (JSON.stringify(next) !== JSON.stringify(target)) {\n await writeState({ version: \"2\", sessions: replaceSession(raw.sessions, next) });\n }\n return next;\n }, access);\n}\n\nexport async function updateSessionPid(\n sessionId: string,\n pid: number,\n access?: StateAccessOptions,\n): Promise<ActiveSession | undefined> {\n if (!Number.isSafeInteger(pid) || pid <= 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Tunnel PID must be a positive safe integer.\");\n }\n const tunnelProcessIdentity = await readProcessIdentity(pid, access?.signal);\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (target === undefined || startupMutationBlocked(target)) {\n return target;\n }\n const { tunnelProcessIdentity: previousIdentity, ...base } = target;\n void previousIdentity;\n const next: ActiveSession = {\n ...base,\n pid,\n tunnelPid: pid,\n ...(tunnelProcessIdentity === undefined ? {} : { tunnelProcessIdentity }),\n };\n if (JSON.stringify(next) !== JSON.stringify(target)) {\n await writeState({ version: \"2\", sessions: replaceSession(raw.sessions, next) });\n }\n return next;\n }, access);\n}\n\nexport async function updateSessionRemoteNodePid(\n sessionId: string,\n remoteNodePid: number,\n access?: StateAccessOptions,\n): Promise<ActiveSession | undefined> {\n resolveNodeTarget({ nodePid: remoteNodePid });\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (target === undefined || startupMutationBlocked(target)) {\n return target;\n }\n const next: ActiveSession = { ...target, remoteNodePid };\n if (target.remoteNodePid !== remoteNodePid) {\n await writeState({ version: \"2\", sessions: replaceSession(raw.sessions, next) });\n }\n return next;\n }, access);\n}\n\nexport async function removeSession(sessionId: string): Promise<ActiveSession | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<ActiveSession | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (target === undefined) {\n return undefined;\n }\n await writeState({\n version: \"2\",\n sessions: raw.sessions.filter((session) => session.sessionId !== sessionId),\n });\n return target;\n });\n}\n\nexport interface SessionStopClaim {\n readonly session: ActiveSession;\n readonly previousStatus: ActiveSession[\"status\"];\n}\n\nexport async function requestSessionStop(sessionId: string): Promise<SessionStopClaim | undefined> {\n return await withFileLock(stateLockPath(), async (): Promise<SessionStopClaim | undefined> => {\n const raw = await readStateRaw();\n const target = raw.sessions.find((session) => session.sessionId === sessionId);\n if (target === undefined) {\n return undefined;\n }\n if (target.status === \"ready\") {\n return { session: target, previousStatus: target.status };\n }\n await writeSessionStopIntent(sessionId);\n if (target.stopRequestedAt !== undefined) {\n return { session: target, previousStatus: target.status };\n }\n const requested: ActiveSession = { ...target, stopRequestedAt: new Date().toISOString() };\n await writeState({\n version: \"2\",\n sessions: raw.sessions.map((session) =>\n session.sessionId === sessionId ? requested : session\n ),\n });\n return { session: requested, previousStatus: target.status };\n });\n}\n","export const DEFAULT_TUNNEL_READY_TIMEOUT_MS = 180_000;\nexport const DEFAULT_STARTUP_TIMEOUT_MS = 300_000;\nexport const MAX_STARTUP_TIMEOUT_MS = 1_800_000;\nexport const STARTUP_STALE_SLACK_MS = 60_000;\nexport const INSPECTOR_PROBE_ATTEMPT_TIMEOUT_MS = 2_500;\nexport const CHILD_SIGTERM_GRACE_MS = 2_000;\nexport const CHILD_SIGKILL_GRACE_MS = 1_000;\nexport const PID_TERMINATION_POLL_MS = 100;\n","import { execFile } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport nodeProcess from \"node:process\";\nimport { promisify } from \"node:util\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type ProcessIdentityVerdict = \"match\" | \"mismatch\" | \"unavailable\";\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const code: unknown = Reflect.get(error, \"code\");\n return typeof code === \"string\" ? code : undefined;\n}\n\nexport function parseLinuxProcessStartTime(statLine: string): string | undefined {\n const commandEnd = statLine.lastIndexOf(\")\");\n if (commandEnd < 0) {\n return undefined;\n }\n const fieldsAfterCommand = statLine.slice(commandEnd + 1).trim().split(/\\s+/);\n // The tail begins at proc(5) field 3, so field 22 (starttime) is index 19.\n const startTime = fieldsAfterCommand[19];\n return startTime !== undefined && /^\\d+$/.test(startTime) ? startTime : undefined;\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Process identity inspection was aborted.\");\n }\n}\n\nasync function linuxProcessIdentity(\n pid: number,\n signal: AbortSignal | undefined,\n): Promise<string | undefined> {\n try {\n const statLine = await readFile(`/proc/${pid.toString()}/stat`, {\n encoding: \"utf8\",\n ...(signal === undefined ? {} : { signal }),\n });\n const startTime = parseLinuxProcessStartTime(statLine);\n return startTime === undefined ? undefined : `linux:${startTime}`;\n } catch (error: unknown) {\n throwIfAborted(signal);\n if (errorCode(error) === \"ENOENT\") {\n return undefined;\n }\n return undefined;\n }\n}\n\nasync function darwinProcessIdentity(\n pid: number,\n signal: AbortSignal | undefined,\n): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"ps\", [\"-p\", pid.toString(), \"-o\", \"lstart=\"], {\n ...(signal === undefined ? {} : { signal }),\n timeout: 2_000,\n });\n const startedAt = stdout.trim();\n return startedAt.length === 0 ? undefined : `darwin:${startedAt}`;\n } catch {\n throwIfAborted(signal);\n return undefined;\n }\n}\n\nexport async function readProcessIdentity(\n pid: number,\n signal?: AbortSignal,\n): Promise<string | undefined> {\n throwIfAborted(signal);\n if (!Number.isSafeInteger(pid) || pid <= 0) {\n return undefined;\n }\n if (nodeProcess.platform === \"linux\") {\n return await linuxProcessIdentity(pid, signal);\n }\n if (nodeProcess.platform === \"darwin\") {\n return await darwinProcessIdentity(pid, signal);\n }\n // Windows intentionally retains PID-only compatibility: there is no cheap,\n // dependency-free process creation token available to this package.\n return undefined;\n}\n\nexport async function processIdentityMatches(\n pid: number,\n expected: string | undefined,\n signal?: AbortSignal,\n): Promise<boolean> {\n return await inspectProcessIdentity(pid, expected, signal) === \"match\";\n}\n\nexport async function inspectProcessIdentity(\n pid: number,\n expected: string | undefined,\n signal?: AbortSignal,\n): Promise<ProcessIdentityVerdict> {\n throwIfAborted(signal);\n if (expected === undefined) {\n return \"match\";\n }\n const current = await readProcessIdentity(pid, signal);\n if (current === undefined) {\n return \"unavailable\";\n }\n return current === expected ? \"match\" : \"mismatch\";\n}\n","import { randomUUID } from \"node:crypto\";\nimport { chmod, mkdir, open, readFile, stat, unlink } from \"node:fs/promises\";\nimport type { FileHandle } from \"node:fs/promises\";\nimport { hostname } from \"node:os\";\nimport { dirname } from \"node:path\";\nimport process from \"node:process\";\n\nimport {\n inspectProcessIdentity,\n readProcessIdentity,\n} from \"./debug-session/process-identity.js\";\nimport { CfDebuggerError } from \"./types.js\";\n\nconst DEFAULT_POLL_MS = 50;\nconst DEFAULT_STALE_MS = 60_000;\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst FOREIGN_HOST_STALE_MULTIPLIER = 10;\nconst LEGACY_SAME_HOST_STALE_MULTIPLIER = 24 * 60;\n\ninterface FileLock {\n readonly handle: FileHandle;\n readonly token: string;\n}\n\ninterface LockOwner {\n readonly hostname: string;\n readonly pid: number;\n readonly processIdentity?: string;\n readonly token: string;\n readonly version: \"1\";\n}\n\nfunction sleep(ms: number, signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(new CfDebuggerError(\"ABORTED\", \"State lock acquisition was aborted.\"));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new CfDebuggerError(\"ABORTED\", \"State lock acquisition was aborted.\"));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const code: unknown = Reflect.get(error, \"code\");\n return typeof code === \"string\" ? code : undefined;\n}\n\nfunction field(value: object, key: string): unknown {\n return Reflect.get(value, key);\n}\n\nfunction parseLockOwner(raw: string): LockOwner | undefined {\n let value: unknown;\n try {\n value = JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const lockHostname = field(value, \"hostname\");\n const pid = field(value, \"pid\");\n const token = field(value, \"token\");\n const version = field(value, \"version\");\n const processIdentity = field(value, \"processIdentity\");\n if (typeof lockHostname !== \"string\" || typeof pid !== \"number\" || !Number.isSafeInteger(pid) || pid <= 0) {\n return undefined;\n }\n if (typeof token !== \"string\" || version !== \"1\") {\n return undefined;\n }\n if (\n processIdentity !== undefined &&\n (typeof processIdentity !== \"string\" || processIdentity.length === 0)\n ) {\n return undefined;\n }\n return {\n hostname: lockHostname,\n pid,\n ...(processIdentity === undefined ? {} : { processIdentity }),\n token,\n version,\n };\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error: unknown) {\n return errorCode(error) !== \"ESRCH\";\n }\n}\n\nasync function readLockOwner(lockPath: string): Promise<LockOwner | undefined> {\n try {\n await chmod(lockPath, 0o600);\n return parseLockOwner(await readFile(lockPath, \"utf8\"));\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nasync function isStaleLock(lockPath: string, staleMs: number): Promise<boolean> {\n let modifiedAt: number;\n try {\n modifiedAt = (await stat(lockPath)).mtimeMs;\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return true;\n }\n throw error;\n }\n const owner = await readLockOwner(lockPath);\n const ageMs = Date.now() - modifiedAt;\n if (owner?.hostname === hostname()) {\n if (!isProcessAlive(owner.pid)) {\n return true;\n }\n if (owner.processIdentity !== undefined) {\n const identity = await inspectProcessIdentity(owner.pid, owner.processIdentity);\n if (identity === \"mismatch\") {\n return true;\n }\n if (identity === \"match\") {\n return false;\n }\n }\n // Locks pre-dating the identity field retain PID-only compatibility, but\n // cannot deadlock a shared home forever after PID reuse.\n return ageMs > staleMs * LEGACY_SAME_HOST_STALE_MULTIPLIER;\n }\n if (owner === undefined) {\n return ageMs > staleMs;\n }\n return ageMs > staleMs * FOREIGN_HOST_STALE_MULTIPLIER;\n}\n\nasync function reclaimAbandonedRecoveryLock(\n recoveryPath: string,\n staleMs: number,\n): Promise<void> {\n if (!(await isStaleLock(recoveryPath, staleMs))) {\n return;\n }\n const owner = await readLockOwner(recoveryPath);\n if (owner !== undefined) {\n // removeOwnedLock reads again, so a replacement lock with a new token survives this race.\n await removeOwnedLock(recoveryPath, owner.token);\n return;\n }\n await unlink(recoveryPath).catch((error: unknown) => {\n if (errorCode(error) !== \"ENOENT\") {\n throw error;\n }\n });\n}\n\nasync function reclaimStaleLock(lockPath: string, staleMs: number): Promise<boolean> {\n const recoveryPath = `${lockPath}.recovery`;\n let recoveryLock: FileLock;\n try {\n recoveryLock = await createFileLock(recoveryPath);\n } catch (error: unknown) {\n if (errorCode(error) === \"EEXIST\") {\n await reclaimAbandonedRecoveryLock(recoveryPath, staleMs);\n return false;\n }\n throw error;\n }\n try {\n if (!(await isStaleLock(lockPath, staleMs))) {\n return false;\n }\n try {\n await unlink(lockPath);\n } catch (error: unknown) {\n if (errorCode(error) !== \"ENOENT\") {\n throw error;\n }\n }\n return true;\n } finally {\n await releaseFileLock(recoveryPath, recoveryLock);\n }\n}\n\nasync function removeOwnedLock(lockPath: string, token: string): Promise<void> {\n const owner = await readLockOwner(lockPath);\n if (owner?.token !== token) {\n return;\n }\n await unlink(lockPath).catch((error: unknown) => {\n if (errorCode(error) !== \"ENOENT\") {\n throw error;\n }\n });\n}\n\nasync function createFileLock(lockPath: string): Promise<FileLock> {\n const processIdentity = await readProcessIdentity(process.pid);\n const handle = await open(lockPath, \"wx\", 0o600);\n const token = randomUUID();\n try {\n await handle.writeFile(`${JSON.stringify({\n hostname: hostname(),\n pid: process.pid,\n ...(processIdentity === undefined ? {} : { processIdentity }),\n token,\n version: \"1\",\n })}\\n`, \"utf8\");\n return { handle, token };\n } catch (error: unknown) {\n await handle.close();\n await unlink(lockPath).catch(() => false);\n throw error;\n }\n}\n\nasync function acquireFileLock(\n lockPath: string,\n timeoutMs: number,\n pollMs: number,\n staleMs: number,\n signal: AbortSignal | undefined,\n): Promise<FileLock> {\n const deadline = Date.now() + timeoutMs;\n const parentDir = dirname(lockPath);\n await mkdir(parentDir, { recursive: true, mode: 0o700 });\n await chmod(parentDir, 0o700);\n\n for (;;) {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"State lock acquisition was aborted.\");\n }\n try {\n return await createFileLock(lockPath);\n } catch (error: unknown) {\n if (errorCode(error) !== \"EEXIST\") {\n throw error;\n }\n }\n if (await reclaimStaleLock(lockPath, staleMs)) {\n continue;\n }\n if (Date.now() > deadline) {\n throw new CfDebuggerError(\n \"STATE_LOCK_TIMEOUT\",\n `Timed out acquiring debugger state lock at ${lockPath}. ` +\n \"Keep ~/.saptools on a local filesystem and retry.\",\n );\n }\n await sleep(pollMs, signal);\n }\n}\n\nasync function releaseFileLock(lockPath: string, lock: FileLock): Promise<void> {\n await lock.handle.close();\n await removeOwnedLock(lockPath, lock.token);\n}\n\nexport interface WithLockOptions {\n readonly pollMs?: number;\n readonly signal?: AbortSignal;\n readonly staleMs?: number;\n readonly timeoutMs?: number;\n}\n\nexport async function withFileLock<T>(\n lockPath: string,\n work: () => Promise<T>,\n options?: WithLockOptions,\n): Promise<T> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const pollMs = options?.pollMs ?? DEFAULT_POLL_MS;\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const lock = await acquireFileLock(\n lockPath,\n timeoutMs,\n pollMs,\n staleMs,\n options?.signal,\n );\n try {\n return await work();\n } finally {\n await releaseFileLock(lockPath, lock);\n }\n}\n","import { homedir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport { CfDebuggerError } from \"./types.js\";\n\nexport const SAPTOOLS_DIR_NAME = \".saptools\";\nexport const CF_DEBUGGER_STATE_FILENAME = \"cf-debugger-state-v2.json\";\nexport const CF_DEBUGGER_LOCK_FILENAME = \"cf-debugger-state-v2.lock\";\nexport const CF_DEBUGGER_HOMES_DIRNAME = \"cf-debugger-homes-v2\";\nexport const CF_DEBUGGER_STOP_INTENT_PREFIX = \"cf-debugger-stop-v2-\";\nconst SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\n\nexport function saptoolsDir(): string {\n return join(homedir(), SAPTOOLS_DIR_NAME);\n}\n\nexport function stateFilePath(): string {\n return join(saptoolsDir(), CF_DEBUGGER_STATE_FILENAME);\n}\n\nexport function stateLockPath(): string {\n return join(saptoolsDir(), CF_DEBUGGER_LOCK_FILENAME);\n}\n\nexport function sessionStopIntentPath(sessionId: string): string {\n if (!isSafeSessionId(sessionId)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Invalid debugger session ID.\");\n }\n return join(saptoolsDir(), `${CF_DEBUGGER_STOP_INTENT_PREFIX}${sessionId}.stop`);\n}\n\nexport function isSafeSessionId(sessionId: string): boolean {\n return SESSION_ID_PATTERN.test(sessionId);\n}\n\nexport function sessionCfHomeDir(sessionId: string): string {\n if (!isSafeSessionId(sessionId)) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", \"Invalid debugger session ID.\");\n }\n return join(saptoolsDir(), CF_DEBUGGER_HOMES_DIRNAME, sessionId);\n}\n\nexport function isOwnedSessionCfHomeDir(sessionId: string, candidate: string): boolean {\n if (!isSafeSessionId(sessionId) || !isAbsolute(candidate)) {\n return false;\n }\n return candidate === sessionCfHomeDir(sessionId);\n}\n","import { isAbsolute } from \"node:path\";\n\nimport { resolveNodeTarget } from \"../cloud-foundry/node-process.js\";\nimport { MAX_STARTUP_TIMEOUT_MS } from \"../debug-session/constants.js\";\nimport { isSafeSessionId } from \"../paths.js\";\nimport type { ActiveSession, SessionStatus, StateFile } from \"../types.js\";\n\nconst INVALID_SESSION = new Error(\"Invalid persisted debugger session\");\nconst VALID_STATUSES: ReadonlySet<string> = new Set<SessionStatus>([\n \"starting\",\n \"logging-in\",\n \"targeting\",\n \"ssh-enabling\",\n \"ssh-restarting\",\n \"signaling\",\n \"tunneling\",\n \"ready\",\n \"stopping\",\n \"stopped\",\n \"error\",\n]);\n\nexport interface StateDecodeSuccess {\n readonly kind: \"decoded\";\n readonly state: StateFile;\n readonly dropped: readonly string[];\n}\n\nexport interface StateDecodeFailure {\n readonly kind: \"invalid-file\";\n readonly reason: string;\n}\n\nexport type StateDecodeResult = StateDecodeFailure | StateDecodeSuccess;\n\nfunction field(value: object, key: string): unknown {\n return Reflect.get(value, key);\n}\n\nfunction requireString(value: object, key: string): string {\n const candidate = field(value, key);\n if (typeof candidate !== \"string\" || candidate.length === 0) {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction optionalString(value: object, key: string): string | undefined {\n const candidate = field(value, key);\n if (candidate === undefined) {\n return undefined;\n }\n if (typeof candidate !== \"string\") {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction optionalNonEmptyString(value: object, key: string): string | undefined {\n const candidate = optionalString(value, key);\n if (candidate?.length === 0) {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction requireInteger(\n value: object,\n key: string,\n minimum: number,\n maximum: number,\n): number {\n const candidate = field(value, key);\n if (\n typeof candidate !== \"number\" ||\n !Number.isSafeInteger(candidate) ||\n candidate < minimum ||\n candidate > maximum\n ) {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction optionalInteger(\n value: object,\n key: string,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\n): number | undefined {\n const candidate = field(value, key);\n if (candidate === undefined) {\n return undefined;\n }\n if (\n typeof candidate !== \"number\" ||\n !Number.isSafeInteger(candidate) ||\n candidate < minimum ||\n candidate > maximum\n ) {\n throw INVALID_SESSION;\n }\n return candidate;\n}\n\nfunction requireSessionId(value: object): string {\n const sessionId = requireString(value, \"sessionId\");\n if (!isSafeSessionId(sessionId)) {\n throw INVALID_SESSION;\n }\n return sessionId;\n}\n\nfunction requireAbsolutePath(value: object, key: string): string {\n const path = requireString(value, key);\n if (!isAbsolute(path)) {\n throw INVALID_SESSION;\n }\n return path;\n}\n\nfunction requireTimestamp(value: object): string {\n const timestamp = requireString(value, \"startedAt\");\n if (Number.isNaN(Date.parse(timestamp))) {\n throw INVALID_SESSION;\n }\n return timestamp;\n}\n\nfunction optionalTimestamp(value: object, key: string): string | undefined {\n const timestamp = optionalString(value, key);\n if (timestamp !== undefined && Number.isNaN(Date.parse(timestamp))) {\n throw INVALID_SESSION;\n }\n return timestamp;\n}\n\nfunction isSessionStatus(value: string): value is SessionStatus {\n return VALID_STATUSES.has(value);\n}\n\nfunction requireStatus(value: object): SessionStatus {\n const status = requireString(value, \"status\");\n if (!isSessionStatus(status)) {\n throw INVALID_SESSION;\n }\n return status;\n}\n\nfunction optionalFields(value: object): Pick<\n ActiveSession,\n \"controllerProcessIdentity\" | \"startupTimeoutMs\" | \"tunnelProcessIdentity\"\n> {\n const controllerProcessIdentity = optionalNonEmptyString(value, \"controllerProcessIdentity\");\n const tunnelProcessIdentity = optionalNonEmptyString(value, \"tunnelProcessIdentity\");\n const startupTimeoutMs = optionalInteger(value, \"startupTimeoutMs\", 1, MAX_STARTUP_TIMEOUT_MS);\n return {\n ...(controllerProcessIdentity === undefined ? {} : { controllerProcessIdentity }),\n ...(tunnelProcessIdentity === undefined ? {} : { tunnelProcessIdentity }),\n ...(startupTimeoutMs === undefined ? {} : { startupTimeoutMs }),\n };\n}\n\nfunction decodeTarget(value: object): ReturnType<typeof resolveNodeTarget> {\n const nodePid = optionalInteger(value, \"nodePid\", 1);\n return resolveNodeTarget({\n process: requireString(value, \"process\"),\n instance: requireInteger(value, \"instance\", 0, Number.MAX_SAFE_INTEGER),\n ...(nodePid === undefined ? {} : { nodePid }),\n });\n}\n\nexport function decodeSession(value: unknown): ActiveSession | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n try {\n const target = decodeTarget(value);\n const pid = requireInteger(value, \"pid\", 1, Number.MAX_SAFE_INTEGER);\n const tunnelPid = optionalInteger(value, \"tunnelPid\", 1);\n const controllerPid = optionalInteger(value, \"controllerPid\", 1) ?? pid;\n const remoteNodePid = optionalInteger(value, \"remoteNodePid\", 1);\n const stopRequestedAt = optionalTimestamp(value, \"stopRequestedAt\");\n const message = optionalString(value, \"message\");\n const status = requireStatus(value);\n if (pid !== (tunnelPid ?? controllerPid) || (status === \"ready\" && tunnelPid === undefined)) {\n throw INVALID_SESSION;\n }\n return {\n sessionId: requireSessionId(value),\n pid,\n controllerPid,\n ...optionalFields(value),\n ...(tunnelPid === undefined ? {} : { tunnelPid }),\n hostname: requireString(value, \"hostname\"),\n region: requireString(value, \"region\"),\n org: requireString(value, \"org\"),\n space: requireString(value, \"space\"),\n app: requireString(value, \"app\"),\n process: target.process,\n instance: target.instance,\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n apiEndpoint: requireString(value, \"apiEndpoint\"),\n localPort: requireInteger(value, \"localPort\", 1, 65_535),\n remotePort: requireInteger(value, \"remotePort\", 1, 65_535),\n cfHomeDir: requireAbsolutePath(value, \"cfHomeDir\"),\n startedAt: requireTimestamp(value),\n status,\n ...(remoteNodePid === undefined ? {} : { remoteNodePid }),\n ...(stopRequestedAt === undefined ? {} : { stopRequestedAt }),\n ...(message === undefined ? {} : { message }),\n };\n } catch {\n return undefined;\n }\n}\n\nfunction duplicateSessionIds(sessions: readonly ActiveSession[]): ReadonlySet<string> {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const session of sessions) {\n if (seen.has(session.sessionId)) {\n duplicates.add(session.sessionId);\n }\n seen.add(session.sessionId);\n }\n return duplicates;\n}\n\nexport function decodeStateFileDetailed(value: unknown): StateDecodeResult {\n if (typeof value !== \"object\" || value === null) {\n return { kind: \"invalid-file\", reason: \"root is not an object\" };\n }\n if (field(value, \"version\") !== \"2\") {\n return { kind: \"invalid-file\", reason: \"unsupported or missing version\" };\n }\n const rawSessions = field(value, \"sessions\");\n if (!Array.isArray(rawSessions)) {\n return { kind: \"invalid-file\", reason: \"sessions is not an array\" };\n }\n const decoded = rawSessions.map((raw) => decodeSession(raw));\n const valid = decoded.filter((session): session is ActiveSession => session !== undefined);\n const duplicates = duplicateSessionIds(valid);\n const sessions = valid.filter((session) => !duplicates.has(session.sessionId));\n const dropped = decoded.flatMap((session, index): readonly string[] => {\n if (session === undefined) {\n return [`session[${index.toString()}]: invalid entry`];\n }\n return duplicates.has(session.sessionId)\n ? [`session[${index.toString()}]: duplicate sessionId ${session.sessionId}`]\n : [];\n });\n return {\n kind: \"decoded\",\n state: { version: \"2\", sessions },\n dropped,\n };\n}\n\nexport function decodeStateFile(value: unknown): StateFile | undefined {\n const result = decodeStateFileDetailed(value);\n return result.kind === \"decoded\" ? result.state : undefined;\n}\n","import { hostname as getHostname } from \"node:os\";\nimport nodeProcess from \"node:process\";\n\nimport {\n MAX_STARTUP_TIMEOUT_MS,\n STARTUP_STALE_SLACK_MS,\n} from \"../debug-session/constants.js\";\nimport { inspectProcessIdentity } from \"../debug-session/process-identity.js\";\nimport type { ProcessIdentityVerdict } from \"../debug-session/process-identity.js\";\nimport { inspectPortOwnership } from \"../port.js\";\nimport type { ActiveSession } from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const code: unknown = Reflect.get(error, \"code\");\n return typeof code === \"string\" ? code : undefined;\n}\n\nexport function isPidAlive(pid: number): boolean {\n try {\n nodeProcess.kill(pid, 0);\n return true;\n } catch (error: unknown) {\n return errorCode(error) !== \"ESRCH\";\n }\n}\n\nexport function isProcessGroupAlive(pid: number): boolean {\n return nodeProcess.platform !== \"win32\" && isPidAlive(-pid);\n}\n\nexport function isPidOrGroupAlive(pid: number): boolean {\n return isPidAlive(pid) || isProcessGroupAlive(pid);\n}\n\nexport type SessionHealthStatus = \"healthy\" | \"stale\" | \"unverified\";\n\nexport interface SessionHealthVerdict {\n readonly status: SessionHealthStatus;\n readonly reason: string;\n}\n\nfunction startupAgeLimit(session: ActiveSession): number {\n return (session.startupTimeoutMs ?? MAX_STARTUP_TIMEOUT_MS) + STARTUP_STALE_SLACK_MS;\n}\n\nfunction startupExpired(session: ActiveSession): boolean {\n const startedAt = Date.parse(session.startedAt);\n return Number.isNaN(startedAt) || Date.now() - startedAt > startupAgeLimit(session);\n}\n\ntype RecordedProcessVerdict = \"dead\" | ProcessIdentityVerdict;\n\nasync function inspectRecordedProcess(\n pid: number,\n identity: string | undefined,\n signal?: AbortSignal,\n): Promise<RecordedProcessVerdict> {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Session health inspection was aborted.\");\n }\n if (!isPidAlive(pid)) {\n return \"dead\";\n }\n return await inspectProcessIdentity(pid, identity, signal);\n}\n\nasync function readySessionHealth(\n session: ActiveSession,\n signal?: AbortSignal,\n): Promise<SessionHealthVerdict> {\n const tunnelPid = session.tunnelPid;\n if (tunnelPid === undefined) {\n return { status: \"stale\", reason: \"recorded tunnel PID is missing\" };\n }\n const processVerdict = await inspectRecordedProcess(\n tunnelPid,\n session.tunnelProcessIdentity,\n signal,\n );\n if (processVerdict === \"dead\" && isProcessGroupAlive(tunnelPid)) {\n return {\n status: \"unverified\",\n reason: \"tunnel leader exited while its process group is still alive\",\n };\n }\n if (processVerdict === \"dead\" || processVerdict === \"mismatch\") {\n return { status: \"stale\", reason: \"recorded tunnel process is gone or was reused\" };\n }\n if (processVerdict === \"unavailable\") {\n return { status: \"unverified\", reason: \"recorded tunnel identity could not be inspected\" };\n }\n const ownership = await inspectPortOwnership(session.localPort, tunnelPid, signal);\n if (ownership.status === \"owned\") {\n return { status: \"healthy\", reason: \"recorded tunnel owns the local port\" };\n }\n if (ownership.status === \"unverified\") {\n return { status: \"unverified\", reason: ownership.reason };\n }\n return {\n status: \"unverified\",\n reason: ownership.status === \"not-owned\"\n ? `recorded live tunnel no longer owns the local port; observed PID(s) ${ownership.pids.join(\", \")}`\n : \"recorded live tunnel no longer has a listening local port\",\n };\n}\n\nasync function startingSessionHealth(\n session: ActiveSession,\n signal?: AbortSignal,\n): Promise<SessionHealthVerdict> {\n if (startupExpired(session)) {\n if (session.tunnelPid !== undefined) {\n return await readySessionHealth(session, signal);\n }\n return { status: \"stale\", reason: \"startup exceeded its maximum supported age\" };\n }\n const controllerPid = session.controllerPid ?? session.pid;\n const processVerdict = await inspectRecordedProcess(\n controllerPid,\n session.controllerProcessIdentity,\n signal,\n );\n if (processVerdict === \"match\") {\n return { status: \"healthy\", reason: \"startup controller identity matches\" };\n }\n if (processVerdict === \"unavailable\") {\n return { status: \"unverified\", reason: \"startup controller identity could not be inspected\" };\n }\n if (session.tunnelPid === undefined) {\n return { status: \"stale\", reason: \"startup controller is gone or was reused\" };\n }\n return await readySessionHealth(session, signal);\n}\n\nexport async function inspectSessionHealth(\n session: ActiveSession,\n host = getHostname(),\n signal?: AbortSignal,\n): Promise<SessionHealthVerdict> {\n if (session.hostname !== host) {\n return { status: \"stale\", reason: \"session belongs to another host\" };\n }\n return session.status === \"ready\"\n ? await readySessionHealth(session, signal)\n : await startingSessionHealth(session, signal);\n}\n\nexport async function filterStaleSessions(\n sessions: readonly ActiveSession[],\n signal?: AbortSignal,\n): Promise<readonly ActiveSession[]> {\n const host = getHostname();\n const verdicts = await Promise.all(\n sessions.map(async (session): Promise<readonly [ActiveSession, SessionHealthVerdict]> => [\n session,\n await inspectSessionHealth(session, host, signal),\n ]),\n );\n return verdicts\n .filter(([, verdict]) => verdict.status !== \"stale\")\n .map(([session]) => session);\n}\n","import { execFile } from \"node:child_process\";\nimport { readdir, readFile, readlink } from \"node:fs/promises\";\nimport { get as httpGet, type IncomingMessage } from \"node:http\";\nimport { createConnection, createServer } from \"node:net\";\nimport { promisify } from \"node:util\";\n\nimport { CfDebuggerError } from \"../types.js\";\n\nconst execFileAsync = promisify(execFile);\nconst PROBE_INTERVAL_MS = 250;\nconst INSPECTOR_ATTEMPT_TIMEOUT_MS = 2_500;\nconst MAX_INSPECTOR_RESPONSE_BYTES = 64 * 1_024;\nconst OWNER_COMMAND_TIMEOUT_MS = 5_000;\n\ninterface PidCommandResult {\n readonly available: boolean;\n readonly pids: readonly number[];\n readonly reason?: string;\n}\n\ninterface ProcSocketResult extends PidCommandResult {\n readonly listenerFound: boolean;\n}\n\nexport type ListeningProcessInspection =\n | { readonly status: \"found\"; readonly pids: readonly number[] }\n | { readonly status: \"not-listening\"; readonly pids: readonly number[] }\n | { readonly status: \"unverified\"; readonly reason: string };\n\nexport type PortOwnershipInspection =\n | { readonly status: \"owned\"; readonly pids: readonly number[] }\n | { readonly status: \"not-owned\"; readonly pids: readonly number[] }\n | { readonly status: \"not-listening\"; readonly pids: readonly number[] }\n | { readonly status: \"unverified\"; readonly reason: string };\n\nexport type InspectorReadinessResult =\n | { readonly status: \"ready\" }\n | { readonly status: \"unreachable\" };\n\nfunction sortedUniquePids(pids: Iterable<number>): readonly number[] {\n return [...new Set(pids)].sort((left, right) => left - right);\n}\n\nfunction parseAddressPort(address: string): number | undefined {\n const separator = address.lastIndexOf(\":\");\n const portText = separator >= 0 ? address.slice(separator + 1) : \"\";\n if (!/^\\d+$/.test(portText)) {\n return undefined;\n }\n return Number.parseInt(portText, 10);\n}\n\nexport function parseWindowsNetstatListeningPids(\n output: string,\n port: number,\n): readonly number[] {\n const pids = new Set<number>();\n for (const line of output.split(/\\r?\\n/)) {\n const fields = line.trim().split(/\\s+/);\n const protocol = fields[0]?.toUpperCase();\n const localAddress = fields[1];\n const state = fields[3]?.toUpperCase();\n const pidText = fields[4];\n if (\n protocol !== \"TCP\"\n || localAddress === undefined\n || state !== \"LISTENING\"\n || pidText === undefined\n || parseAddressPort(localAddress) !== port\n ) {\n continue;\n }\n const pid = Number.parseInt(pidText, 10);\n if (Number.isSafeInteger(pid) && pid > 0) {\n pids.add(pid);\n }\n }\n return sortedUniquePids(pids);\n}\n\nfunction errorCode(error: unknown): string | number | undefined {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) {\n return undefined;\n }\n const code = error.code;\n return typeof code === \"string\" || typeof code === \"number\" ? code : undefined;\n}\n\nfunction errorStderr(error: unknown): string {\n if (typeof error !== \"object\" || error === null || !(\"stderr\" in error)) {\n return \"\";\n }\n return typeof error.stderr === \"string\" ? error.stderr.trim() : \"\";\n}\n\nasync function findListeningPidsWithNetstat(\n port: number,\n signal?: AbortSignal,\n): Promise<PidCommandResult> {\n try {\n const { stdout } = await execFileAsync(\"netstat\", [\"-ano\"], {\n ...(signal === undefined ? {} : { signal }),\n timeout: OWNER_COMMAND_TIMEOUT_MS,\n });\n return {\n available: true,\n pids: parseWindowsNetstatListeningPids(stdout, port),\n };\n } catch (error: unknown) {\n throwIfAborted(signal);\n return {\n available: false,\n pids: [],\n reason: `Unable to inspect listening ports with netstat (${String(errorCode(error) ?? \"unknown error\")}).`,\n };\n }\n}\n\nasync function findListeningPidsWithLsof(\n port: number,\n signal?: AbortSignal,\n): Promise<PidCommandResult> {\n try {\n const { stdout } = await execFileAsync(\"lsof\", [\n \"-nP\",\n \"-t\",\n \"-i\",\n `tcp:${port.toString()}`,\n \"-sTCP:LISTEN\",\n ], {\n ...(signal === undefined ? {} : { signal }),\n timeout: OWNER_COMMAND_TIMEOUT_MS,\n });\n const pids = stdout\n .trim()\n .split(\"\\n\")\n .filter((line) => line.length > 0)\n .map((line) => Number.parseInt(line, 10))\n .filter((pid) => Number.isSafeInteger(pid) && pid > 0);\n return { available: true, pids: sortedUniquePids(pids) };\n } catch (error: unknown) {\n throwIfAborted(signal);\n if (errorCode(error) === 1 && errorStderr(error).length === 0) {\n return { available: true, pids: [] };\n }\n const missing = errorCode(error) === \"ENOENT\";\n return {\n available: false,\n pids: [],\n reason: missing\n ? \"The lsof command is required to verify tunnel ownership on this platform.\"\n : `lsof could not inspect the listening port (${String(errorCode(error) ?? \"unknown error\")}).`,\n };\n }\n}\n\nasync function collectListeningSocketInodes(\n path: string,\n port: number,\n inodes: Set<string>,\n): Promise<boolean> {\n try {\n const content = await readFile(path, \"utf8\");\n for (const line of content.split(\"\\n\").slice(1)) {\n const fields = line.trim().split(/\\s+/);\n const localAddress = fields[1];\n const state = fields[3];\n const inode = fields[9];\n if (localAddress === undefined || state === undefined || inode === undefined) {\n continue;\n }\n const localPort = Number.parseInt(localAddress.split(\":\")[1] ?? \"\", 16);\n if (localPort === port && state === \"0A\") {\n inodes.add(inode);\n }\n }\n return true;\n } catch {\n return false;\n }\n}\n\nasync function findListeningSocketInodesWithProc(\n port: number,\n): Promise<{ readonly available: boolean; readonly inodes: ReadonlySet<string> }> {\n const inodes = new Set<string>();\n const tcpAvailable = await collectListeningSocketInodes(\"/proc/net/tcp\", port, inodes);\n const tcp6Available = await collectListeningSocketInodes(\"/proc/net/tcp6\", port, inodes);\n return { available: tcpAvailable || tcp6Available, inodes };\n}\n\nasync function processHasSocketInode(pid: string, inodes: ReadonlySet<string>): Promise<boolean> {\n try {\n const descriptors = await readdir(`/proc/${pid}/fd`);\n for (const descriptor of descriptors) {\n try {\n const link = await readlink(`/proc/${pid}/fd/${descriptor}`);\n const match = /^socket:\\[(\\d+)\\]$/.exec(link);\n if (match?.[1] !== undefined && inodes.has(match[1])) {\n return true;\n }\n } catch {\n // The process may close descriptors while we scan them.\n }\n }\n } catch {\n // The process may exit, or permissions may prevent fd inspection.\n }\n return false;\n}\n\nasync function findListeningPidsWithProc(\n port: number,\n signal?: AbortSignal,\n): Promise<ProcSocketResult> {\n throwIfAborted(signal);\n const socketResult = await findListeningSocketInodesWithProc(port);\n if (!socketResult.available) {\n return {\n available: false,\n listenerFound: false,\n pids: [],\n reason: \"The /proc socket tables are unavailable.\",\n };\n }\n if (socketResult.inodes.size === 0) {\n return { available: true, listenerFound: false, pids: [] };\n }\n try {\n const entries = await readdir(\"/proc\", { withFileTypes: true });\n const pids = new Set<number>();\n for (const entry of entries) {\n throwIfAborted(signal);\n if (\n entry.isDirectory()\n && /^\\d+$/.test(entry.name)\n && await processHasSocketInode(entry.name, socketResult.inodes)\n ) {\n pids.add(Number.parseInt(entry.name, 10));\n }\n }\n return {\n available: true,\n listenerFound: true,\n pids: sortedUniquePids(pids),\n };\n } catch {\n throwIfAborted(signal);\n return {\n available: false,\n listenerFound: true,\n pids: [],\n reason: \"A listener exists, but its owner could not be inspected through /proc.\",\n };\n }\n}\n\nfunction inspectionFromPids(pids: readonly number[]): ListeningProcessInspection {\n return pids.length > 0\n ? { status: \"found\", pids }\n : { status: \"not-listening\", pids };\n}\n\nexport async function inspectListeningProcesses(\n port: number,\n signal?: AbortSignal,\n): Promise<ListeningProcessInspection> {\n throwIfAborted(signal);\n if (process.platform === \"win32\") {\n const netstat = await findListeningPidsWithNetstat(port, signal);\n return netstat.available\n ? inspectionFromPids(netstat.pids)\n : { status: \"unverified\", reason: netstat.reason ?? \"netstat is unavailable.\" };\n }\n\n const lsof = await findListeningPidsWithLsof(port, signal);\n if (lsof.pids.length > 0) {\n return { status: \"found\", pids: lsof.pids };\n }\n if (process.platform === \"darwin\") {\n return lsof.available\n ? { status: \"not-listening\", pids: [] }\n : { status: \"unverified\", reason: lsof.reason ?? \"lsof is unavailable.\" };\n }\n\n const proc = await findListeningPidsWithProc(port, signal);\n if (proc.pids.length > 0) {\n return { status: \"found\", pids: proc.pids };\n }\n if (proc.listenerFound || (!proc.available && !lsof.available)) {\n return {\n status: \"unverified\",\n reason: proc.reason ?? lsof.reason ?? \"The listener owner could not be verified.\",\n };\n }\n return { status: \"not-listening\", pids: [] };\n}\n\nexport async function findListeningProcessIds(\n port: number,\n signal?: AbortSignal,\n): Promise<readonly number[]> {\n const inspection = await inspectListeningProcesses(port, signal);\n return inspection.status === \"found\" ? inspection.pids : [];\n}\n\nexport function classifyPortOwnership(\n pids: readonly number[],\n expectedPid: number,\n): PortOwnershipInspection {\n return pids.includes(expectedPid)\n ? { status: \"owned\", pids }\n : { status: \"not-owned\", pids };\n}\n\nexport async function inspectPortOwnership(\n port: number,\n expectedPid: number,\n signal?: AbortSignal,\n): Promise<PortOwnershipInspection> {\n const inspection = await inspectListeningProcesses(port, signal);\n if (inspection.status === \"unverified\") {\n return inspection;\n }\n if (inspection.status === \"not-listening\") {\n return inspection;\n }\n return classifyPortOwnership(inspection.pids, expectedPid);\n}\n\nexport async function isPortFree(\n port: number,\n signal?: AbortSignal,\n): Promise<boolean> {\n throwIfAborted(signal);\n return await new Promise<boolean>((resolve, reject) => {\n const server = createServer();\n let settled = false;\n const finish = (available: boolean): void => {\n if (settled) {\n return;\n }\n settled = true;\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(available);\n };\n const onAbort = (): void => {\n if (settled) {\n return;\n }\n settled = true;\n if (server.listening) {\n server.close();\n }\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n };\n server.once(\"error\", () => {\n finish(false);\n });\n server.once(\"listening\", () => {\n server.close(() => {\n finish(true);\n });\n });\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (signal?.aborted) {\n onAbort();\n return;\n }\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport async function isPortListening(port: number, timeoutMs = 200): Promise<boolean> {\n return await new Promise<boolean>((resolve) => {\n const socket = createConnection({ port, host: \"127.0.0.1\" });\n socket.setTimeout(timeoutMs);\n socket.once(\"connect\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.once(\"error\", () => {\n socket.destroy();\n resolve(false);\n });\n socket.once(\"timeout\", () => {\n socket.destroy();\n resolve(false);\n });\n });\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n}\n\nfunction waitForNextProbe(delayMs: number, signal: AbortSignal | undefined): Promise<void> {\n throwIfAborted(signal);\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, delayMs);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (signal?.aborted) {\n onAbort();\n }\n });\n}\n\nexport async function probeTunnelReady(\n port: number,\n timeoutMs: number,\n signal?: AbortSignal,\n): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n throwIfAborted(signal);\n\n while (Date.now() < deadline) {\n const remainingMs = deadline - Date.now();\n if (await isPortListening(port, Math.min(200, remainingMs))) {\n return true;\n }\n const waitMs = Math.min(PROBE_INTERVAL_MS, Math.max(0, deadline - Date.now()));\n if (waitMs > 0) {\n await waitForNextProbe(waitMs, signal);\n }\n }\n\n throwIfAborted(signal);\n return false;\n}\n\nfunction parseJson(body: string): unknown {\n return JSON.parse(body) as unknown;\n}\n\nfunction isUnknownRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isUnknownArray(value: unknown): value is readonly unknown[] {\n return Array.isArray(value);\n}\n\nfunction hasAttachableInspectorTarget(body: string): boolean {\n let parsed: unknown;\n try {\n parsed = parseJson(body);\n } catch {\n return false;\n }\n if (!isUnknownArray(parsed) || parsed.length === 0) {\n return false;\n }\n const first = parsed[0];\n if (!isUnknownRecord(first)) {\n return false;\n }\n const candidate = first[\"webSocketDebuggerUrl\"];\n if (typeof candidate !== \"string\") {\n return false;\n }\n try {\n const url = new URL(candidate);\n return (url.protocol === \"ws:\" || url.protocol === \"wss:\") && url.hostname.length > 0;\n } catch {\n return false;\n }\n}\n\nfunction readInspectorResponse(\n response: IncomingMessage,\n finish: (ready: boolean) => void,\n): void {\n if (response.statusCode !== 200) {\n response.destroy();\n finish(false);\n return;\n }\n const chunks: Buffer[] = [];\n let totalBytes = 0;\n response.on(\"data\", (chunk: Buffer) => {\n totalBytes += chunk.length;\n if (totalBytes > MAX_INSPECTOR_RESPONSE_BYTES) {\n response.destroy();\n finish(false);\n return;\n }\n chunks.push(chunk);\n });\n response.once(\"end\", () => {\n finish(hasAttachableInspectorTarget(Buffer.concat(chunks).toString(\"utf8\")));\n });\n response.once(\"error\", () => {\n finish(false);\n });\n}\n\nfunction probeInspectorAttempt(\n port: number,\n timeoutMs: number,\n signal: AbortSignal | undefined,\n): Promise<boolean> {\n throwIfAborted(signal);\n return new Promise<boolean>((resolve, reject) => {\n const state: {\n settled: boolean;\n removeAbortListener?: () => void;\n timer?: NodeJS.Timeout;\n } = { settled: false };\n const finish = (ready: boolean): void => {\n if (!state.settled) {\n state.settled = true;\n clearTimeout(state.timer);\n state.removeAbortListener?.();\n resolve(ready);\n }\n };\n const request = httpGet({ host: \"127.0.0.1\", port, path: \"/json/list\" }, (response) => {\n readInspectorResponse(response, finish);\n });\n const onAbort = (): void => {\n request.destroy();\n if (!state.settled) {\n state.settled = true;\n clearTimeout(state.timer);\n state.removeAbortListener?.();\n reject(new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\"));\n }\n };\n state.removeAbortListener = (): void => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (signal?.aborted) {\n onAbort();\n return;\n }\n state.timer = setTimeout(() => {\n request.destroy();\n finish(false);\n }, timeoutMs);\n request.once(\"error\", () => {\n if (signal?.aborted) {\n onAbort();\n return;\n }\n finish(false);\n });\n });\n}\n\nexport async function probeInspectorReady(\n port: number,\n timeoutMs: number,\n signal?: AbortSignal,\n): Promise<InspectorReadinessResult> {\n const deadline = Date.now() + timeoutMs;\n throwIfAborted(signal);\n\n while (Date.now() < deadline) {\n const remainingMs = deadline - Date.now();\n const attemptTimeoutMs = Math.max(\n 1,\n Math.min(INSPECTOR_ATTEMPT_TIMEOUT_MS, remainingMs),\n );\n if (await probeInspectorAttempt(port, attemptTimeoutMs, signal)) {\n return { status: \"ready\" };\n }\n const waitMs = Math.min(PROBE_INTERVAL_MS, Math.max(0, deadline - Date.now()));\n if (waitMs > 0) {\n await waitForNextProbe(waitMs, signal);\n }\n }\n\n throwIfAborted(signal);\n return { status: \"unreachable\" };\n}\n\nexport async function findListeningProcessId(port: number): Promise<number | undefined> {\n const pids = await findListeningProcessIds(port);\n return pids[0];\n}\n","import { access, chmod, mkdir, unlink, writeFile } from \"node:fs/promises\";\n\nimport { saptoolsDir, sessionStopIntentPath } from \"../paths.js\";\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const code: unknown = Reflect.get(error, \"code\");\n return typeof code === \"string\" ? code : undefined;\n}\n\nexport async function writeSessionStopIntent(sessionId: string): Promise<void> {\n const directory = saptoolsDir();\n await mkdir(directory, { recursive: true, mode: 0o700 });\n await chmod(directory, 0o700);\n try {\n await writeFile(sessionStopIntentPath(sessionId), \"\", {\n encoding: \"utf8\",\n flag: \"wx\",\n mode: 0o600,\n });\n } catch (error: unknown) {\n if (errorCode(error) !== \"EEXIST\") {\n throw error;\n }\n }\n}\n\nexport async function hasSessionStopIntent(sessionId: string): Promise<boolean> {\n try {\n await access(sessionStopIntentPath(sessionId));\n return true;\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nexport async function clearSessionStopIntent(sessionId: string): Promise<void> {\n await unlink(sessionStopIntentPath(sessionId)).catch((error: unknown) => {\n if (errorCode(error) !== \"ENOENT\") {\n throw error;\n }\n });\n}\n","import { CfDebuggerError } from \"./types.js\";\n\nexport const CLEANUP_FAILURE_EXIT_CODE = 70;\n\nexport class CleanupFailureError extends AggregateError {\n public constructor(errors: readonly unknown[], cause: unknown) {\n super(\n errors,\n \"Debugger startup failed and resource cleanup was incomplete\",\n { cause },\n );\n this.name = \"CleanupFailureError\";\n }\n}\n\nfunction requestedCliExitCode(error: unknown): number | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const value: unknown = Reflect.get(error, \"cliExitCode\");\n return value === 130 || value === 143 ? value : undefined;\n}\n\nexport function hasTunnelTerminationFailure(error: unknown): boolean {\n if (error instanceof CfDebuggerError) {\n return error.code === \"TUNNEL_TERMINATION_FAILED\";\n }\n return error instanceof AggregateError &&\n error.errors.some((nested: unknown) => hasTunnelTerminationFailure(nested));\n}\n\nfunction hasCleanupFailure(error: unknown): boolean {\n return error instanceof CleanupFailureError ||\n hasTunnelTerminationFailure(error);\n}\n\nexport function cliErrorExitCode(error: unknown): number {\n const requested = requestedCliExitCode(error);\n if (requested !== undefined) {\n return requested;\n }\n if (error instanceof CfDebuggerError && error.code === \"ABORTED\") {\n return 130;\n }\n return hasCleanupFailure(error) ? CLEANUP_FAILURE_EXIT_CODE : 1;\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { constants as osConstants } from \"node:os\";\n\nimport {\n formatTunnelDiagnostics,\n getTunnelDiagnostics,\n} from \"../cf.js\";\nimport { CleanupFailureError } from \"../cli-errors.js\";\nimport { inspectPortOwnership } from \"../port.js\";\nimport {\n clearSessionStopIntent,\n hasSessionStopIntent,\n removeSession,\n updateSessionStatus,\n} from \"../state.js\";\nimport type {\n ActiveSession,\n DebuggerHandle,\n SessionStatus,\n} from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport {\n inspectProcessIdentity,\n readProcessIdentity,\n} from \"./process-identity.js\";\nimport { killProcessGroupOrProc } from \"./processes.js\";\nimport type { TerminationVerifier } from \"./processes.js\";\nimport { removeOwnedSessionCfHome } from \"./session-home.js\";\n\ntype StatusEmitter = (status: SessionStatus, message?: string) => void;\nconst handleLifecycles = new WeakMap<DebuggerHandle, TunnelLifecycle>();\n\nfunction childIsOpen(child: ChildProcess): boolean {\n return child.exitCode === null && child.signalCode === null;\n}\n\nexport interface TunnelLifecycle {\n readonly exitPromise: Promise<number | null>;\n readonly assertRunning: () => void;\n readonly finalize: (emitStopped: boolean) => Promise<void>;\n readonly observeChild: (child: ChildProcess) => void;\n readonly failed: () => boolean;\n readonly error: () => CfDebuggerError | undefined;\n}\n\nfunction signalExitCode(signal: NodeJS.Signals): number {\n return 128 + osConstants.signals[signal];\n}\n\nfunction unexpectedExitCode(\n code: number | null,\n signal: NodeJS.Signals | null,\n): number {\n if (signal !== null) {\n return signalExitCode(signal);\n }\n return code === null || code === 0 ? 1 : code;\n}\n\nfunction emitSafely(\n emit: StatusEmitter,\n status: SessionStatus,\n message?: string,\n): void {\n try {\n emit(status, message);\n } catch {\n // Status observers are informational and must never defeat owned-resource cleanup.\n }\n}\n\nasync function runCleanupActions(\n actions: readonly (() => void | Promise<void>)[],\n aggregateMessage: string,\n): Promise<void> {\n const errors: unknown[] = [];\n for (const action of actions) {\n try {\n await action();\n } catch (error: unknown) {\n errors.push(error);\n }\n }\n if (errors.length === 1) {\n throw errors[0];\n }\n if (errors.length > 1) {\n throw new AggregateError(errors, aggregateMessage);\n }\n}\n\nasync function handleTunnelClose(\n sessionId: string,\n code: number | null,\n signal: NodeJS.Signals | null,\n child: ChildProcess,\n resolveExit: (code: number | null) => void,\n isFinalizing: () => boolean,\n hasFailed: () => boolean,\n markFailed: (error: CfDebuggerError) => void,\n emit: StatusEmitter,\n): Promise<void> {\n const stopRequested = await hasSessionStopIntent(sessionId);\n const expected = isFinalizing() || stopRequested;\n if (stopRequested) {\n await clearSessionStopIntent(sessionId);\n }\n if (!expected && !hasFailed()) {\n const detail = signal === null\n ? code === null\n ? \"no exit status\"\n : `exit code ${code.toString()}`\n : `signal ${signal}`;\n const diagnostics = formatTunnelDiagnostics(getTunnelDiagnostics(child));\n const error = new CfDebuggerError(\n \"TUNNEL_EXITED\",\n `SSH tunnel ended unexpectedly with ${detail}.`,\n diagnostics,\n );\n markFailed(error);\n emitSafely(emit, \"error\", error.message);\n }\n resolveExit(expected && !hasFailed() ? 0 : unexpectedExitCode(code, signal));\n}\n\nfunction attachTunnelEvents(\n sessionId: string,\n child: ChildProcess,\n resolveExit: (code: number | null) => void,\n isFinalizing: () => boolean,\n hasFailed: () => boolean,\n markFailed: (error: CfDebuggerError) => void,\n emit: StatusEmitter,\n): void {\n child.once(\"close\", (code, signal) => {\n void handleTunnelClose(\n sessionId,\n code,\n signal,\n child,\n resolveExit,\n isFinalizing,\n hasFailed,\n markFailed,\n emit,\n ).catch((error: unknown) => {\n const failure = new CfDebuggerError(\n \"TUNNEL_EXITED\",\n `SSH tunnel ended and its stop intent could not be verified: ${\n error instanceof Error ? error.message : String(error)\n }`,\n formatTunnelDiagnostics(getTunnelDiagnostics(child)),\n );\n markFailed(failure);\n emitSafely(emit, \"error\", failure.message);\n resolveExit(unexpectedExitCode(code, signal));\n });\n });\n child.once(\"error\", (error: Error) => {\n const failure = new CfDebuggerError(\n \"TUNNEL_EXITED\",\n error.message,\n formatTunnelDiagnostics(getTunnelDiagnostics(child)),\n );\n markFailed(failure);\n emitSafely(emit, \"error\", failure.message);\n });\n}\n\nasync function expectedTunnelStillOwned(\n session: ActiveSession,\n child: ChildProcess | undefined,\n): Promise<boolean | \"unverified\"> {\n const childPid = child?.pid;\n if (childPid === undefined) {\n return false;\n }\n const ownership = await inspectPortOwnership(session.localPort, childPid);\n return ownership.status === \"unverified\"\n ? \"unverified\"\n : ownership.status === \"owned\";\n}\n\nasync function cleanupFinishedSession(session: ActiveSession): Promise<void> {\n await removeOwnedSessionCfHome(session.sessionId, session.cfHomeDir);\n await removeSession(session.sessionId);\n await clearSessionStopIntent(session.sessionId);\n}\n\nexport function createTunnelLifecycle(\n session: ActiveSession,\n emit: StatusEmitter,\n): TunnelLifecycle {\n let child: ChildProcess | undefined;\n let childIdentity: Promise<string | undefined> | undefined;\n let childFailed = false;\n let tunnelError: CfDebuggerError | undefined;\n let finalizing = false;\n let exitResolve: (code: number | null) => void = (_code) => {\n throw new Error(\"Tunnel exit resolver was used before initialization.\");\n };\n const exitPromise = new Promise<number | null>((resolve) => {\n exitResolve = resolve;\n });\n const observeChild = (tunnelChild: ChildProcess): void => {\n child = tunnelChild;\n childIdentity = tunnelChild.pid === undefined\n ? undefined\n : readProcessIdentity(tunnelChild.pid);\n attachTunnelEvents(\n session.sessionId,\n tunnelChild,\n exitResolve,\n (): boolean => finalizing,\n (): boolean => childFailed,\n (error): void => {\n if (!childFailed) {\n childFailed = true;\n tunnelError = error;\n }\n },\n emit,\n );\n };\n const verifyBeforeSignal: TerminationVerifier = async (signal): Promise<boolean> => {\n const tunnelChild = child;\n const childPid = tunnelChild?.pid;\n if (\n tunnelChild === undefined ||\n childPid === undefined ||\n !childIsOpen(tunnelChild)\n ) {\n return false;\n }\n const expectedIdentity = await childIdentity;\n if (expectedIdentity !== undefined) {\n return await inspectProcessIdentity(childPid, expectedIdentity) === \"match\" &&\n childIsOpen(tunnelChild);\n }\n if (signal === \"SIGKILL\") {\n return await expectedTunnelStillOwned(session, tunnelChild) === true;\n }\n // The still-open ChildProcess handle is the best available ownership proof\n // on platforms without a process birth token.\n return true;\n };\n const finalize = async (emitStopped: boolean): Promise<void> => {\n finalizing = true;\n const termination = child === undefined\n ? \"terminated\"\n : await killProcessGroupOrProc(child, verifyBeforeSignal);\n const stillOwned = await expectedTunnelStillOwned(session, child);\n if (termination !== \"terminated\" || stillOwned === true || stillOwned === \"unverified\") {\n const stderr = child === undefined\n ? undefined\n : formatTunnelDiagnostics(getTunnelDiagnostics(child));\n throw new CfDebuggerError(\n \"TUNNEL_TERMINATION_FAILED\",\n `Tunnel for session ${session.sessionId} did not terminate cleanly; state and CF home were retained.`,\n stderr,\n );\n }\n await cleanupFinishedSession(session);\n if (emitStopped) {\n emitSafely(emit, \"stopped\");\n }\n };\n return {\n exitPromise,\n assertRunning: (): void => {\n if (\n child === undefined ||\n !childIsOpen(child) ||\n childFailed\n ) {\n throw new CfDebuggerError(\n \"TUNNEL_NOT_READY\",\n `SSH tunnel for session ${session.sessionId} exited before readiness could be committed.`,\n child === undefined\n ? undefined\n : formatTunnelDiagnostics(getTunnelDiagnostics(child)),\n );\n }\n },\n finalize,\n observeChild,\n failed: (): boolean => childFailed,\n error: (): CfDebuggerError | undefined => tunnelError,\n };\n}\n\nexport function createDebuggerHandle(\n session: ActiveSession,\n emit: StatusEmitter,\n lifecycle: TunnelLifecycle,\n): DebuggerHandle {\n let disposePromise: Promise<void> | undefined;\n const handle: DebuggerHandle = {\n session,\n dispose: async (): Promise<void> => {\n const attempt = disposePromise ?? (async (): Promise<void> => {\n const reportLifecycle = !lifecycle.failed();\n await runCleanupActions([\n async (): Promise<void> => {\n if (reportLifecycle) {\n emitSafely(emit, \"stopping\");\n await updateSessionStatus(session.sessionId, \"stopping\");\n }\n },\n async (): Promise<void> => {\n await lifecycle.finalize(reportLifecycle);\n },\n ], \"Debugger disposal failed\");\n })();\n disposePromise = attempt;\n try {\n await attempt;\n } catch (error: unknown) {\n if (disposePromise === attempt) {\n disposePromise = undefined;\n }\n throw error;\n }\n },\n waitForExit: async (): Promise<number | null> => await lifecycle.exitPromise,\n };\n handleLifecycles.set(handle, lifecycle);\n return handle;\n}\n\nexport function getDebuggerHandleTunnelError(\n handle: DebuggerHandle,\n): CfDebuggerError | undefined {\n return handleLifecycles.get(handle)?.error();\n}\n\nexport async function cleanupFailedStartup(\n error: unknown,\n lifecycle: TunnelLifecycle,\n emit: StatusEmitter,\n): Promise<never> {\n emitSafely(emit, \"error\", error instanceof Error ? error.message : String(error));\n try {\n await lifecycle.finalize(false);\n } catch (cleanupError: unknown) {\n throw new CleanupFailureError(\n [error, cleanupError],\n cleanupError,\n );\n }\n throw error;\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport process from \"node:process\";\n\nimport { isPidAlive, isProcessGroupAlive } from \"../state.js\";\n\nimport {\n CHILD_SIGKILL_GRACE_MS,\n CHILD_SIGTERM_GRACE_MS,\n PID_TERMINATION_POLL_MS,\n} from \"./constants.js\";\n\ntype TerminationTargetKind = \"group\" | \"pid\";\nexport type TerminationOutcome = \"ownership-lost\" | \"still-alive\" | \"terminated\";\nexport type TerminationVerifier = (signal: \"SIGKILL\" | \"SIGTERM\") => Promise<boolean>;\n\nexport async function terminatePidOrGroup(\n pid: number,\n timeoutMs: number = CHILD_SIGTERM_GRACE_MS,\n pinnedTarget?: TerminationTargetKind,\n verifyBeforeSignal?: TerminationVerifier,\n): Promise<TerminationOutcome> {\n const targetKind = pinnedTarget ?? (isProcessGroupAlive(pid) ? \"group\" : \"pid\");\n const targetAlive = (): boolean => targetKind === \"group\"\n ? isProcessGroupAlive(pid)\n : isPidAlive(pid);\n if (!targetAlive()) {\n return \"terminated\";\n }\n if (\n verifyBeforeSignal !== undefined &&\n !(await verifyBeforeSignal(\"SIGTERM\"))\n ) {\n return \"ownership-lost\";\n }\n\n try {\n process.kill(targetKind === \"group\" ? -pid : pid, \"SIGTERM\");\n } catch {\n // target already gone\n }\n const startedAt = Date.now();\n while (Date.now() - startedAt < timeoutMs) {\n if (!targetAlive()) {\n return \"terminated\";\n }\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PID_TERMINATION_POLL_MS);\n });\n }\n\n if (\n verifyBeforeSignal !== undefined &&\n !(await verifyBeforeSignal(\"SIGKILL\"))\n ) {\n return \"ownership-lost\";\n }\n try {\n process.kill(targetKind === \"group\" ? -pid : pid, \"SIGKILL\");\n } catch {\n // target already gone\n }\n const forceStartedAt = Date.now();\n while (Date.now() - forceStartedAt < CHILD_SIGKILL_GRACE_MS) {\n if (!targetAlive()) {\n return \"terminated\";\n }\n await new Promise<void>((resolve) => {\n setTimeout(resolve, PID_TERMINATION_POLL_MS);\n });\n }\n return targetAlive() ? \"still-alive\" : \"terminated\";\n}\n\nexport async function killProcessGroupOrProc(\n child: ChildProcess,\n verifyBeforeSignal?: TerminationVerifier,\n timeoutMs: number = CHILD_SIGTERM_GRACE_MS,\n): Promise<TerminationOutcome> {\n if (child.pid === undefined) {\n return \"terminated\";\n }\n const childClosed = child.exitCode !== null || child.signalCode !== null;\n if (childClosed && process.platform === \"win32\") {\n return \"terminated\";\n }\n return await terminatePidOrGroup(\n child.pid,\n timeoutMs,\n childClosed ? \"group\" : undefined,\n verifyBeforeSignal,\n );\n}\n","import { rm } from \"node:fs/promises\";\n\nimport { isOwnedSessionCfHomeDir } from \"../paths.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nexport async function removeOwnedSessionCfHome(\n sessionId: string,\n candidate: string,\n): Promise<void> {\n if (!isOwnedSessionCfHomeDir(sessionId, candidate)) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n `Refusing to remove unowned debugger CF home for session ${sessionId}.`,\n );\n }\n await rm(candidate, { recursive: true, force: true });\n}\n\nexport async function tryRemoveOwnedSessionCfHome(\n sessionId: string,\n candidate: string,\n): Promise<boolean> {\n if (!isOwnedSessionCfHomeDir(sessionId, candidate)) {\n return false;\n }\n try {\n await removeOwnedSessionCfHome(sessionId, candidate);\n return true;\n } catch {\n return false;\n }\n}\n","import { CfDebuggerError } from \"../types.js\";\n\nimport {\n DEFAULT_STARTUP_TIMEOUT_MS,\n MAX_STARTUP_TIMEOUT_MS,\n} from \"./constants.js\";\n\nexport interface StartupDeadline {\n readonly expiresAt: number;\n readonly signal: AbortSignal;\n readonly timeoutMs: number;\n dispose(): void;\n}\n\nexport function resolveStartupTimeoutMs(value: number | undefined): number {\n const timeoutMs = value ?? DEFAULT_STARTUP_TIMEOUT_MS;\n if (\n !Number.isSafeInteger(timeoutMs) ||\n timeoutMs <= 0 ||\n timeoutMs > MAX_STARTUP_TIMEOUT_MS\n ) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n `Startup timeout must be an integer from 1 to ${MAX_STARTUP_TIMEOUT_MS.toString()} milliseconds.`,\n );\n }\n return timeoutMs;\n}\n\nexport function remainingStartupMs(expiresAt: number): number {\n return Math.max(0, expiresAt - Date.now());\n}\n\nexport function startupTimeoutError(timeoutMs: number, phase: string): CfDebuggerError {\n return new CfDebuggerError(\n \"STARTUP_TIMEOUT\",\n `Debugger startup exceeded its ${(timeoutMs / 1000).toString()}s deadline during ${phase}.`,\n );\n}\n\nexport function createStartupDeadline(\n timeoutMs: number,\n callerSignal?: AbortSignal,\n): StartupDeadline {\n const controller = new AbortController();\n const expiresAt = Date.now() + timeoutMs;\n const onCallerAbort = (): void => {\n controller.abort(callerSignal?.reason);\n };\n const timer = setTimeout(() => {\n controller.abort(startupTimeoutError(timeoutMs, \"startup\"));\n }, timeoutMs);\n timer.unref();\n callerSignal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n if (callerSignal?.aborted === true) {\n controller.abort(callerSignal.reason);\n }\n\n return {\n expiresAt,\n signal: controller.signal,\n timeoutMs,\n dispose: (): void => {\n clearTimeout(timer);\n callerSignal?.removeEventListener(\"abort\", onCallerAbort);\n },\n };\n}\n\nexport function throwIfStartupAborted(\n signal: AbortSignal | undefined,\n expiresAt: number,\n timeoutMs: number,\n phase: string,\n): void {\n if (remainingStartupMs(expiresAt) === 0) {\n throw startupTimeoutError(timeoutMs, phase);\n }\n if (signal?.aborted) {\n throw new CfDebuggerError(\"ABORTED\", \"Operation aborted by caller\");\n }\n}\n","import { chmod, mkdir } from \"node:fs/promises\";\nimport nodeProcess from \"node:process\";\n\nimport {\n cfAppExists,\n cfLogin,\n cfTarget,\n type CfExecContext,\n type CfRetryStatus,\n} from \"../cf.js\";\nimport {\n DEFAULT_NODE_INSPECTOR_PORT,\n resolveNodeTarget,\n type ResolvedNodeTarget,\n} from \"../cloud-foundry/node-process.js\";\nimport { sessionCfHomeDir } from \"../paths.js\";\nimport { isPortFree } from \"../port.js\";\nimport { resolveApiEndpoint } from \"../regions.js\";\nimport {\n registerNewSession,\n sessionKeyString,\n updateSessionRemoteNodePid,\n updateSessionStatus,\n} from \"../state.js\";\nimport type { StateAccessOptions } from \"../state.js\";\nimport type {\n ActiveSession,\n DebuggerHandle,\n SessionStatus,\n StartDebuggerOptions,\n} from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport { DEFAULT_TUNNEL_READY_TIMEOUT_MS } from \"./constants.js\";\nimport {\n cleanupFailedStartup,\n createDebuggerHandle,\n createTunnelLifecycle,\n} from \"./lifecycle.js\";\nimport { pruneAndCleanupOrphans } from \"./orphans.js\";\nimport { createStartupCancellation } from \"./startup-cancellation.js\";\nimport {\n createStartupDeadline,\n remainingStartupMs,\n resolveStartupTimeoutMs,\n type StartupDeadline,\n startupTimeoutError,\n throwIfStartupAborted,\n} from \"./startup-deadline.js\";\nimport { signalRemoteNode } from \"./startup-remote.js\";\nimport { openReadyTunnel } from \"./startup-tunnel.js\";\n\ntype StatusEmitter = (status: SessionStatus, message?: string) => void;\n\ninterface StatusTracker {\n readonly emit: StatusEmitter;\n readonly current: () => SessionStatus;\n}\n\ninterface StartupInputs {\n readonly options: StartDebuggerOptions;\n readonly target: ResolvedNodeTarget;\n readonly session: ActiveSession;\n readonly context: CfExecContext;\n readonly credentials: Credentials;\n readonly tunnelReadyTimeoutMs: number;\n readonly emit: StatusEmitter;\n readonly transition: (\n status: SessionStatus,\n message?: string,\n ) => Promise<ActiveSession>;\n readonly lifecycle: ReturnType<typeof createTunnelLifecycle>;\n}\n\ninterface Credentials {\n readonly email: string;\n readonly password: string;\n}\n\nfunction requireCredentials(options: StartDebuggerOptions): Credentials {\n const email = options.email ?? nodeProcess.env[\"SAP_EMAIL\"];\n const password = options.password ?? nodeProcess.env[\"SAP_PASSWORD\"];\n if (email === undefined || email.length === 0) {\n throw new CfDebuggerError(\n \"MISSING_CREDENTIALS\",\n \"SAP email is required. Pass `email` or set SAP_EMAIL.\",\n );\n }\n if (password === undefined || password.length === 0) {\n throw new CfDebuggerError(\n \"MISSING_CREDENTIALS\",\n \"SAP password is required. Pass `password` or set SAP_PASSWORD.\",\n );\n }\n return { email, password };\n}\n\nfunction resolveTunnelReadyTimeoutMs(value: number | undefined): number {\n const timeoutMs = value ?? DEFAULT_TUNNEL_READY_TIMEOUT_MS;\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"Tunnel-ready timeout must be a positive integer number of milliseconds.\",\n );\n }\n return timeoutMs;\n}\n\nasync function registerSession(\n options: StartDebuggerOptions,\n target: ResolvedNodeTarget,\n apiEndpoint: string,\n deadline: StartupDeadline,\n): Promise<ActiveSession> {\n const portProbe = async (port: number): Promise<boolean> => {\n throwIfStartupAborted(\n deadline.signal,\n deadline.expiresAt,\n deadline.timeoutMs,\n \"local port selection\",\n );\n const available = await isPortFree(port, deadline.signal);\n throwIfStartupAborted(\n deadline.signal,\n deadline.expiresAt,\n deadline.timeoutMs,\n \"local port selection\",\n );\n return available;\n };\n const registration = await registerNewSession({\n region: options.region,\n org: options.org,\n space: options.space,\n app: options.app,\n process: target.process,\n instance: target.instance,\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n apiEndpoint,\n remotePort: options.remotePort ?? DEFAULT_NODE_INSPECTOR_PORT,\n startupTimeoutMs: deadline.timeoutMs,\n ...(options.preferredPort === undefined ? {} : { preferredPort: options.preferredPort }),\n portProbe,\n cfHomeForSession: sessionCfHomeDir,\n stateAccess: startupStateAccess(deadline.signal, deadline.expiresAt),\n });\n if (registration.existing !== undefined) {\n throw new CfDebuggerError(\n \"SESSION_ALREADY_RUNNING\",\n `A debugger session already exists for ${sessionKeyString(options)} on port ` +\n `${registration.existing.localPort.toString()} (session ${registration.existing.sessionId}).`,\n );\n }\n return registration.session;\n}\n\nfunction requireStartupState(\n state: ActiveSession | undefined,\n expectedStatus?: SessionStatus,\n): ActiveSession {\n if (state === undefined) {\n throw new CfDebuggerError(\n \"SESSION_STATE_LOST\",\n \"Debugger session ownership state disappeared during startup.\",\n );\n }\n if (state.stopRequestedAt !== undefined || state.status === \"stopping\") {\n throw new CfDebuggerError(\"ABORTED\", \"Debugger session stop was requested during startup.\");\n }\n if (expectedStatus !== undefined && state.status !== expectedStatus) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n `Debugger session state did not transition to ${expectedStatus}.`,\n );\n }\n return state;\n}\n\nfunction startupStateAccess(\n signal: AbortSignal | undefined,\n expiresAt: number | undefined,\n): StateAccessOptions {\n return {\n ...(signal === undefined ? {} : { signal }),\n ...(expiresAt === undefined\n ? {}\n : { timeoutMs: Math.max(1, remainingStartupMs(expiresAt)) }),\n };\n}\n\nfunction createTransition(\n sessionId: string,\n context: CfExecContext,\n): StartupInputs[\"transition\"] {\n return async (status, message): Promise<ActiveSession> => {\n return requireStartupState(\n await updateSessionStatus(\n sessionId,\n status,\n message,\n startupStateAccess(context.signal, context.deadlineAt),\n ),\n status,\n );\n };\n}\n\nasync function prepareCfHome(cfHomeDir: string): Promise<void> {\n await mkdir(cfHomeDir, { recursive: true, mode: 0o700 });\n await chmod(cfHomeDir, 0o700);\n}\n\nasync function loginAndTarget(inputs: StartupInputs): Promise<void> {\n const { options, context, credentials, emit, transition } = inputs;\n emit(\"logging-in\");\n await transition(\"logging-in\");\n await cfLogin(\n inputs.session.apiEndpoint,\n credentials.email,\n credentials.password,\n { ...context, phase: \"Cloud Foundry login\" },\n );\n emit(\"targeting\");\n await transition(\"targeting\");\n const targetingContext = { ...context, phase: \"Cloud Foundry target selection\" };\n await cfTarget(options.org, options.space, targetingContext);\n if (!(await cfAppExists(options.app, targetingContext))) {\n throw new CfDebuggerError(\n \"APP_NOT_FOUND\",\n `Cloud Foundry app ${options.app} was not found in ${options.org}/${options.space}.`,\n );\n }\n}\n\nasync function ensurePortAvailable(\n localPort: number,\n context: CfExecContext,\n): Promise<void> {\n if (!(await isPortFree(localPort, context.signal))) {\n throw new CfDebuggerError(\n \"PORT_UNAVAILABLE\",\n `Local port ${localPort.toString()} was taken before remote signalling began.`,\n );\n }\n}\n\nasync function recordRemoteNodePid(\n sessionId: string,\n remoteNodePid: number,\n context: CfExecContext,\n): Promise<void> {\n const state = requireStartupState(\n await updateSessionRemoteNodePid(\n sessionId,\n remoteNodePid,\n startupStateAccess(context.signal, context.deadlineAt),\n ),\n );\n if (state.remoteNodePid !== remoteNodePid) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n \"Debugger session did not retain the selected remote Node PID.\",\n );\n }\n}\n\nasync function establishDebuggerSession(inputs: StartupInputs): Promise<ActiveSession> {\n await prepareCfHome(inputs.session.cfHomeDir);\n await loginAndTarget(inputs);\n await ensurePortAvailable(inputs.session.localPort, inputs.context);\n const remoteNodePid = await signalRemoteNode({\n options: inputs.options,\n target: inputs.target,\n context: inputs.context,\n transition: inputs.transition,\n emit: inputs.emit,\n warn: writeWarning,\n });\n throwIfStartupAborted(\n inputs.context.signal,\n inputs.context.deadlineAt ?? Number.MAX_SAFE_INTEGER,\n inputs.context.startupTimeoutMs ?? Number.MAX_SAFE_INTEGER,\n \"remote inspector signalling\",\n );\n await recordRemoteNodePid(inputs.session.sessionId, remoteNodePid, inputs.context);\n inputs.emit(\"tunneling\");\n await inputs.transition(\"tunneling\");\n await openReadyTunnel({\n options: inputs.options,\n target: inputs.target,\n session: inputs.session,\n context: inputs.context,\n tunnelReadyTimeoutMs: inputs.tunnelReadyTimeoutMs,\n onChild: inputs.lifecycle.observeChild,\n });\n const readySession = await inputs.transition(\"ready\");\n inputs.lifecycle.assertRunning();\n inputs.emit(\"ready\");\n return readySession;\n}\n\nfunction writeWarning(message: string): void {\n nodeProcess.stderr.write(`[cf-debugger] warning: ${message}\\n`);\n}\n\nfunction writeTunnelOutput(stream: \"stderr\" | \"stdout\", text: string): void {\n nodeProcess.stderr.write(`[cf-debugger tunnel ${stream}] ${text}\\n`);\n}\n\nfunction retryMessage(status: CfRetryStatus): string {\n const remainingSeconds = Math.ceil(status.remainingMs / 1000);\n return `${status.command} attempt ${status.attempt.toString()} failed; retrying in ` +\n `${status.delayMs.toString()}ms (${remainingSeconds.toString()}s startup budget left)`;\n}\n\nfunction createStatusTracker(options: StartDebuggerOptions): StatusTracker {\n let currentStatus: SessionStatus = \"starting\";\n return {\n current: (): SessionStatus => currentStatus,\n emit: (status, message): void => {\n currentStatus = status;\n try {\n options.onStatus?.(status, message);\n } catch {\n writeWarning(\"The onStatus callback threw; lifecycle cleanup will continue.\");\n }\n },\n };\n}\n\nfunction createCfContext(\n session: ActiveSession,\n credentials: Credentials,\n cancellation: ReturnType<typeof createStartupCancellation>,\n deadline: ReturnType<typeof createStartupDeadline>,\n tracker: StatusTracker,\n verbose: boolean,\n): CfExecContext {\n return {\n cfHome: session.cfHomeDir,\n signal: cancellation.signal,\n deadlineAt: deadline.expiresAt,\n startupTimeoutMs: deadline.timeoutMs,\n sensitiveValues: [credentials.email, credentials.password],\n ...(verbose\n ? {\n onRetry: (status: CfRetryStatus): void => {\n tracker.emit(tracker.current(), retryMessage(status));\n },\n onTunnelOutput: writeTunnelOutput,\n }\n : {}),\n };\n}\n\nfunction normalizeStartupError(\n error: unknown,\n expiresAt: number,\n timeoutMs: number,\n): unknown {\n if (\n error instanceof CfDebuggerError &&\n error.code === \"ABORTED\" &&\n remainingStartupMs(expiresAt) === 0\n ) {\n return startupTimeoutError(timeoutMs, \"startup\");\n }\n return error;\n}\n\nasync function startDebuggerUsingDeadline(\n options: StartDebuggerOptions,\n deadline: StartupDeadline,\n): Promise<DebuggerHandle> {\n const target = resolveNodeTarget(options);\n const credentials = requireCredentials(options);\n const apiEndpoint = resolveApiEndpoint(options.region, options.apiEndpoint, writeWarning);\n const startupTimeoutMs = deadline.timeoutMs;\n const tunnelReadyTimeoutMs = resolveTunnelReadyTimeoutMs(options.tunnelReadyTimeoutMs);\n const tracker = createStatusTracker(options);\n tracker.emit(\"starting\");\n let cancellation: ReturnType<typeof createStartupCancellation> | undefined;\n let lifecycle: ReturnType<typeof createTunnelLifecycle> | undefined;\n try {\n throwIfStartupAborted(deadline.signal, deadline.expiresAt, startupTimeoutMs, \"initialization\");\n await pruneAndCleanupOrphans(\n startupStateAccess(deadline.signal, deadline.expiresAt),\n );\n throwIfStartupAborted(deadline.signal, deadline.expiresAt, startupTimeoutMs, \"state cleanup\");\n const session = await registerSession(options, target, apiEndpoint, deadline);\n cancellation = createStartupCancellation(session.sessionId, deadline.signal);\n const context = createCfContext(\n session,\n credentials,\n cancellation,\n deadline,\n tracker,\n options.verbose === true,\n );\n lifecycle = createTunnelLifecycle(session, tracker.emit);\n const activeSession = await establishDebuggerSession({\n options: { ...options, remotePort: session.remotePort },\n target,\n session,\n context,\n credentials,\n tunnelReadyTimeoutMs,\n emit: tracker.emit,\n transition: createTransition(session.sessionId, context),\n lifecycle,\n });\n cancellation.dispose();\n deadline.dispose();\n return createDebuggerHandle(activeSession, tracker.emit, lifecycle);\n } catch (error: unknown) {\n cancellation?.dispose();\n deadline.dispose();\n const normalized = normalizeStartupError(error, deadline.expiresAt, startupTimeoutMs);\n if (lifecycle === undefined) {\n tracker.emit(\n \"error\",\n normalized instanceof Error ? normalized.message : String(normalized),\n );\n throw normalized;\n }\n return await cleanupFailedStartup(normalized, lifecycle, tracker.emit);\n }\n}\n\nexport async function startDebuggerWithinDeadline(\n options: StartDebuggerOptions,\n deadline: StartupDeadline,\n): Promise<DebuggerHandle> {\n try {\n return await startDebuggerUsingDeadline(options, deadline);\n } catch (error: unknown) {\n deadline.dispose();\n throw error;\n }\n}\n\nexport async function startDebugger(options: StartDebuggerOptions): Promise<DebuggerHandle> {\n const startupTimeoutMs = resolveStartupTimeoutMs(options.startupTimeoutMs);\n const deadline = createStartupDeadline(startupTimeoutMs, options.signal);\n return await startDebuggerWithinDeadline(options, deadline);\n}\n","import { readdir, stat, unlink } from \"node:fs/promises\";\nimport { hostname as getHostname } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport {\n CF_DEBUGGER_STATE_FILENAME,\n saptoolsDir,\n} from \"../paths.js\";\nimport { readAndPruneActiveSessions } from \"../state.js\";\nimport type { StateAccessOptions } from \"../state.js\";\nimport type { ActiveSession } from \"../types.js\";\n\nimport { tryRemoveOwnedSessionCfHome } from \"./session-home.js\";\n\nconst STALE_TEMP_AGE_MS = 24 * 60 * 60 * 1_000;\n\nexport interface PruneCleanupResult {\n readonly sessions: readonly ActiveSession[];\n readonly removed: readonly ActiveSession[];\n}\n\nasync function modifiedAt(path: string): Promise<number | undefined> {\n try {\n return (await stat(path)).mtimeMs;\n } catch {\n return undefined;\n }\n}\n\nasync function cleanupStaleStateTemps(): Promise<void> {\n const root = saptoolsDir();\n const entries = await readdir(root, { withFileTypes: true }).catch(() => []);\n const now = Date.now();\n for (const entry of entries) {\n if (\n !entry.isFile() ||\n !entry.name.startsWith(`${CF_DEBUGGER_STATE_FILENAME}.`) ||\n !entry.name.endsWith(\".tmp\")\n ) {\n continue;\n }\n const path = join(root, entry.name);\n const mtimeMs = await modifiedAt(path);\n if (mtimeMs !== undefined && now - mtimeMs >= STALE_TEMP_AGE_MS) {\n await unlink(path).catch(() => false);\n }\n }\n}\n\nexport async function pruneAndCleanupOrphans(\n stateAccess?: StateAccessOptions,\n): Promise<PruneCleanupResult> {\n const result = await readAndPruneActiveSessions(stateAccess);\n const host = getHostname();\n for (const removed of result.removed) {\n if (removed.hostname === host) {\n await tryRemoveOwnedSessionCfHome(removed.sessionId, removed.cfHomeDir);\n }\n }\n await cleanupStaleStateTemps();\n return result;\n}\n","import { hasSessionStopIntent } from \"../state.js\";\n\nconst STOP_REQUEST_POLL_MS = 500;\n\nexport interface StartupCancellation {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\nexport function createStartupCancellation(\n sessionId: string,\n callerSignal?: AbortSignal,\n): StartupCancellation {\n const controller = new AbortController();\n let active = true;\n let timer: NodeJS.Timeout | undefined;\n const onCallerAbort = (): void => {\n controller.abort(callerSignal?.reason);\n };\n const schedule = (): void => {\n timer = setTimeout(() => { void poll(); }, STOP_REQUEST_POLL_MS);\n timer.unref();\n };\n const poll = async (): Promise<void> => {\n try {\n if (active && await hasSessionStopIntent(sessionId)) {\n controller.abort();\n }\n } catch {\n // A lifecycle transition still validates state under the lock after transient read failures.\n }\n if (active && !controller.signal.aborted) {\n schedule();\n }\n };\n\n callerSignal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n if (callerSignal?.aborted === true) {\n controller.abort(callerSignal.reason);\n } else {\n void poll();\n }\n return {\n signal: controller.signal,\n dispose: (): void => {\n active = false;\n clearTimeout(timer);\n callerSignal?.removeEventListener(\"abort\", onCallerAbort);\n controller.abort();\n },\n };\n}\n","import {\n cfEnableSsh,\n cfRestartApp,\n cfSshEnabled,\n cfSshOneShot,\n isSshDisabledError,\n isSshPermissionError,\n type CfExecContext,\n} from \"../cf.js\";\nimport {\n buildNodeInspectorCommand,\n DEFAULT_NODE_INSPECTOR_PORT,\n parseNodeInspectorMarkers,\n type ResolvedNodeTarget,\n} from \"../cloud-foundry/node-process.js\";\nimport type { ActiveSession, SessionStatus, StartDebuggerOptions } from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\ntype SignalResult = Awaited<ReturnType<typeof cfSshOneShot>>;\ntype Transition = (\n status: SessionStatus,\n message?: string,\n) => Promise<ActiveSession>;\ntype StatusEmitter = (status: SessionStatus, message?: string) => void;\n\nexport interface RemoteSignalInputs {\n readonly options: StartDebuggerOptions;\n readonly target: ResolvedNodeTarget;\n readonly context: CfExecContext;\n readonly transition: Transition;\n readonly emit: StatusEmitter;\n readonly warn: (message: string) => void;\n}\n\nfunction signalFailureDetail(result: SignalResult): string {\n if (result.timedOutAfterMs !== undefined) {\n return `timed out after ${(result.timedOutAfterMs / 1000).toString()}s`;\n }\n const stderr = result.stderr.trim();\n if (stderr.length > 0) {\n return stderr;\n }\n if (result.signal !== undefined) {\n return `terminated by signal ${result.signal}`;\n }\n return `exit code ${String(result.exitCode)}`;\n}\n\nfunction warnOnTruncatedStderr(\n inputs: RemoteSignalInputs,\n result: SignalResult,\n): void {\n if (result.stderrTruncated) {\n inputs.warn(\n \"Remote SSH stderr diagnostics were truncated; inspector marker parsing used complete stdout.\",\n );\n }\n}\n\nfunction parseSignalResult(\n appName: string,\n remotePort: number,\n result: SignalResult,\n): number {\n if (result.exitCode !== 0) {\n throw new CfDebuggerError(\n \"USR1_SIGNAL_FAILED\",\n `Failed to send SIGUSR1 to the Node.js process on ${appName}: ${signalFailureDetail(result)}`,\n result.stderr,\n );\n }\n if (result.stdoutTruncated) {\n throw new CfDebuggerError(\n \"INSPECTOR_OUTPUT_TOO_LARGE\",\n \"Inspector startup stdout exceeded the configured capture limit.\",\n result.stderr,\n );\n }\n return parseNodeInspectorMarkers(result.stdout, remotePort).remoteNodePid;\n}\n\nasync function executeRemoteSignal(inputs: RemoteSignalInputs): Promise<SignalResult> {\n const { options, target, context } = inputs;\n return await cfSshOneShot(\n options.app,\n buildNodeInspectorCommand(target.nodePid, options.remotePort),\n { ...context, phase: \"remote inspector signalling\" },\n {\n process: target.process,\n instance: target.instance,\n },\n );\n}\n\nfunction restartRefusal(options: StartDebuggerOptions, stderr: string): CfDebuggerError {\n return new CfDebuggerError(\n \"SSH_NOT_ENABLED\",\n `SSH is disabled for ${options.app}. Re-run with --allow-ssh-enable-restart, or run ` +\n `\\`cf enable-ssh ${options.app} && cf restart ${options.app}\\` manually.`,\n stderr,\n );\n}\n\nfunction ensureRestartSafe(inputs: RemoteSignalInputs, stderr: string): void {\n if (inputs.options.allowSshEnableRestart !== true) {\n throw restartRefusal(inputs.options, stderr);\n }\n if (inputs.target.nodePid !== undefined) {\n throw new CfDebuggerError(\n \"NODE_PID_RESTART_UNSAFE\",\n `Cannot restart ${inputs.options.app} while targeting Node PID ` +\n `${inputs.target.nodePid.toString()}; restart manually and select its new PID.`,\n stderr,\n );\n }\n}\n\nasync function enableAppSsh(inputs: RemoteSignalInputs, stderr: string): Promise<void> {\n ensureRestartSafe(inputs, stderr);\n const state = await cfSshEnabled(\n inputs.options.app,\n { ...inputs.context, phase: \"checking app SSH state\" },\n );\n if (state === \"enabled\") {\n throw new CfDebuggerError(\n \"SSH_NOT_ENABLED\",\n `SSH is already enabled for ${inputs.options.app}, so restarting it is not a remedy. ` +\n \"Check space-level SSH policy and your Developer role.\",\n stderr,\n );\n }\n if (state === \"unknown\") {\n throw new CfDebuggerError(\n \"SSH_STATE_UNKNOWN\",\n `Could not verify whether SSH is enabled for ${inputs.options.app}; no deployment change was made.`,\n stderr,\n );\n }\n inputs.emit(\"ssh-enabling\", \"Enabling app-level SSH\");\n await inputs.transition(\"ssh-enabling\", \"Enabling app-level SSH\");\n await cfEnableSsh(\n inputs.options.app,\n { ...inputs.context, phase: \"enabling app SSH\" },\n );\n const confirmed = await cfSshEnabled(\n inputs.options.app,\n { ...inputs.context, phase: \"confirming app SSH state\" },\n );\n if (confirmed !== \"enabled\") {\n throw new CfDebuggerError(\n \"SSH_STATE_UNKNOWN\",\n `App-level SSH enablement for ${inputs.options.app} could not be confirmed; no restart was attempted.`,\n );\n }\n}\n\nasync function enableAndRestart(inputs: RemoteSignalInputs, stderr: string): Promise<void> {\n await enableAppSsh(inputs, stderr);\n const { app, org, space } = inputs.options;\n inputs.warn(\n `Restarting app ${app} in ${org}/${space} so newly enabled SSH becomes active.`,\n );\n inputs.emit(\"ssh-restarting\", \"Restarting app so SSH becomes active\");\n await inputs.transition(\"ssh-restarting\", \"Restarting app so SSH becomes active\");\n await cfRestartApp(app, { ...inputs.context, phase: \"restarting the app\" });\n}\n\nasync function retrySignal(inputs: RemoteSignalInputs): Promise<number> {\n inputs.emit(\"signaling\");\n await inputs.transition(\"signaling\");\n const result = await executeRemoteSignal(inputs);\n warnOnTruncatedStderr(inputs, result);\n if (result.exitCode !== 0) {\n throw new CfDebuggerError(\n \"USR1_SIGNAL_FAILED\",\n `Failed to signal ${inputs.options.app} after enabling SSH: ${signalFailureDetail(result)}`,\n result.stderr,\n );\n }\n return parseSignalResult(\n inputs.options.app,\n inputs.options.remotePort ?? DEFAULT_NODE_INSPECTOR_PORT,\n result,\n );\n}\n\nexport async function signalRemoteNode(inputs: RemoteSignalInputs): Promise<number> {\n inputs.emit(\"signaling\");\n await inputs.transition(\"signaling\");\n const result = await executeRemoteSignal(inputs);\n warnOnTruncatedStderr(inputs, result);\n const remotePort = inputs.options.remotePort ?? DEFAULT_NODE_INSPECTOR_PORT;\n if (result.exitCode === 0) {\n return parseSignalResult(inputs.options.app, remotePort, result);\n }\n if (isSshPermissionError(result.stderr)) {\n throw new CfDebuggerError(\n \"SSH_PERMISSION_DENIED\",\n `CF SSH permission was denied for ${inputs.options.app}. Check your space role and SSH policy.`,\n result.stderr,\n );\n }\n if (!isSshDisabledError(result.stderr)) {\n return parseSignalResult(inputs.options.app, remotePort, result);\n }\n await enableAndRestart(inputs, result.stderr);\n return await retrySignal(inputs);\n}\n","import type { ChildProcess } from \"node:child_process\";\n\nimport {\n formatTunnelDiagnostics,\n getTunnelDiagnostics,\n spawnSshTunnel,\n type CfExecContext,\n} from \"../cf.js\";\nimport type { ResolvedNodeTarget } from \"../cloud-foundry/node-process.js\";\nimport {\n inspectPortOwnership,\n isPortFree,\n probeInspectorReady,\n probeTunnelReady,\n} from \"../port.js\";\nimport {\n updateSessionPid,\n} from \"../state.js\";\nimport type { StateAccessOptions } from \"../state.js\";\nimport type { ActiveSession, StartDebuggerOptions } from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport { throwIfStartupAborted } from \"./startup-deadline.js\";\n\ninterface TunnelInputs {\n readonly options: StartDebuggerOptions;\n readonly target: ResolvedNodeTarget;\n readonly session: ActiveSession;\n readonly context: CfExecContext;\n readonly tunnelReadyTimeoutMs: number;\n readonly onChild: (child: ChildProcess) => void;\n}\n\ninterface LinkedAbortSignal {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\nfunction linkAbortSignals(signals: readonly AbortSignal[]): LinkedAbortSignal {\n const controller = new AbortController();\n const subscriptions: (readonly [AbortSignal, () => void])[] = [];\n for (const signal of signals) {\n const abort = (): void => {\n controller.abort(signal.reason);\n };\n if (signal.aborted) {\n abort();\n break;\n }\n signal.addEventListener(\"abort\", abort, { once: true });\n subscriptions.push([signal, abort]);\n }\n return {\n signal: controller.signal,\n dispose: (): void => {\n for (const [signal, abort] of subscriptions) {\n signal.removeEventListener(\"abort\", abort);\n }\n },\n };\n}\n\nfunction diagnosticsStderr(child: ChildProcess): string | undefined {\n return formatTunnelDiagnostics(getTunnelDiagnostics(child));\n}\n\nasync function ensurePortAvailable(\n localPort: number,\n signal: AbortSignal | undefined,\n): Promise<void> {\n if (!(await isPortFree(localPort, signal))) {\n throw new CfDebuggerError(\n \"PORT_UNAVAILABLE\",\n `Local port ${localPort.toString()} was taken before the tunnel could start.`,\n );\n }\n}\n\nfunction remainingReadyTimeout(inputs: TunnelInputs): number {\n if (inputs.context.deadlineAt === undefined) {\n return inputs.tunnelReadyTimeoutMs;\n }\n return Math.max(\n 1,\n Math.min(inputs.tunnelReadyTimeoutMs, inputs.context.deadlineAt - Date.now()),\n );\n}\n\nfunction startupStateAccess(inputs: TunnelInputs): StateAccessOptions {\n return {\n ...(inputs.context.signal === undefined ? {} : { signal: inputs.context.signal }),\n ...(inputs.context.deadlineAt === undefined\n ? {}\n : { timeoutMs: Math.max(1, inputs.context.deadlineAt - Date.now()) }),\n };\n}\n\nfunction ownerVerificationError(\n localPort: number,\n inspection: Awaited<ReturnType<typeof inspectPortOwnership>>,\n child: ChildProcess,\n): CfDebuggerError {\n const stderr = diagnosticsStderr(child);\n if (inspection.status === \"unverified\") {\n return new CfDebuggerError(\n \"TUNNEL_OWNER_UNVERIFIED\",\n `Could not verify local tunnel port ${localPort.toString()}: ${inspection.reason}`,\n stderr,\n );\n }\n const owners = inspection.status === \"not-owned\"\n ? inspection.pids.join(\", \")\n : \"none\";\n return new CfDebuggerError(\n \"TUNNEL_OWNER_MISMATCH\",\n `Local tunnel port ${localPort.toString()} is not owned by the spawned tunnel ` +\n `(observed PID(s): ${owners}).`,\n stderr,\n );\n}\n\nasync function waitForLocalTunnel(\n inputs: TunnelInputs,\n child: ChildProcess,\n timeoutMs: number,\n): Promise<void> {\n const childEnded = new AbortController();\n const linked = linkAbortSignals([\n ...(inputs.context.signal === undefined ? [] : [inputs.context.signal]),\n childEnded.signal,\n ]);\n try {\n const probe = probeTunnelReady(inputs.session.localPort, timeoutMs, linked.signal);\n const winner = await Promise.race([\n probe.then((ready) => ({ kind: \"probe\" as const, ready })),\n childExitPromise(child).then(() => ({ kind: \"child-exit\" as const })),\n ]);\n if (winner.kind === \"probe\" && winner.ready) {\n return;\n }\n if (winner.kind === \"child-exit\") {\n childEnded.abort();\n await probe.catch(() => false);\n }\n } finally {\n linked.dispose();\n }\n throw new CfDebuggerError(\n \"TUNNEL_NOT_READY\",\n `SSH tunnel on local port ${inputs.session.localPort.toString()} did not bind within ` +\n `${Math.round(timeoutMs / 1000).toString()}s.`,\n diagnosticsStderr(child),\n );\n}\n\nasync function verifyLocalOwner(\n inputs: TunnelInputs,\n child: ChildProcess,\n childPid: number,\n): Promise<void> {\n const ownership = await inspectPortOwnership(\n inputs.session.localPort,\n childPid,\n inputs.context.signal,\n );\n if (ownership.status !== \"owned\") {\n throw ownerVerificationError(inputs.session.localPort, ownership, child);\n }\n}\n\nfunction childExitPromise(child: ChildProcess): Promise<void> {\n if (child.exitCode !== null || child.signalCode !== null) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n child.once(\"close\", () => {\n resolve();\n });\n });\n}\n\nasync function verifyInspector(\n inputs: TunnelInputs,\n child: ChildProcess,\n timeoutMs: number,\n): Promise<void> {\n const childEnded = new AbortController();\n const linked = linkAbortSignals([\n ...(inputs.context.signal === undefined ? [] : [inputs.context.signal]),\n childEnded.signal,\n ]);\n try {\n const probe = probeInspectorReady(inputs.session.localPort, timeoutMs, linked.signal);\n const winner = await Promise.race([\n probe.then((result) => ({ kind: \"probe\" as const, result })),\n childExitPromise(child).then(() => ({ kind: \"child-exit\" as const })),\n ]);\n if (winner.kind === \"probe\" && winner.result.status === \"ready\") {\n return;\n }\n if (winner.kind === \"child-exit\") {\n childEnded.abort();\n await probe.catch(() => ({ status: \"unreachable\" as const }));\n }\n } finally {\n linked.dispose();\n }\n throw new CfDebuggerError(\n \"INSPECTOR_UNREACHABLE\",\n `The inspector did not answer through local port ${inputs.session.localPort.toString()} ` +\n `to remote port ${inputs.session.remotePort.toString()}. The inspector may not have opened, ` +\n \"the app or container may have restarted, or a different Node PID may own it.\",\n diagnosticsStderr(child),\n );\n}\n\nfunction requireChildPid(child: ChildProcess): number {\n if (child.pid === undefined) {\n throw new CfDebuggerError(\n \"TUNNEL_PROCESS_MISSING\",\n \"The CF SSH tunnel process did not expose a PID.\",\n );\n }\n return child.pid;\n}\n\nasync function recordTunnelPid(inputs: TunnelInputs, childPid: number): Promise<void> {\n const state = await updateSessionPid(\n inputs.session.sessionId,\n childPid,\n startupStateAccess(inputs),\n );\n if (\n state === undefined\n || state.stopRequestedAt !== undefined\n || state.status === \"stopping\"\n ) {\n throw new CfDebuggerError(\n state === undefined ? \"SESSION_STATE_LOST\" : \"ABORTED\",\n state === undefined\n ? \"Debugger session ownership state disappeared while recording the tunnel PID.\"\n : \"Debugger session stop was requested while recording the tunnel PID.\",\n );\n }\n if (state.tunnelPid !== childPid || state.pid !== childPid) {\n throw new CfDebuggerError(\n \"SESSION_STATE_CONFLICT\",\n \"Debugger session did not retain ownership of the spawned tunnel process.\",\n );\n }\n}\n\nfunction ensureStartupActive(inputs: TunnelInputs, phase: string): void {\n throwIfStartupAborted(\n inputs.context.signal,\n inputs.context.deadlineAt ?? Number.MAX_SAFE_INTEGER,\n inputs.context.startupTimeoutMs ?? Number.MAX_SAFE_INTEGER,\n phase,\n );\n}\n\nexport async function openReadyTunnel(inputs: TunnelInputs): Promise<void> {\n await ensurePortAvailable(inputs.session.localPort, inputs.context.signal);\n ensureStartupActive(inputs, \"the final local-port check\");\n const child = spawnSshTunnel(\n inputs.options.app,\n inputs.session.localPort,\n inputs.session.remotePort,\n { ...inputs.context, phase: \"opening the SSH tunnel\" },\n { process: inputs.target.process, instance: inputs.target.instance },\n );\n inputs.onChild(child);\n const childPid = requireChildPid(child);\n await recordTunnelPid(inputs, childPid);\n const timeoutMs = remainingReadyTimeout(inputs);\n const readyDeadline = Date.now() + timeoutMs;\n await waitForLocalTunnel(inputs, child, timeoutMs);\n ensureStartupActive(inputs, \"local tunnel binding\");\n await verifyLocalOwner(inputs, child, childPid);\n ensureStartupActive(inputs, \"local tunnel ownership verification\");\n await verifyInspector(inputs, child, Math.max(1, readyDeadline - Date.now()));\n ensureStartupActive(inputs, \"inspector readiness verification\");\n await verifyLocalOwner(inputs, child, childPid);\n ensureStartupActive(inputs, \"final local tunnel ownership verification\");\n if (child.exitCode !== null || child.signalCode !== null) {\n throw new CfDebuggerError(\n \"TUNNEL_NOT_READY\",\n `SSH tunnel on local port ${inputs.session.localPort.toString()} exited during readiness verification.`,\n diagnosticsStderr(child),\n );\n }\n}\n","import type { Dirent, Stats } from \"node:fs\";\nimport {\n lstat,\n readFile,\n readdir,\n unlink,\n} from \"node:fs/promises\";\nimport { hostname } from \"node:os\";\nimport { join } from \"node:path\";\nimport nodeProcess from \"node:process\";\n\nimport { withFileLock } from \"../lock.js\";\nimport {\n inspectListeningProcesses,\n isPortListening,\n} from \"../network/ports.js\";\nimport {\n CF_DEBUGGER_HOMES_DIRNAME,\n CF_DEBUGGER_LOCK_FILENAME,\n CF_DEBUGGER_STATE_FILENAME,\n CF_DEBUGGER_STOP_INTENT_PREFIX,\n isOwnedSessionCfHomeDir,\n saptoolsDir,\n stateFilePath,\n stateLockPath,\n} from \"../paths.js\";\nimport { decodeStateFileDetailed } from \"../session-state/decoder.js\";\nimport type { SessionHealthVerdict } from \"../session-state/store.js\";\nimport { inspectSessionHealth } from \"../session-state/store.js\";\nimport type {\n ActiveSession,\n StateFile,\n} from \"../types.js\";\n\nimport { inspectProcessIdentity } from \"./process-identity.js\";\nimport { tryRemoveOwnedSessionCfHome } from \"./session-home.js\";\n\nconst MANAGED_PORT_MIN = 20_000;\nconst MANAGED_PORT_MAX = 20_999;\nconst PORT_SCAN_CONCURRENCY = 32;\nconst STALE_TEMP_AGE_MS = 24 * 60 * 60 * 1_000;\nconst STALE_LOCK_AGE_MS = 60 * 60 * 1_000;\nconst FOREIGN_OR_MALFORMED_LOCK_AGE_MS = 24 * 60 * 60 * 1_000;\nconst LEGACY_STATE_FILENAME = \"cf-debugger-state.json\";\nconst LEGACY_LOCK_FILENAME = \"cf-debugger-state.lock\";\nconst LEGACY_HOMES_DIRNAME = \"cf-debugger-homes\";\n\nexport type DoctorCleanupStatus =\n | \"not-requested\"\n | \"not-eligible\"\n | \"removed\"\n | \"skipped\"\n | \"failed\";\n\nexport interface DoctorSessionFinding {\n readonly session: ActiveSession;\n readonly health: SessionHealthVerdict;\n}\n\nexport interface DoctorHomeFinding {\n readonly sessionId: string;\n readonly path: string;\n readonly cleanupEligible: boolean;\n readonly cleanupStatus: DoctorCleanupStatus;\n}\n\nexport interface DoctorPortFinding {\n readonly port: number;\n readonly pids: readonly number[];\n readonly ownerStatus: \"found\" | \"unverified\";\n readonly reason?: string;\n}\n\nexport type DoctorArtifactKind =\n | \"state-temp\"\n | \"state-lock\"\n | \"state-recovery\"\n | \"stop-intent\"\n | \"corrupt-backup\";\n\nexport interface DoctorArtifactFinding {\n readonly kind: DoctorArtifactKind;\n readonly path: string;\n readonly ageMs: number;\n readonly cleanupEligible: boolean;\n readonly cleanupStatus: DoctorCleanupStatus;\n readonly cleanupError?: string;\n}\n\nexport interface DoctorLegacyFinding {\n readonly statePath: string;\n readonly statePresent: boolean;\n readonly homesPath: string;\n readonly homesPresent: boolean;\n readonly warning?: string;\n readonly manualRemovalCommand?: string;\n}\n\nexport interface DoctorReport {\n readonly sessions: readonly DoctorSessionFinding[];\n readonly orphanHomes: readonly DoctorHomeFinding[];\n readonly unclaimedPorts: readonly DoctorPortFinding[];\n readonly artifacts: readonly DoctorArtifactFinding[];\n readonly legacy: DoctorLegacyFinding;\n readonly warnings: readonly string[];\n readonly cleanedPaths: readonly string[];\n}\n\nexport interface DoctorOptions {\n readonly cleanup?: boolean;\n}\n\ninterface StateReadResult {\n readonly state: StateFile;\n readonly warnings: readonly string[];\n readonly homeCleanupSafe: boolean;\n}\n\ninterface LockOwner {\n readonly hostname: string;\n readonly pid: number;\n readonly processIdentity?: string;\n readonly token: string;\n}\n\ninterface ArtifactCandidate {\n readonly kind: DoctorArtifactKind;\n readonly path: string;\n readonly ageMs: number;\n readonly cleanupEligible: boolean;\n readonly fingerprint: string;\n readonly sessionId?: string;\n}\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const value: unknown = Reflect.get(error, \"code\");\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction emptyState(): StateFile {\n return { version: \"2\", sessions: [] };\n}\n\nasync function readDoctorState(): Promise<StateReadResult> {\n let raw: string;\n try {\n raw = await readFile(stateFilePath(), \"utf8\");\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return { state: emptyState(), warnings: [], homeCleanupSafe: true };\n }\n return {\n state: emptyState(),\n warnings: [`Could not read debugger state: ${errorMessage(error)}`],\n homeCleanupSafe: false,\n };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch {\n return {\n state: emptyState(),\n warnings: [\"Debugger state contains invalid JSON.\"],\n homeCleanupSafe: false,\n };\n }\n const decoded = decodeStateFileDetailed(parsed);\n if (decoded.kind === \"invalid-file\") {\n return {\n state: emptyState(),\n warnings: [`Debugger state is invalid: ${decoded.reason}.`],\n homeCleanupSafe: false,\n };\n }\n return {\n state: decoded.state,\n warnings: decoded.dropped.map((reason) => `Dropped state entry: ${reason}.`),\n homeCleanupSafe: decoded.dropped.length === 0,\n };\n}\n\nasync function inspectSessions(\n sessions: readonly ActiveSession[],\n): Promise<readonly DoctorSessionFinding[]> {\n const local = sessions.filter((session) => session.hostname === hostname());\n return await Promise.all(local.map(async (session): Promise<DoctorSessionFinding> => {\n try {\n return { session, health: await inspectSessionHealth(session) };\n } catch (error: unknown) {\n return {\n session,\n health: {\n status: \"unverified\",\n reason: `health inspection failed: ${errorMessage(error)}`,\n },\n };\n }\n }));\n}\n\nasync function readDirectory(path: string): Promise<readonly Dirent[]> {\n try {\n return await readdir(path, { withFileTypes: true });\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function findOrphanHomes(\n sessions: readonly ActiveSession[],\n cleanup: boolean,\n): Promise<readonly DoctorHomeFinding[]> {\n const root = join(saptoolsDir(), CF_DEBUGGER_HOMES_DIRNAME);\n const claimed = new Set(sessions.map((session) => session.sessionId));\n const entries = await readDirectory(root);\n const orphans = entries\n .filter((entry) => entry.isDirectory() && !claimed.has(entry.name))\n .sort((left, right) => left.name.localeCompare(right.name));\n return await Promise.all(orphans.map(async (entry): Promise<DoctorHomeFinding> => {\n const path = join(root, entry.name);\n const cleanupEligible = isOwnedSessionCfHomeDir(entry.name, path);\n if (!cleanup) {\n return { sessionId: entry.name, path, cleanupEligible, cleanupStatus: \"not-requested\" };\n }\n if (!cleanupEligible) {\n return { sessionId: entry.name, path, cleanupEligible, cleanupStatus: \"not-eligible\" };\n }\n const cleanupStatus = await cleanupOrphanHome(entry.name, path);\n return {\n sessionId: entry.name,\n path,\n cleanupEligible,\n cleanupStatus,\n };\n }));\n}\n\nasync function cleanupOrphanHome(\n sessionId: string,\n path: string,\n): Promise<DoctorCleanupStatus> {\n try {\n return await withFileLock(\n stateLockPath(),\n async (): Promise<DoctorCleanupStatus> => {\n const current = await readDoctorState();\n if (\n !current.homeCleanupSafe ||\n current.state.sessions.some((session) => session.sessionId === sessionId)\n ) {\n return \"skipped\";\n }\n return await tryRemoveOwnedSessionCfHome(sessionId, path)\n ? \"removed\"\n : \"failed\";\n },\n );\n } catch {\n return \"failed\";\n }\n}\n\nasync function mapConcurrent<T, Result>(\n values: readonly T[],\n concurrency: number,\n work: (value: T) => Promise<Result | undefined>,\n): Promise<readonly Result[]> {\n const results: Result[] = [];\n let nextIndex = 0;\n const worker = async (): Promise<void> => {\n for (;;) {\n const index = nextIndex;\n nextIndex += 1;\n const value = values[index];\n if (value === undefined) {\n return;\n }\n const result = await work(value);\n if (result !== undefined) {\n results.push(result);\n }\n }\n };\n const workerCount = Math.min(concurrency, values.length);\n await Promise.all(Array.from({ length: workerCount }, worker));\n return results;\n}\n\nfunction unclaimedManagedPorts(sessions: readonly ActiveSession[]): readonly number[] {\n const localClaims = new Set(\n sessions\n .filter((session) => session.hostname === hostname())\n .map((session) => session.localPort),\n );\n const ports: number[] = [];\n for (let port = MANAGED_PORT_MIN; port <= MANAGED_PORT_MAX; port += 1) {\n if (!localClaims.has(port)) {\n ports.push(port);\n }\n }\n return ports;\n}\n\nasync function inspectUnclaimedPort(port: number): Promise<DoctorPortFinding | undefined> {\n if (!(await isPortListening(port))) {\n return undefined;\n }\n const inspection = await inspectListeningProcesses(port);\n if (inspection.status === \"found\") {\n return { port, pids: inspection.pids, ownerStatus: \"found\" };\n }\n if (inspection.status === \"unverified\") {\n return {\n port,\n pids: [],\n ownerStatus: \"unverified\",\n reason: inspection.reason,\n };\n }\n return undefined;\n}\n\nasync function findUnclaimedPorts(\n sessions: readonly ActiveSession[],\n): Promise<readonly DoctorPortFinding[]> {\n const findings = await mapConcurrent(\n unclaimedManagedPorts(sessions),\n PORT_SCAN_CONCURRENCY,\n inspectUnclaimedPort,\n );\n return [...findings].sort((left, right) => left.port - right.port);\n}\n\nfunction artifactKind(name: string): DoctorArtifactKind | undefined {\n if (name === CF_DEBUGGER_LOCK_FILENAME) {\n return \"state-lock\";\n }\n if (name === `${CF_DEBUGGER_LOCK_FILENAME}.recovery`) {\n return \"state-recovery\";\n }\n if (\n name.startsWith(`${CF_DEBUGGER_STATE_FILENAME}.`)\n && name.endsWith(\".tmp\")\n ) {\n return \"state-temp\";\n }\n if (\n name.startsWith(CF_DEBUGGER_STOP_INTENT_PREFIX)\n && name.endsWith(\".stop\")\n ) {\n return \"stop-intent\";\n }\n return name.startsWith(`${CF_DEBUGGER_STATE_FILENAME}.corrupt-`)\n ? \"corrupt-backup\"\n : undefined;\n}\n\nfunction parseLockOwner(raw: string): LockOwner | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return undefined;\n }\n const ownerHostname: unknown = Reflect.get(parsed, \"hostname\");\n const pid: unknown = Reflect.get(parsed, \"pid\");\n const processIdentity: unknown = Reflect.get(parsed, \"processIdentity\");\n const token: unknown = Reflect.get(parsed, \"token\");\n if (\n typeof ownerHostname !== \"string\"\n || typeof pid !== \"number\"\n || !Number.isSafeInteger(pid)\n || pid <= 0\n || (\n processIdentity !== undefined &&\n (typeof processIdentity !== \"string\" || processIdentity.length === 0)\n )\n || typeof token !== \"string\"\n ) {\n return undefined;\n }\n return {\n hostname: ownerHostname,\n pid,\n ...(processIdentity === undefined ? {} : { processIdentity }),\n token,\n };\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n nodeProcess.kill(pid, 0);\n return true;\n } catch (error: unknown) {\n return errorCode(error) !== \"ESRCH\";\n }\n}\n\nasync function readLockOwner(path: string): Promise<LockOwner | undefined> {\n try {\n return parseLockOwner(await readFile(path, \"utf8\"));\n } catch {\n return undefined;\n }\n}\n\nasync function lockCleanupEligible(path: string, ageMs: number): Promise<boolean> {\n if (ageMs < STALE_LOCK_AGE_MS) {\n return false;\n }\n const owner = await readLockOwner(path);\n if (owner?.hostname === hostname()) {\n if (!isPidAlive(owner.pid)) {\n return true;\n }\n if (owner.processIdentity !== undefined) {\n const identity = await inspectProcessIdentity(owner.pid, owner.processIdentity);\n if (identity === \"mismatch\") {\n return true;\n }\n if (identity === \"match\") {\n return false;\n }\n }\n return ageMs >= FOREIGN_OR_MALFORMED_LOCK_AGE_MS;\n }\n return ageMs >= FOREIGN_OR_MALFORMED_LOCK_AGE_MS;\n}\n\nfunction artifactFingerprint(stats: Stats): string {\n return [\n stats.dev.toString(),\n stats.ino.toString(),\n stats.size.toString(),\n stats.mtimeMs.toString(),\n ].join(\":\");\n}\n\nasync function inspectArtifact(\n entry: Dirent,\n now: number,\n claimedSessionIds: ReadonlySet<string>,\n stopIntentCleanupSafe: boolean,\n): Promise<ArtifactCandidate | undefined> {\n const kind = artifactKind(entry.name);\n if (kind === undefined) {\n return undefined;\n }\n const path = join(saptoolsDir(), entry.name);\n const stats = await lstat(path);\n const ageMs = Math.max(0, now - stats.mtimeMs);\n const regularFile = stats.isFile();\n let sessionId: string | undefined;\n let cleanupEligible = regularFile && kind === \"state-temp\" && ageMs >= STALE_TEMP_AGE_MS;\n if (regularFile && kind === \"stop-intent\") {\n sessionId = entry.name.slice(\n CF_DEBUGGER_STOP_INTENT_PREFIX.length,\n -\".stop\".length,\n );\n cleanupEligible = stopIntentCleanupSafe &&\n ageMs >= STALE_TEMP_AGE_MS &&\n !claimedSessionIds.has(sessionId);\n }\n if (regularFile && (kind === \"state-lock\" || kind === \"state-recovery\")) {\n cleanupEligible = await lockCleanupEligible(path, ageMs);\n }\n return {\n kind,\n path,\n ageMs,\n cleanupEligible,\n fingerprint: artifactFingerprint(stats),\n ...(sessionId === undefined ? {} : { sessionId }),\n };\n}\n\nasync function candidateStillMatches(candidate: ArtifactCandidate): Promise<boolean> {\n try {\n const stats = await lstat(candidate.path);\n return artifactFingerprint(stats) === candidate.fingerprint;\n } catch {\n return false;\n }\n}\n\nasync function cleanupArtifact(\n candidate: ArtifactCandidate,\n): Promise<{ readonly status: DoctorCleanupStatus; readonly error?: string }> {\n if (!candidate.cleanupEligible) {\n return { status: \"not-eligible\" };\n }\n try {\n if (candidate.kind === \"stop-intent\" && candidate.sessionId !== undefined) {\n return await withFileLock(\n stateLockPath(),\n async (): Promise<{ readonly status: DoctorCleanupStatus }> => {\n const current = await readDoctorState();\n if (\n !current.homeCleanupSafe ||\n current.state.sessions.some(\n (session) => session.sessionId === candidate.sessionId,\n ) ||\n !(await candidateStillMatches(candidate))\n ) {\n return { status: \"skipped\" };\n }\n await unlink(candidate.path);\n return { status: \"removed\" };\n },\n );\n }\n if (!(await candidateStillMatches(candidate))) {\n return { status: \"skipped\" };\n }\n await unlink(candidate.path);\n return { status: \"removed\" };\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return { status: \"skipped\" };\n }\n return { status: \"failed\", error: errorMessage(error) };\n }\n}\n\nasync function findArtifacts(\n cleanup: boolean,\n sessions: readonly ActiveSession[],\n stopIntentCleanupSafe: boolean,\n): Promise<readonly DoctorArtifactFinding[]> {\n const entries = await readDirectory(saptoolsDir());\n const claimedSessionIds = new Set(sessions.map((session) => session.sessionId));\n const inspected = await Promise.all(\n entries.map(async (entry): Promise<ArtifactCandidate | undefined> =>\n await inspectArtifact(entry, Date.now(), claimedSessionIds, stopIntentCleanupSafe)\n ),\n );\n const candidates = inspected.filter(\n (candidate): candidate is ArtifactCandidate => candidate !== undefined,\n ).sort((left, right) => left.path.localeCompare(right.path));\n const findings: DoctorArtifactFinding[] = [];\n for (const candidate of candidates) {\n const result = cleanup\n ? await cleanupArtifact(candidate)\n : {\n status: candidate.cleanupEligible ? \"not-requested\" : \"not-eligible\",\n } satisfies { readonly status: DoctorCleanupStatus };\n findings.push({\n kind: candidate.kind,\n path: candidate.path,\n ageMs: candidate.ageMs,\n cleanupEligible: candidate.cleanupEligible,\n cleanupStatus: result.status,\n ...(result.error === undefined ? {} : { cleanupError: result.error }),\n });\n }\n return findings;\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await lstat(path);\n return true;\n } catch (error: unknown) {\n if (errorCode(error) === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", \"'\\\"'\\\"'\")}'`;\n}\n\nasync function findLegacyArtifacts(): Promise<DoctorLegacyFinding> {\n const statePath = join(saptoolsDir(), LEGACY_STATE_FILENAME);\n const lockPath = join(saptoolsDir(), LEGACY_LOCK_FILENAME);\n const homesPath = join(saptoolsDir(), LEGACY_HOMES_DIRNAME);\n const [statePresent, homesPresent] = await Promise.all([\n pathExists(statePath),\n pathExists(homesPath),\n ]);\n if (!statePresent && !homesPresent) {\n return { statePath, statePresent, homesPath, homesPresent };\n }\n const command = `rm -rf -- ${shellQuote(homesPath)} ${shellQuote(statePath)} ${shellQuote(lockPath)}`;\n return {\n statePath,\n statePresent,\n homesPath,\n homesPresent,\n warning:\n \"Legacy v1 debugger homes may contain live CF refresh and access tokens. \" +\n \"Confirm no v1 tunnel is running before removing them.\",\n manualRemovalCommand: command,\n };\n}\n\nfunction reportWarnings(\n stateWarnings: readonly string[],\n orphanHomes: readonly DoctorHomeFinding[],\n unclaimedPorts: readonly DoctorPortFinding[],\n legacy: DoctorLegacyFinding,\n): readonly string[] {\n const warnings = [...stateWarnings];\n if (orphanHomes.length > 0) {\n warnings.push(`${orphanHomes.length.toString()} orphaned v2 CF home(s) found.`);\n }\n if (unclaimedPorts.length > 0) {\n warnings.push(`${unclaimedPorts.length.toString()} unclaimed managed-port listener(s) found.`);\n }\n if (legacy.warning !== undefined) {\n warnings.push(legacy.warning);\n }\n return warnings;\n}\n\nexport async function runDoctor(options: DoctorOptions = {}): Promise<DoctorReport> {\n const cleanup = options.cleanup === true;\n const stateResult = await readDoctorState();\n const homeCleanup = cleanup && stateResult.homeCleanupSafe;\n const [sessions, orphanHomes, unclaimedPorts, artifacts, legacy] = await Promise.all([\n inspectSessions(stateResult.state.sessions),\n findOrphanHomes(stateResult.state.sessions, homeCleanup),\n findUnclaimedPorts(stateResult.state.sessions),\n findArtifacts(cleanup, stateResult.state.sessions, stateResult.homeCleanupSafe),\n findLegacyArtifacts(),\n ]);\n const cleanedPaths = [\n ...orphanHomes\n .filter((finding) => finding.cleanupStatus === \"removed\")\n .map((finding) => finding.path),\n ...artifacts\n .filter((finding) => finding.cleanupStatus === \"removed\")\n .map((finding) => finding.path),\n ];\n return {\n sessions,\n orphanHomes,\n unclaimedPorts,\n artifacts,\n legacy,\n warnings: [\n ...reportWarnings(stateResult.warnings, orphanHomes, unclaimedPorts, legacy),\n ...(cleanup && !stateResult.homeCleanupSafe\n ? [\n \"Skipped orphan-home and stop-intent cleanup because debugger state was incomplete or invalid.\",\n ]\n : []),\n ],\n cleanedPaths,\n };\n}\n","import { hostname as getHostname } from \"node:os\";\nimport nodeProcess from \"node:process\";\n\nimport { isOwnedSessionCfHomeDir } from \"../paths.js\";\nimport { inspectListeningProcesses, inspectPortOwnership } from \"../port.js\";\nimport {\n clearSessionStopIntent,\n isPidAlive,\n isPidOrGroupAlive,\n matchesKey,\n readActiveSessions,\n readSessionSnapshot,\n removeSession,\n requestSessionStop,\n writeSessionStopIntent,\n} from \"../state.js\";\nimport type { ActiveSession, SessionKey } from \"../types.js\";\nimport { CfDebuggerError } from \"../types.js\";\n\nimport {\n MAX_STARTUP_TIMEOUT_MS,\n STARTUP_STALE_SLACK_MS,\n} from \"./constants.js\";\nimport { inspectProcessIdentity } from \"./process-identity.js\";\nimport type { ProcessIdentityVerdict } from \"./process-identity.js\";\nimport {\n terminatePidOrGroup,\n type TerminationOutcome,\n type TerminationVerifier,\n} from \"./processes.js\";\nimport { removeOwnedSessionCfHome } from \"./session-home.js\";\n\nexport interface StopOptions {\n readonly sessionId?: string;\n readonly key?: SessionKey;\n readonly force?: boolean;\n}\n\nexport interface StopDebuggerResult extends ActiveSession {\n readonly stale: boolean;\n readonly pending: boolean;\n readonly forced: boolean;\n readonly warning?: string;\n}\n\nexport interface StopAllOutcome {\n readonly sessionId: string;\n readonly app: string;\n readonly status: \"failed\" | \"pending\" | \"stale\" | \"stopped\";\n readonly result?: StopDebuggerResult;\n readonly error?: CfDebuggerError;\n}\n\nexport interface StopAllResult {\n readonly outcomes: readonly StopAllOutcome[];\n readonly failed: number;\n readonly pending: number;\n readonly stale: number;\n readonly stopped: number;\n}\n\nfunction findMatchingSession(\n sessions: readonly ActiveSession[],\n options: StopOptions,\n): ActiveSession | undefined {\n if (options.sessionId !== undefined) {\n return sessions.find((session) => session.sessionId === options.sessionId);\n }\n if (options.key === undefined) {\n return undefined;\n }\n const key = options.key;\n const matches = sessions.filter((session) => matchesKey(session, key));\n if (matches.length > 1) {\n throw new CfDebuggerError(\n \"SESSION_AMBIGUOUS\",\n \"Multiple debugger sessions match this target. Pass --session-id, --api-endpoint, or --node-pid.\",\n );\n }\n return matches[0];\n}\n\nfunction startupAgeLimit(session: ActiveSession): number {\n return (session.startupTimeoutMs ?? MAX_STARTUP_TIMEOUT_MS) + STARTUP_STALE_SLACK_MS;\n}\n\nfunction startupExpired(session: ActiveSession): boolean {\n const startedAt = Date.parse(session.startedAt);\n return Number.isNaN(startedAt) || Date.now() - startedAt > startupAgeLimit(session);\n}\n\ntype RecordedProcessVerdict = \"dead\" | ProcessIdentityVerdict;\n\nasync function inspectRecordedProcess(\n pid: number,\n identity: string | undefined,\n): Promise<RecordedProcessVerdict> {\n if (!isPidAlive(pid)) {\n return \"dead\";\n }\n return await inspectProcessIdentity(pid, identity);\n}\n\nasync function inspectController(target: ActiveSession): Promise<RecordedProcessVerdict> {\n const controllerPid = target.controllerPid ?? target.pid;\n return await inspectRecordedProcess(controllerPid, target.controllerProcessIdentity);\n}\n\nexport async function ownsRecordedTunnel(target: ActiveSession): Promise<boolean> {\n const tunnelPid = target.tunnelPid;\n if (tunnelPid === undefined) {\n return false;\n }\n const processVerdict = await inspectRecordedProcess(\n tunnelPid,\n target.tunnelProcessIdentity,\n );\n if (processVerdict !== \"match\") {\n return false;\n }\n return (await inspectPortOwnership(target.localPort, tunnelPid)).status === \"owned\";\n}\n\nasync function terminateVerifiedTunnel(target: ActiveSession): Promise<TerminationOutcome> {\n const tunnelPid = target.tunnelPid;\n if (tunnelPid === undefined || tunnelPid === nodeProcess.pid) {\n return tunnelPid === nodeProcess.pid ? \"still-alive\" : \"terminated\";\n }\n try {\n const verifyBeforeSignal: TerminationVerifier = async (signal): Promise<boolean> => {\n if (signal === \"SIGTERM\" || target.tunnelProcessIdentity === undefined) {\n return await ownsRecordedTunnel(target);\n }\n return await inspectRecordedProcess(\n tunnelPid,\n target.tunnelProcessIdentity,\n ) === \"match\";\n };\n return await terminatePidOrGroup(\n tunnelPid,\n undefined,\n undefined,\n verifyBeforeSignal,\n );\n } catch {\n return \"still-alive\";\n }\n}\n\nasync function terminateVerifiedTunnelAndConfirm(\n target: ActiveSession,\n recordExpectedStop = false,\n): Promise<void> {\n if (recordExpectedStop) {\n await writeSessionStopIntent(target.sessionId);\n }\n if (!(await ownsRecordedTunnel(target))) {\n throw ownershipError(target, \"recorded tunnel no longer owns the local port\");\n }\n const termination = await terminateVerifiedTunnel(target);\n if (termination !== \"terminated\" || await ownsRecordedTunnel(target)) {\n throw new CfDebuggerError(\n \"TUNNEL_TERMINATION_FAILED\",\n termination === \"ownership-lost\"\n ? `Tunnel ownership for session ${target.sessionId} could not be reverified during termination; ` +\n \"no unverified process was signalled and state was retained.\"\n : `Tunnel process for session ${target.sessionId} did not terminate; state was retained.`,\n );\n }\n}\n\nasync function removeOwnedSession(\n target: ActiveSession,\n stale: boolean,\n forced = false,\n warning?: string,\n preserveStopIntent = false,\n): Promise<StopDebuggerResult> {\n let resultWarning = warning;\n if (isOwnedSessionCfHomeDir(target.sessionId, target.cfHomeDir)) {\n await removeOwnedSessionCfHome(target.sessionId, target.cfHomeDir);\n } else {\n const skipped = `State referenced unowned CF home ${target.cfHomeDir}; it was not deleted.`;\n resultWarning = resultWarning === undefined ? skipped : `${resultWarning} ${skipped}`;\n }\n const removed = await removeSession(target.sessionId);\n if (!preserveStopIntent) {\n await clearSessionStopIntent(target.sessionId);\n }\n return {\n ...(removed ?? target),\n stale,\n pending: false,\n forced,\n ...(resultWarning === undefined ? {} : { warning: resultWarning }),\n };\n}\n\nfunction ownershipError(target: ActiveSession, detail: string): CfDebuggerError {\n return new CfDebuggerError(\n \"TUNNEL_OWNERSHIP_UNVERIFIED\",\n `Cannot safely stop session ${target.sessionId}: ${detail}. ` +\n `No process was signalled. Retry with --force to forget the record and its owned CF home.`,\n );\n}\n\nfunction forcedWarning(target: ActiveSession, detail: string): string {\n return `Forced state cleanup abandoned PID ${String(target.tunnelPid ?? target.controllerPid ?? target.pid)} ` +\n `and local port ${target.localPort.toString()}: ${detail}. No unverified process was signalled.`;\n}\n\nasync function forceRemoveUnverified(\n target: ActiveSession,\n detail: string,\n preserveStopIntent = false,\n): Promise<StopDebuggerResult> {\n return await removeOwnedSession(\n target,\n true,\n true,\n forcedWarning(target, detail),\n preserveStopIntent,\n );\n}\n\nasync function stopReadySession(\n target: ActiveSession,\n force: boolean,\n): Promise<StopDebuggerResult> {\n if (await ownsRecordedTunnel(target)) {\n await terminateVerifiedTunnelAndConfirm(target, true);\n return await removeOwnedSession(target, false, false, undefined, true);\n }\n const tunnelVerdict = target.tunnelPid === undefined\n ? \"dead\"\n : await inspectRecordedProcess(target.tunnelPid, target.tunnelProcessIdentity);\n const tunnelDead = target.tunnelPid === undefined ||\n !isPidOrGroupAlive(target.tunnelPid) ||\n tunnelVerdict === \"mismatch\";\n const ownership = target.tunnelPid === undefined\n ? await inspectListeningProcesses(target.localPort)\n : await inspectPortOwnership(target.localPort, target.tunnelPid);\n if (tunnelDead && ownership.status === \"not-listening\") {\n return await removeOwnedSession(target, true, false, undefined, true);\n }\n const detail = ownership.status === \"unverified\"\n ? ownership.reason\n : ownership.status === \"not-owned\"\n ? `local port ${target.localPort.toString()} belongs to PID(s) ${ownership.pids.join(\", \")}`\n : tunnelVerdict === \"unavailable\"\n ? \"the recorded tunnel identity could not be inspected\"\n : \"the recorded tunnel could not be proven dead and owned\";\n if (force) {\n return await forceRemoveUnverified(target, detail, true);\n }\n throw ownershipError(target, detail);\n}\n\nasync function stopStartingSession(\n target: ActiveSession,\n force: boolean,\n): Promise<StopDebuggerResult> {\n const expired = startupExpired(target);\n const controllerVerdict = await inspectController(target);\n if (!force && !expired && controllerVerdict === \"match\") {\n return { ...target, stale: false, pending: true, forced: false };\n }\n if (await ownsRecordedTunnel(target)) {\n await terminateVerifiedTunnelAndConfirm(target);\n return await removeOwnedSession(target, false, false, undefined, true);\n }\n const tunnelAlive = target.tunnelPid !== undefined && isPidOrGroupAlive(target.tunnelPid);\n const listening = await inspectListeningProcesses(target.localPort);\n const detail = listening.status === \"unverified\"\n ? listening.reason\n : listening.status === \"found\"\n ? `local port ${target.localPort.toString()} belongs to PID(s) ${listening.pids.join(\", \")}`\n : controllerVerdict === \"unavailable\"\n ? \"the startup controller identity could not be inspected\"\n : \"the recorded startup owner could not be verified as a tunnel\";\n if (force) {\n return await forceRemoveUnverified(\n target,\n detail,\n controllerVerdict === \"match\",\n );\n }\n if (\n !tunnelAlive &&\n listening.status === \"not-listening\" &&\n (expired || controllerVerdict !== \"unavailable\")\n ) {\n return await removeOwnedSession(target, true);\n }\n throw ownershipError(target, detail);\n}\n\nexport async function stopDebugger(\n options: StopOptions,\n): Promise<StopDebuggerResult | undefined> {\n const localSessions = (await readSessionSnapshot()).filter(\n (session) => session.hostname === getHostname(),\n );\n const target = findMatchingSession(localSessions, options);\n if (target === undefined) {\n return undefined;\n }\n const claim = await requestSessionStop(target.sessionId);\n if (claim === undefined) {\n return undefined;\n }\n return claim.previousStatus === \"ready\"\n ? await stopReadySession(claim.session, options.force === true)\n : await stopStartingSession(claim.session, options.force === true);\n}\n\nfunction outcomeForResult(result: StopDebuggerResult): StopAllOutcome {\n return {\n sessionId: result.sessionId,\n app: result.app,\n status: result.pending ? \"pending\" : result.stale ? \"stale\" : \"stopped\",\n result,\n };\n}\n\nfunction outcomeForError(session: ActiveSession, error: unknown): StopAllOutcome {\n const normalized = error instanceof CfDebuggerError\n ? error\n : new CfDebuggerError(\n \"STOP_FAILED\",\n error instanceof Error ? error.message : String(error),\n );\n return {\n sessionId: session.sessionId,\n app: session.app,\n status: \"failed\",\n error: normalized,\n };\n}\n\nfunction outcomeForMissing(session: ActiveSession): StopAllOutcome {\n return {\n sessionId: session.sessionId,\n app: session.app,\n status: \"stale\",\n };\n}\n\nfunction summarizeOutcomes(outcomes: readonly StopAllOutcome[]): StopAllResult {\n const count = (status: StopAllOutcome[\"status\"]): number =>\n outcomes.filter((outcome) => outcome.status === status).length;\n return {\n outcomes,\n failed: count(\"failed\"),\n pending: count(\"pending\"),\n stale: count(\"stale\"),\n stopped: count(\"stopped\"),\n };\n}\n\nexport async function stopAllDebuggers(force = false): Promise<StopAllResult> {\n const sessions = (await readSessionSnapshot()).filter(\n (session) => session.hostname === getHostname(),\n );\n const outcomes: StopAllOutcome[] = [];\n for (const session of sessions) {\n try {\n const result = await stopDebugger({ sessionId: session.sessionId, force });\n outcomes.push(\n result === undefined ? outcomeForMissing(session) : outcomeForResult(result),\n );\n } catch (error: unknown) {\n outcomes.push(outcomeForError(session, error));\n }\n }\n return summarizeOutcomes(outcomes);\n}\n\nexport async function listSessions(): Promise<readonly ActiveSession[]> {\n return await readActiveSessions();\n}\n\nexport async function getSession(key: SessionKey): Promise<ActiveSession | undefined> {\n const sessions = await readActiveSessions();\n return findMatchingSession(sessions, { key });\n}\n"],"mappings":";AA+EO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EAET,YAAY,MAAc,SAAiB,QAAiB;AACjE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,QAAI,WAAW,QAAW;AACxB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AACF;;;ACpFA,IAAM,qBAAqB;AAE3B,IAAM,uBAAyD;AAAA,EAC7D,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,SAAS,sBAAsB,WAA2B;AACxD,QAAM,SAAS,UAAU,WAAW,IAAI,IACpC,yBACA;AACJ,SAAO,kBAAkB,SAAS,IAAI,MAAM;AAC9C;AAEO,SAAS,mBACd,WACA,UACA,WACQ;AACR,MAAI,aAAa,UAAa,aAAa,IAAI;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,CAAC,mBAAmB,KAAK,SAAS,GAAG;AACvC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,uBAAuB,KAAK,UAAU,SAAS,CAAC;AAAA,IAClD;AAAA,EACF;AACA,QAAM,WAAW,OAAO,OAAO,sBAAsB,SAAS,IAC1D,qBAAqB,SAAS,IAC9B;AACJ,MAAI,aAAa,QAAW;AAC1B,WAAO;AAAA,EACT;AACA,QAAM,cAAc,sBAAsB,SAAS;AACnD;AAAA,IACE,cAAc,SAAS,sEAAsE,WAAW;AAAA,EAC1G;AACA,SAAO;AACT;AAEO,SAAS,sBAAyC;AACvD,SAAO,OAAO,KAAK,oBAAoB;AACzC;;;AC5GA,SAAS,gBAAgB;AAKzB,OAAO,iBAAiB;AAIxB,IAAM,aAAa,KAAK,OAAO;AACxB,IAAM,gCAAgC;AACtC,IAAM,kCAAkC;AAC/C,IAAM,eAAe;AACrB,IAAM,qBAAqB;AAmDpB,SAAS,SAAS,QAAmC;AAC1D,SAAO,EAAE,GAAG,YAAY,KAAK,UAAU,SAAS,SAAS,OAAO;AAClE;AAEO,SAAS,WAAW,SAAgC;AACzD,SAAO,QAAQ,WAAW,YAAY,IAAI,oBAAoB,KAAK;AACrE;AAEO,SAAS,oBAAoB,MAAc,QAAmC;AACnF,SAAO,yBAAyB,MAAM,EACnC,OAAO,CAAC,SAAS,UAAU,QAAQ,MAAM,KAAK,EAAE,KAAK,YAAY,GAAG,IAAI;AAC7E;AAEO,SAAS,yBAAyB,QAA8C;AACrF,SAAO,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC,CAAC,CAAC,EAC3D,KAAK,CAAC,MAAM,UAAU,MAAM,SAAS,KAAK,MAAM;AACrD;AAEA,SAAS,WAAW,SAAyC;AAC3D,MAAI,QAAQ,eAAe,UAAa,KAAK,IAAI,KAAK,QAAQ,YAAY;AACxE,UAAM,YAAY,QAAQ;AAC1B,UAAM,WAAW,cAAc,SAAY,eAAe,IAAI,YAAY,KAAM,SAAS,CAAC;AAC1F,WAAO,IAAI;AAAA,MACT;AAAA,MACA,iCAAiC,QAAQ,oBAAoB,QAAQ,SAAS,cAAc;AAAA,IAC9F;AAAA,EACF;AACA,SAAO,IAAI,gBAAgB,WAAW,6BAA6B;AACrE;AAEA,SAAS,aACP,SACA,SACe;AACf,MAAI,QAAQ,QAAQ,SAAS;AAC3B,WAAO,QAAQ,OAAO,WAAW,OAAO,CAAC;AAAA,EAC3C;AACA,SAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,UAAM,UAAU,MAAY;AAC1B,mBAAa,KAAK;AAClB,aAAO,WAAW,OAAO,CAAC;AAAA,IAC5B;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ,QAAQ,oBAAoB,SAAS,OAAO;AACpD,cAAQ;AAAA,IACV,GAAG,OAAO;AACV,YAAQ,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EACnE,CAAC;AACH;AAEA,SAAS,mBACP,MACA,iBACQ;AAER,SAAO,oBAAoB,KAAK,KAAK,GAAG,GAAG,eAAe;AAC5D;AAEA,SAAS,eAAe,OAAoC;AAC1D,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAAS,mBAAmB,OAAkC;AAC5D,QAAM,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO,QAAQ;AACrE,QAAMA,SAAQ,CAAC,QAAyB,WAAW,SAAY,SAAY,QAAQ,IAAI,QAAQ,GAAG;AAClG,SAAO;AAAA,IACL,MAAM,eAAeA,OAAM,MAAM,CAAC;AAAA,IAClC,QAAQA,OAAM,QAAQ,MAAM;AAAA,IAC5B,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,QAAQ,eAAeA,OAAM,QAAQ,CAAC;AAAA,EACxC;AACF;AAEA,SAAS,uBAAuB,OAAkC;AAGhE,QAAM,aAAa,MAAM,QAAQ,YAAY,KAAK;AAClD,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,QAAQ,KAAK,CAAC,WAAW,WAAW,SAAS,MAAM,CAAC;AAC7D;AAEA,SAAS,sBACP,MACA,OACS;AACT,MAAI,KAAK,CAAC,MAAM,QAAQ;AACtB,WAAO;AAAA,EACT;AACA,QAAM,aAAa,GAAG,MAAM,UAAU,EAAE,IAAI,MAAM,OAAO,GAAG,YAAY;AACxE,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,QAAQ,KAAK,CAAC,WAAW,WAAW,SAAS,MAAM,CAAC,KACzD,kBAAkB,KAAK,UAAU;AACrC;AAEA,SAAS,wBACP,OACA,iBACS;AACT,MAAI,iBAAiB;AAEnB,WAAO;AAAA,EACT;AACA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAQ,MAAM,SAAS,UAAa,aAAa,SAAS,MAAM,IAAI,KAClE,uBAAuB,KAAK;AAChC;AAEA,SAAS,4BAA4B,OAAe,MAAsB;AACxE,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GAAG;AAC9C,UAAM,IAAI;AAAA,MACR;AAAA,MACA,GAAG,IAAI;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,kBACP,SACA,OACsB;AACtB,QAAM,UAAU,OAAO,UAAU,WAAW,EAAE,WAAW,MAAM,IAAI;AACnE,QAAM,gBAAgB;AAAA,IACpB,QAAQ,iBAAiB;AAAA,IACzB;AAAA,EACF;AACA,QAAM,mBAAmB;AAAA,IACvB,QAAQ,aAAa;AAAA,IACrB;AAAA,EACF;AACA,QAAM,aAAa,QAAQ,cAAc,KAAK,IAAI,IAAI;AACtD,MAAI,CAAC,OAAO,cAAc,UAAU,KAAK,cAAc,GAAG;AACxD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,KAAK,QAAQ;AAAA,IACb,iBAAiB,yBAAyB;AAAA,MACxC,GAAI,QAAQ,mBAAmB,CAAC;AAAA,MAChC,GAAI,QAAQ,mBAAmB,CAAC;AAAA,IAClC,CAAC;AAAA,IACD;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,iBACb,MACA,SACA,SACA,WACiB;AACjB,QAAM,SAAS,MAAM,mBAAmB,WAAW,OAAO,GAAG,MAAM;AAAA,IACjE,KAAK;AAAA,MACH,GAAG,SAAS,QAAQ,MAAM;AAAA,MAC1B,GAAG,QAAQ;AAAA,MACX,UAAU;AAAA,MACV,SAAS,QAAQ;AAAA,IACnB;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,EACnE,CAAC;AACD,SAAO,OAAO;AAChB;AAEA,SAAS,cAAc,OAAqB,QAA8B;AACxE,MAAI;AACF,UAAM,KAAK,MAAM;AAAA,EACnB,QAAQ;AAAA,EAER;AACF;AAEA,eAAsB,mBACpB,SACA,MACA,SAC+D;AAC/D,SAAO,MAAM,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC5C,QAAI,UAAU;AACd,UAAM,UAAU,MAAY;AAC1B,mBAAa,KAAK;AAClB,cAAQ,QAAQ,oBAAoB,SAAS,OAAO;AAAA,IACtD;AACA,UAAM,aAAa,CAAC,UAAuB;AACzC,UAAI,SAAS;AACX;AAAA,MACF;AACA,gBAAU;AACV,cAAQ;AACR,aAAO,KAAK;AAAA,IACd;AACA,UAAM,QAAQ,SAAS,SAAS,CAAC,GAAG,IAAI,GAAG;AAAA,MACzC,KAAK,QAAQ;AAAA,MACb,WAAW,QAAQ,aAAa;AAAA,MAChC,UAAU;AAAA,IACZ,GAAG,CAAC,OAAiC,QAAgB,WAAmB;AACtE,UAAI,SAAS;AACX;AAAA,MACF;AACA,gBAAU;AACV,cAAQ;AACR,UAAI,UAAU,QAAQ,QAAQ,QAAQ,YAAY,MAAM;AACtD,gBAAQ,EAAE,QAAQ,OAAO,CAAC;AAC1B;AAAA,MACF;AACA,YAAM,UAAU,SAAS,IAAI,MAAM,sBAAsB;AACzD,cAAQ,IAAI,SAAS,UAAU,MAAM;AACrC,aAAO,OAAO;AAAA,IAChB,CAAC;AACD,UAAM,qBAAqB,CAAC,MAAiC,YAA0B;AACrF,UAAI,SAAS;AACX;AAAA,MACF;AACA,oBAAc,OAAO,SAAS;AAC9B,YAAM,QAAQ,QAAQ;AACtB,YAAM,QAAQ,QAAQ;AACtB,YAAM,UAAU,IAAI,MAAM,OAAO;AACjC,cAAQ,IAAI,SAAS,QAAQ,IAAI;AACjC,cAAQ,IAAI,SAAS,UAAU,IAAI;AACnC,cAAQ,IAAI,SAAS,UAAU,EAAE;AACjC,iBAAW,OAAO;AAAA,IACpB;AACA,UAAM,UAAU,MAAY;AAC1B,yBAAmB,aAAa,sBAAsB;AAAA,IACxD;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,yBAAmB,aAAa,0CAA0C;AAAA,IAC5E,GAAG,QAAQ,SAAS;AACpB,YAAQ,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACjE,QAAI,QAAQ,QAAQ,SAAS;AAC3B,cAAQ;AAAA,IACV;AAAA,EACF,CAAC;AACH;AAEA,SAAS,aAAa,SAAyB;AAC7C,SAAO,KAAK,IAAI,MAAQ,KAAK,KAAK,IAAI,UAAU,GAAG,EAAE,GAAI,kBAAkB;AAC7E;AAEA,SAAS,iBACP,MACA,SACA,iBACiB;AACjB,QAAM,SAAS,oBAAoB,QAAQ,QAAQ,KAAK,KAAK,IAAI,eAAe;AAChF,QAAM,WAAW,oBAAoB,QAAQ,SAAS,eAAe;AACrE,QAAM,SAAS,OAAO,SAAS,IAAI,SAAS;AAC5C,SAAO,IAAI;AAAA,IACT;AAAA,IACA,MAAM,mBAAmB,MAAM,eAAe,CAAC,YAAY,MAAM;AAAA,IACjE;AAAA,EACF;AACF;AAEA,SAAS,aACP,SACA,MACA,iBACiB;AACjB,MAAI,QAAQ,eAAe,QAAW;AACpC,UAAM,YAAY,QAAQ;AAC1B,UAAM,WAAW,cAAc,SAAY,eAAe,IAAI,YAAY,KAAM,SAAS,CAAC;AAC1F,WAAO,IAAI;AAAA,MACT;AAAA,MACA,kDAAkD,QAAQ,oBACrD,QAAQ,SAAS,cAAc;AAAA,IACtC;AAAA,EACF;AACA,SAAO,IAAI;AAAA,IACT;AAAA,IACA,MAAM,mBAAmB,MAAM,eAAe,CAAC;AAAA,EACjD;AACF;AAEA,SAAS,YACP,SACA,MACA,SACA,SACA,aACA,iBACM;AACN,UAAQ,UAAU;AAAA,IAChB;AAAA,IACA,SAAS,MAAM,mBAAmB,MAAM,eAAe,CAAC;AAAA,IACxD;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,MACpB,MACA,SACA,QAA+B,CAAC,GACf;AACjB,MAAI,QAAQ,QAAQ,SAAS;AAC3B,UAAM,WAAW,OAAO;AAAA,EAC1B;AACA,QAAM,UAAU,kBAAkB,SAAS,KAAK;AAChD,MAAI,UAAU;AAEd,aAAS;AACP,UAAM,cAAc,QAAQ,aAAa,KAAK,IAAI;AAClD,QAAI,eAAe,GAAG;AACpB,YAAM,aAAa,SAAS,MAAM,QAAQ,eAAe;AAAA,IAC3D;AACA,eAAW;AACX,UAAM,mBAAmB,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,kBAAkB,WAAW,CAAC;AACpF,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI;AACF,aAAO,MAAM,iBAAiB,MAAM,SAAS,SAAS,gBAAgB;AAAA,IACxE,SAAS,OAAgB;AACvB,YAAM,UAAU,mBAAmB,KAAK;AACxC,UAAI,QAAQ,QAAQ,WAAW,QAAQ,SAAS,aAAa;AAC3D,cAAM,WAAW,OAAO;AAAA,MAC1B;AACA,YAAM,YAAY,KAAK,IAAI,IAAI;AAC/B,YAAM,kBAAkB,QAAQ,UAC9B,YAAY,OAAO;AACrB,UACE,sBAAsB,MAAM,OAAO,KACnC,CAAC,wBAAwB,SAAS,eAAe,GACjD;AACA,cAAM,iBAAiB,MAAM,SAAS,QAAQ,eAAe;AAAA,MAC/D;AACA,YAAM,UAAU,aAAa,OAAO;AACpC,YAAM,iBAAiB,QAAQ,aAAa,KAAK,IAAI;AACrD,UAAI,kBAAkB,SAAS;AAC7B,cAAM,aAAa,SAAS,MAAM,QAAQ,eAAe;AAAA,MAC3D;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV;AACA,YAAM,aAAa,SAAS,OAAO;AAAA,IACrC;AAAA,EACF;AACF;;;ACzaA,IAAM,4BAA4B;AAElC,SAAS,wBAAwB,OAAsB;AACrD,MACE,iBAAiB,oBAChB,MAAM,SAAS,aAAa,MAAM,SAAS,oBAC5C;AACA,UAAM;AAAA,EACR;AACF;AAgBA,eAAsB,MAAM,aAAqB,SAAuC;AACtF,QAAM,MAAM,CAAC,OAAO,WAAW,GAAG,OAAO;AAC3C;AAEA,eAAsB,OACpB,OACA,UACA,SACe;AACf,MAAI;AACF,UAAM,MAAM,CAAC,MAAM,GAAG,SAAS;AAAA,MAC7B,KAAK,EAAE,aAAa,UAAU,aAAa,MAAM;AAAA,MACjD,iBAAiB,CAAC,OAAO,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH,SAAS,OAAgB;AACvB,4BAAwB,KAAK;AAC7B,QAAI,iBAAiB,iBAAiB;AACpC,YAAM,IAAI;AAAA,QACR;AAAA,QACA,GAAG,MAAM,OAAO;AAAA,QAChB,MAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,QACpB,aACA,OACA,UACA,SACe;AACf,MAAI;AACF,UAAM,MAAM,aAAa,OAAO;AAAA,EAClC,SAAS,OAAgB;AACvB,4BAAwB,KAAK;AAC7B,QAAI,iBAAiB,iBAAiB;AACpC,YAAM,IAAI,gBAAgB,mBAAmB,MAAM,SAAS,MAAM,MAAM;AAAA,IAC1E;AACA,UAAM;AAAA,EACR;AACA,QAAM,OAAO,OAAO,UAAU,OAAO;AACvC;AAEA,eAAsB,SACpB,KACA,OACA,SACe;AACf,MAAI;AACF,UAAM,MAAM,CAAC,UAAU,MAAM,KAAK,MAAM,KAAK,GAAG,OAAO;AAAA,EACzD,SAAS,KAAc;AACrB,4BAAwB,GAAG;AAC3B,QAAI,eAAe,iBAAiB;AAClC,YAAM,IAAI,gBAAgB,oBAAoB,IAAI,SAAS,IAAI,MAAM;AAAA,IACvE;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,YAAY,SAAiB,SAA0C;AAC3F,MAAI;AACF,UAAM,MAAM,CAAC,OAAO,OAAO,GAAG,OAAO;AACrC,WAAO;AAAA,EACT,SAAS,KAAc;AACrB,4BAAwB,GAAG;AAC3B,UAAM,SAAS,eAAe,kBAAkB,IAAI,UAAU,KAAK;AACnE,QAAI,OAAO,YAAY,EAAE,SAAS,WAAW,GAAG;AAC9C,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAIA,eAAsB,aACpB,SACA,SAC6B;AAC7B,MAAI;AACF,UAAM,SAAS,MAAM,MAAM,CAAC,eAAe,OAAO,GAAG,OAAO;AAC5D,UAAM,aAAa,OAAO,YAAY;AACtC,QAAI,WAAW,SAAS,wBAAwB,GAAG;AACjD,aAAO;AAAA,IACT;AACA,QAAI,WAAW,SAAS,yBAAyB,GAAG;AAClD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,SAAS,KAAc;AACrB,4BAAwB,GAAG;AAC3B,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,YAAY,SAAiB,SAAuC;AACxF,MAAI;AACF,UAAM,MAAM,CAAC,cAAc,OAAO,GAAG,OAAO;AAAA,EAC9C,SAAS,KAAc;AACrB,4BAAwB,GAAG;AAC3B,QAAI,eAAe,iBAAiB;AAClC,YAAM,IAAI,gBAAgB,mBAAmB,IAAI,SAAS,IAAI,MAAM;AAAA,IACtE;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,aAAa,SAAiB,SAAuC;AACzF,QAAM,MAAM,CAAC,WAAW,OAAO,GAAG,OAAO;AAC3C;AAEA,eAAsB,oBACpB,UAAsC,CAAC,GACD;AACtC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB,QAAQ,WAAW,QAAQ,IAAI,oBAAoB,KAAK;AAAA,MACxD,CAAC,QAAQ;AAAA,MACT;AAAA,QACE,KAAK,EAAE,GAAG,QAAQ,KAAK,GAAG,QAAQ,KAAK,UAAU,QAAQ;AAAA,QACzD,WAAW,KAAK,OAAO;AAAA,QACvB,WAAW,QAAQ,aAAa;AAAA,QAChC,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,MACnE;AAAA,IACF;AACA,WAAO,qBAAqB,MAAM;AAAA,EACpC,SAAS,OAAgB;AACvB,QACE,QAAQ,QAAQ,YAAY,QAC3B,OAAO,UAAU,YAAY,UAAU,QAAQ,QAAQ,IAAI,OAAO,MAAM,MAAM,aAC/E;AACA,YAAM,IAAI,gBAAgB,WAAW,0CAA0C;AAAA,IACjF;AACA,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,IAAI,gBAAgB,oBAAoB,qBAAqB,OAAO,EAAE;AAAA,EAC9E;AACF;AAEO,SAAS,qBAAqB,QAA6C;AAChF,QAAM,SAAS,kBAAkB,MAAM;AACvC,QAAM,cAAc,OAAO,IAAI,cAAc;AAC7C,QAAM,MAAM,OAAO,IAAI,KAAK;AAC5B,QAAM,QAAQ,OAAO,IAAI,OAAO;AAChC,MAAI,CAAC,UAAU,WAAW,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,KAAK,GAAG;AACnE,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,wBAAwB,WAAW;AAClD,SAAO;AAAA,IACL;AAAA,IACA,GAAI,WAAW,SAAY,CAAC,IAAI,EAAE,OAAO;AAAA,IACzC;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,uBACd,QACA,cAAc,6BACN;AACR,MAAI,OAAO,WAAW,QAAW;AAC/B,WAAO,OAAO;AAAA,EAChB;AACA,QAAM,IAAI;AAAA,IACR;AAAA,IACA,4BAA4B,OAAO,WAAW,wCAAwC,WAAW;AAAA,EACnG;AACF;AAEA,SAAS,kBAAkB,QAAqC;AAC9D,SAAO,IAAI;AAAA,IACT,OACG,MAAM,IAAI,EACV,IAAI,CAAC,SAAgD;AACpD,YAAM,YAAY,KAAK,QAAQ,GAAG;AAClC,UAAI,YAAY,GAAG;AACjB,eAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,KAAK,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY;AAAA,QAC5C,KAAK,MAAM,YAAY,CAAC,EAAE,KAAK;AAAA,MACjC;AAAA,IACF,CAAC,EACA,OAAO,CAACC,WAA8CA,WAAU,MAAS;AAAA,EAC9E;AACF;AAEO,SAAS,wBAAwB,aAAyC;AAC/E,QAAM,aAAa,qBAAqB,WAAW;AACnD,QAAM,QAAQ,oBAAoB,EAAE,KAAK,CAAC,QAAQ,qBAAqB,mBAAmB,GAAG,CAAC,MAAM,UAAU;AAC9G,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,SAAO,4BAA4B,UAAU;AAC/C;AAEA,SAAS,qBAAqB,aAA6B;AACzD,SAAO,YAAY,KAAK,EAAE,QAAQ,QAAQ,EAAE,EAAE,YAAY;AAC5D;AAEO,SAAS,4BAA4B,aAAyC;AACnF,QAAM,QAAQ,gGAAgG,KAAK,WAAW;AAC9H,QAAM,YAAY,QAAQ,CAAC;AAC3B,QAAM,SAAS,QAAQ,CAAC;AACxB,MAAI,cAAc,UAAa,WAAW,QAAW;AACnD,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,UAAU,WAAW,IAAI,IAC5C,yBACA;AACJ,SAAO,WAAW,iBAAiB,YAAY;AACjD;AAEA,SAAS,UAAU,OAA4C;AAC7D,SAAO,UAAU,UAAa,MAAM,SAAS;AAC/C;;;ACzPO,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAC5B,IAAM,8BAA8B;AAE3C,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,cAAc;AAkBpB,SAAS,oBAAoB,aAA2B;AACtD,MAAI,YAAY,WAAW,KAAK,YAAY,WAAW,GAAG,KAAK,oBAAoB,WAAW,GAAG;AAC/F,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,UAAwB;AAChD,MAAI,CAAC,OAAO,cAAc,QAAQ,KAAK,WAAW,GAAG;AACnD,UAAM,IAAI,gBAAgB,gBAAgB,+CAA+C;AAAA,EAC3F;AACF;AAEA,SAAS,gBAAgB,SAAmC;AAC1D,MAAI,YAAY,WAAc,CAAC,OAAO,cAAc,OAAO,KAAK,WAAW,IAAI;AAC7E,UAAM,IAAI,gBAAgB,gBAAgB,0CAA0C;AAAA,EACtF;AACF;AAEA,SAAS,mBAAmB,YAA0B;AACpD,MAAI,CAAC,OAAO,cAAc,UAAU,KAAK,aAAa,KAAK,aAAa,OAAQ;AAC9E,UAAM,IAAI,gBAAgB,gBAAgB,oDAAoD;AAAA,EAChG;AACF;AAEO,SAAS,kBAAkB,OAAgD;AAChF,QAAM,eAAe,MAAM,WAAW,oBAAoB,KAAK;AAC/D,QAAM,WAAW,MAAM,YAAY;AACnC,sBAAoB,WAAW;AAC/B,mBAAiB,QAAQ;AACzB,kBAAgB,MAAM,OAAO;AAC7B,SAAO,MAAM,YAAY,SACrB,EAAE,SAAS,aAAa,SAAS,IACjC,EAAE,SAAS,aAAa,UAAU,SAAS,MAAM,QAAQ;AAC/D;AAEA,SAAS,oBAAoB,OAAwB;AACnD,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,OAAO,MAAM,SAAS,KAAK;AAC7B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,0BACd,SACA,aAAa,6BACL;AACR,kBAAgB,OAAO;AACvB,qBAAmB,UAAU;AAC7B,QAAM,gBAAgB,WAAW,SAAS,EAAE,EAAE,YAAY,EAAE,SAAS,GAAG,GAAG;AAC3E,SAAO,sBACJ,QAAQ,0BAA0B,SAAS,SAAS,KAAK,EAAE,EAC3D,WAAW,0BAA0B,aAAa;AACvD;AAEO,SAAS,0BACd,QACA,aAAa,6BACS;AACtB,qBAAmB,UAAU;AAC7B,MAAI,OAAO,WAAW,QAAQ,MAAM,IAAI,kBAAkB;AACxD,UAAM,IAAI,gBAAgB,8BAA8B,gDAAgD;AAAA,EAC1G;AACA,QAAM,UAAU,aAAa,MAAM;AACnC,wBAAsB,SAAS,UAAU;AACzC,QAAM,gBAAgB,cAAc,SAAS,6BAA6B;AAC1E,QAAM,WAAW,cAAc,SAAS,8BAA8B;AACtE,MAAI,CAAC,QAAQ,IAAI,0BAA0B,KAAK,kBAAkB,UAAa,aAAa,eAAe;AACzG,UAAM,IAAI,gBAAgB,uBAAuB,wDAAwD;AAAA,EAC3G;AACA,SAAO,EAAE,cAAc;AACzB;AAEA,SAAS,aAAa,QAA6C;AACjE,QAAM,UAAU,oBAAI,IAAoB;AACxC,aAAW,WAAW,OAAO,MAAM,OAAO,GAAG;AAC3C,UAAM,OAAO,QAAQ,KAAK;AAC1B,QAAI,CAAC,KAAK,WAAW,qBAAqB,GAAG;AAC3C;AAAA,IACF;AACA,UAAM,YAAY,KAAK,QAAQ,GAAG;AAClC,YAAQ,IAAI,YAAY,IAAI,OAAO,KAAK,MAAM,GAAG,SAAS,GAAG,YAAY,IAAI,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC;AAAA,EAC7G;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,SAAsC,YAA0B;AAC7F,MAAI,QAAQ,IAAI,mCAAmC,GAAG;AACpD,UAAM,IAAI,gBAAgB,0BAA0B,2DAA2D;AAAA,EACjH;AACA,QAAM,YAAY,QAAQ,IAAI,mCAAmC;AACjE,MAAI,cAAc,QAAW;AAC3B,UAAM,aAAa,iBAAiB,KAAK,SAAS,IAAI,UAAU,MAAM,GAAG,EAAE,KAAK,IAAI,IAAI;AACxF,UAAM,IAAI,gBAAgB,0BAA0B,0CAA0C,UAAU,4BAA4B;AAAA,EACtI;AACA,QAAM,UAAU,QAAQ,IAAI,iCAAiC;AAC7D,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,gBAAgB,oBAAoB,cAAc,YAAY,OAAO,CAAC,4BAA4B;AAAA,EAC9G;AACA,yBAAuB,SAAS,UAAU;AAC5C;AAEA,SAAS,uBAAuB,SAAsC,YAA0B;AAC9F,QAAM,WAAW,QAAQ,IAAI,mCAAmC;AAChE,MAAI,aAAa,QAAW;AAC1B,UAAM,CAAC,WAAW,WAAW,QAAQ,SAAS,IAAI,SAAS,MAAM,KAAK,CAAC,EAAE,IAAI,WAAW;AACxF,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qBAAqB,QAAQ,wBAAwB,WAAW,SAAS,CAAC,oBAAoB,KAAK;AAAA,IACrG;AAAA,EACF;AACA,QAAM,eAAe,QAAQ,IAAI,kCAAkC;AACnE,MAAI,iBAAiB,QAAW;AAC9B,UAAM,IAAI,gBAAgB,sBAAsB,oCAAoC,YAAY,YAAY,CAAC,GAAG;AAAA,EAClH;AACA,MAAI,QAAQ,IAAI,8BAA8B,GAAG;AAC/C,UAAM,IAAI;AAAA,MACR;AAAA,MACA,sDAAsD,WAAW,SAAS,CAAC;AAAA,IAC7E;AAAA,EACF;AACF;AAEA,SAAS,cAAc,SAAsC,MAAkC;AAC7F,QAAM,MAAM,QAAQ,IAAI,IAAI;AAC5B,MAAI,QAAQ,UAAa,CAAC,YAAY,KAAK,GAAG,GAAG;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,OAAO,SAAS,KAAK,EAAE;AACrC,SAAO,OAAO,cAAc,KAAK,KAAK,QAAQ,IAAI,QAAQ;AAC5D;AAEA,SAAS,YAAY,KAAqB;AACxC,SAAO,YAAY,KAAK,GAAG,IAAI,MAAM;AACvC;AAEA,IAAM,wBAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;;;AC5SX,SAAS,aAA0D;AACnE,OAAOC,kBAAiB;AAExB,SAAS,qBAAqB;AAkB9B,IAAM,2BAA2B;AACjC,IAAM,wBAAwB;AAC9B,IAAM,8BAA8B;AACpC,IAA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","names":["field","field","nodeProcess","nodeProcess","randomUUID","chmod","mkdir","readFile","unlink","writeFile","getHostname","dirname","isAbsolute","nodeProcess","execFile","nodeProcess","execFile","nodeProcess","readFile","process","errorCode","process","readFile","modifiedAt","isAbsolute","field","optionalString","isAbsolute","nodeProcess","execFile","readFile","promisify","execFileAsync","promisify","execFile","errorCode","throwIfAborted","readFile","throwIfAborted","errorCode","nodeProcess","chmod","mkdir","unlink","errorCode","mkdir","chmod","unlink","errorCode","chmod","readFile","randomUUID","dirname","mkdir","writeFile","unlink","nodeProcess","getHostname","isAbsolute","session","access","process","process","chmod","mkdir","nodeProcess","readdir","stat","unlink","getHostname","join","stat","readdir","join","unlink","getHostname","nodeProcess","startupStateAccess","mkdir","chmod","ensurePortAvailable","readFile","readdir","unlink","hostname","join","nodeProcess","STALE_TEMP_AGE_MS","errorCode","emptyState","readFile","hostname","readdir","join","parseLockOwner","isPidAlive","nodeProcess","readLockOwner","unlink","getHostname","nodeProcess","startupAgeLimit","startupExpired","inspectRecordedProcess","nodeProcess","getHostname"]}