openmeld 0.3.125 → 0.3.127

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.
Files changed (24) hide show
  1. package/dist/{add-me-membership-BCGn5T-D.js → add-me-membership-CSOBspmn.js} +2 -2
  2. package/dist/{add-me-membership-BCGn5T-D.js.map → add-me-membership-CSOBspmn.js.map} +1 -1
  3. package/dist/{api-client-foundation-w4Oa06t4.js → api-client-foundation-eG7A-GEB.js} +84 -25
  4. package/dist/api-client-foundation-eG7A-GEB.js.map +1 -0
  5. package/dist/auth-session-B1jSy0ws.js +1905 -0
  6. package/dist/auth-session-B1jSy0ws.js.map +1 -0
  7. package/dist/{base-url-PkgATS5u.js → base-url-BtqW4aLS.js} +73 -8
  8. package/dist/base-url-BtqW4aLS.js.map +1 -0
  9. package/dist/{command-CD_g9eAM.js → command-Dk3z-M2K.js} +879 -585
  10. package/dist/{command-CD_g9eAM.js.map → command-Dk3z-M2K.js.map} +1 -1
  11. package/dist/{daemon-runtime-lease-Cvo63MGd.js → daemon-runtime-lease-D82uDZ5s.js} +2 -2
  12. package/dist/{daemon-runtime-lease-Cvo63MGd.js.map → daemon-runtime-lease-D82uDZ5s.js.map} +1 -1
  13. package/dist/{dist-DYE9Q3T4.js → dist-BnHChh7U.js} +3 -3
  14. package/dist/{dist-DYE9Q3T4.js.map → dist-BnHChh7U.js.map} +1 -1
  15. package/dist/openmeld-dev.js +1 -1
  16. package/dist/openmeld.js +504 -101
  17. package/dist/openmeld.js.map +1 -1
  18. package/dist/{runtime-transport-CWWB2Ily.js → runtime-transport-CHbXitKu.js} +2 -2
  19. package/dist/{runtime-transport-CWWB2Ily.js.map → runtime-transport-CHbXitKu.js.map} +1 -1
  20. package/package.json +1 -1
  21. package/dist/api-client-foundation-w4Oa06t4.js.map +0 -1
  22. package/dist/auth-session-qk94UQqs.js +0 -1146
  23. package/dist/auth-session-qk94UQqs.js.map +0 -1
  24. package/dist/base-url-PkgATS5u.js.map +0 -1
@@ -0,0 +1,1905 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { $ as runWithHeldLock, K as isOpenMeldLockError, Lt as openMeldRootDir, W as acquireLock, _t as CURRENT_PROCESS_START_IDENTITY, vt as isProcessIdentityAlive, xn as __exportAll } from "./base-url-BtqW4aLS.js";
4
+ import { t as CURRENT_DAEMON_EXECUTION_CONTRACT_EPOCH } from "./runtime-transport-CHbXitKu.js";
5
+ import { createRequire } from "node:module";
6
+ import * as z$1 from "zod/v4";
7
+ import { join, resolve } from "node:path";
8
+ import { createHash, randomUUID } from "node:crypto";
9
+ import { chmod, link, mkdir, open, readFile, rename, rm, writeFile } from "node:fs/promises";
10
+ import { spawn } from "node:child_process";
11
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
12
+ import { fileURLToPath } from "node:url";
13
+ //#region ../../packages/schemas/dist/schemas/local-machine/macos-keychain-helper.js
14
+ const MAC_OS_KEYCHAIN_AUTHENTICATION_INTERACTION = "disallow";
15
+ const macOsKeychainServiceSchema = z$1.string().trim().min(1).max(512);
16
+ const macOsKeychainAccountSchema = z$1.string().trim().min(1).max(512);
17
+ const macOsKeychainAccessTokenSchema = z$1.string().min(1).max(65536);
18
+ const macOsKeychainHelperOperationSchema = z$1.enum([
19
+ "store",
20
+ "read",
21
+ "delete"
22
+ ]);
23
+ const macOsKeychainHelperRequestSchema = z$1.discriminatedUnion("operation", [
24
+ z$1.strictObject({
25
+ schemaVersion: z$1.literal(2),
26
+ operation: z$1.literal("store"),
27
+ service: macOsKeychainServiceSchema,
28
+ account: macOsKeychainAccountSchema,
29
+ accessToken: macOsKeychainAccessTokenSchema,
30
+ authenticationInteraction: z$1.literal(MAC_OS_KEYCHAIN_AUTHENTICATION_INTERACTION)
31
+ }),
32
+ z$1.strictObject({
33
+ schemaVersion: z$1.literal(2),
34
+ operation: z$1.literal("read"),
35
+ service: macOsKeychainServiceSchema,
36
+ account: macOsKeychainAccountSchema,
37
+ authenticationInteraction: z$1.literal(MAC_OS_KEYCHAIN_AUTHENTICATION_INTERACTION)
38
+ }),
39
+ z$1.strictObject({
40
+ schemaVersion: z$1.literal(2),
41
+ operation: z$1.literal("delete"),
42
+ service: macOsKeychainServiceSchema,
43
+ account: macOsKeychainAccountSchema,
44
+ authenticationInteraction: z$1.literal(MAC_OS_KEYCHAIN_AUTHENTICATION_INTERACTION)
45
+ })
46
+ ]);
47
+ const macOsKeychainHelperMutationSuccessSchema = z$1.strictObject({
48
+ schemaVersion: z$1.literal(2),
49
+ ok: z$1.literal(true),
50
+ operation: z$1.enum(["store", "delete"])
51
+ });
52
+ const macOsKeychainHelperReadSuccessSchema = z$1.strictObject({
53
+ schemaVersion: z$1.literal(2),
54
+ ok: z$1.literal(true),
55
+ operation: z$1.literal("read"),
56
+ accessToken: z$1.union([macOsKeychainAccessTokenSchema, z$1.null()])
57
+ });
58
+ const macOsKeychainHelperErrorSchema = z$1.strictObject({
59
+ schemaVersion: z$1.literal(2),
60
+ ok: z$1.literal(false),
61
+ operation: macOsKeychainHelperOperationSchema,
62
+ errorMessage: z$1.string().trim().min(1).max(2048)
63
+ });
64
+ const macOsKeychainHelperResponseSchema = z$1.union([
65
+ macOsKeychainHelperMutationSuccessSchema,
66
+ macOsKeychainHelperReadSuccessSchema,
67
+ macOsKeychainHelperErrorSchema
68
+ ]);
69
+ //#endregion
70
+ //#region src/strategy-constants.ts
71
+ const DEFAULT_GATEWAY_CHAIN_TIMEOUT_MS = 3e4;
72
+ const DEFAULT_REMOTE_SESSION_TIMEOUT_MS = 8e3;
73
+ const LOOPBACK_REMOTE_SESSION_TIMEOUT_MS = 1500;
74
+ const DEFAULT_SPACE_REQUEST_TIMEOUT_MS = 1e4;
75
+ const MIN_SPACE_REQUEST_TIMEOUT_MS = 1e3;
76
+ const MAX_SPACE_REQUEST_TIMEOUT_MS = 12e4;
77
+ const DEFAULT_HEARTBEAT_INTERVAL_MS = 25e3;
78
+ const MIN_HEARTBEAT_INTERVAL_MS = 5e3;
79
+ const MAX_HEARTBEAT_INTERVAL_MS = 6e4;
80
+ const DAEMON_STREAM_KEEPALIVE_INTERVAL_MS = 2e4;
81
+ const DAEMON_STREAM_KEEPALIVE_PONG_TIMEOUT_MS = 1e4;
82
+ const CATALOG_SYNC_RETRY_INTERVAL_MS = 5e3;
83
+ const CATALOG_SYNC_SIGNAL_POLL_INTERVAL_MS = 1e3;
84
+ const ROUTE_CATALOG_LOAD_TIMEOUT_MS = 15e3;
85
+ const RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_INTERVAL_MS = 5 * 6e4;
86
+ const RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_RETRY_INTERVAL_MS = 6e4;
87
+ const PROVIDER_CONVERSATION_PROOF_SYNC_INTERVAL_MS = 5 * 6e4;
88
+ const PROVIDER_CONVERSATION_PROOF_SYNC_RETRY_INTERVAL_MS = 6e4;
89
+ const RUNTIME_STATE_PERSIST_MIN_INTERVAL_MS = 6e4;
90
+ const DAEMON_STREAM_CONNECT_TIMEOUT_MS = 15e3;
91
+ const REGISTER_RESPONSE_TIMEOUT_MS = 1e4;
92
+ const HEARTBEAT_RESPONSE_TIMEOUT_MS = 15e3;
93
+ const DAEMON_RUNTIME_CONTRACT_EPOCH = CURRENT_DAEMON_EXECUTION_CONTRACT_EPOCH;
94
+ const OPENCLAW_CLI_TIMEOUT_MS = 3e4;
95
+ //#endregion
96
+ //#region src/config/auth-session-expiry.ts
97
+ function resolveAuthSessionExpiryEligibility(expiresAt, nowMs = Date.now()) {
98
+ const normalized = String(expiresAt ?? "").trim();
99
+ if (!normalized) return { status: "no_expiry" };
100
+ const expiresAtMs = Date.parse(normalized);
101
+ if (Number.isNaN(expiresAtMs)) return { status: "invalid" };
102
+ return expiresAtMs <= nowMs ? {
103
+ expiresAtMs,
104
+ status: "expired"
105
+ } : {
106
+ expiresAtMs,
107
+ status: "valid"
108
+ };
109
+ }
110
+ //#endregion
111
+ //#region src/config/auth-session-transition-lock.ts
112
+ const AUTH_SESSION_LOCK_KEY = "session-transition-mutation";
113
+ const AUTH_SESSION_LOCK_PROFILE = "auth-session";
114
+ const AUTH_SESSION_LOCK_RETRY_DELAY_MS = 20;
115
+ const AUTH_SESSION_LOCK_WAIT_MS = 1e4;
116
+ async function withAuthSessionTransitionMutationLock(operation) {
117
+ return await runWithHeldLock({
118
+ lock: await acquireAuthSessionTransitionMutationLock(),
119
+ run: operation,
120
+ releaseContext: {
121
+ component: "auth_session_transition",
122
+ lockKey: AUTH_SESSION_LOCK_KEY
123
+ }
124
+ });
125
+ }
126
+ async function acquireAuthSessionTransitionMutationLock() {
127
+ const deadline = Date.now() + AUTH_SESSION_LOCK_WAIT_MS;
128
+ while (true) try {
129
+ return await acquireLock({
130
+ key: AUTH_SESSION_LOCK_KEY,
131
+ meta: { component: "auth_session_transition" },
132
+ openMeldProfileId: AUTH_SESSION_LOCK_PROFILE
133
+ });
134
+ } catch (error) {
135
+ if (!(isOpenMeldLockError(error) && Date.now() < deadline)) throw error;
136
+ await setTimeout$1(AUTH_SESSION_LOCK_RETRY_DELAY_MS);
137
+ }
138
+ }
139
+ //#endregion
140
+ //#region src/runtime/distribution.ts
141
+ const BINARY_DISTRIBUTION = "binary";
142
+ const NPM_DISTRIBUTION = "npm";
143
+ /**
144
+ * The distribution form this CLI build was compiled for. Falls back to `npm`
145
+ * when the marker is absent (e.g. under Vitest, where no build-time define
146
+ * runs), which keeps the safe, path-independent default.
147
+ */
148
+ function resolveOpenMeldDistribution() {
149
+ return NPM_DISTRIBUTION;
150
+ }
151
+ function isBinaryDistribution() {
152
+ return resolveOpenMeldDistribution() === BINARY_DISTRIBUTION;
153
+ }
154
+ //#endregion
155
+ //#region src/config/macos-native-keychain.ts
156
+ const MAC_OS_KEYCHAIN_HELPER_ARG = "__openmeld_macos_keychain_helper";
157
+ const HELPER_OUTPUT_MAX_BYTES = 128 * 1024;
158
+ let loadedAddon = null;
159
+ let unresponsiveKeychainError = null;
160
+ async function storeMacOsNativeKeychainToken(input) {
161
+ if (isBinaryDistribution()) {
162
+ await runBoundedMacOsNativeKeychainRequest({
163
+ operation: "store",
164
+ service: input.service,
165
+ account: input.account,
166
+ accessToken: input.accessToken
167
+ });
168
+ return;
169
+ }
170
+ (await loadAddon()).store(input.service, input.account, input.accessToken);
171
+ }
172
+ async function readMacOsNativeKeychainToken(input) {
173
+ if (isBinaryDistribution()) return await runBoundedMacOsNativeKeychainRequest({
174
+ operation: "read",
175
+ service: input.service,
176
+ account: input.account
177
+ });
178
+ return (await loadAddon()).read(input.service, input.account);
179
+ }
180
+ async function deleteMacOsNativeKeychainToken(input) {
181
+ if (isBinaryDistribution()) {
182
+ await runBoundedMacOsNativeKeychainRequest({
183
+ operation: "delete",
184
+ service: input.service,
185
+ account: input.account
186
+ });
187
+ return;
188
+ }
189
+ (await loadAddon()).remove(input.service, input.account);
190
+ }
191
+ async function runMacOsNativeKeychainRequestInChild(input, options = {}) {
192
+ const request = macOsKeychainHelperRequestSchema.parse({
193
+ schemaVersion: 2,
194
+ authenticationInteraction: MAC_OS_KEYCHAIN_AUTHENTICATION_INTERACTION,
195
+ ...input
196
+ });
197
+ const timeoutMs = options.timeoutMs ?? 5e3;
198
+ if (!(Number.isSafeInteger(timeoutMs) && timeoutMs > 0)) throw new Error("macOS Keychain helper timeout must be a positive integer");
199
+ return await new Promise((resolve, reject) => {
200
+ const child = spawn(process.execPath, [MAC_OS_KEYCHAIN_HELPER_ARG], {
201
+ env: process.env,
202
+ shell: false,
203
+ stdio: [
204
+ "pipe",
205
+ "pipe",
206
+ "pipe"
207
+ ],
208
+ windowsHide: true
209
+ });
210
+ let settled = false;
211
+ let stdout = "";
212
+ let stderr = "";
213
+ const clearDeadline = () => {
214
+ clearTimeout(deadline);
215
+ };
216
+ const rejectOnce = (error) => {
217
+ if (settled) return;
218
+ settled = true;
219
+ clearDeadline();
220
+ reject(error);
221
+ };
222
+ const deadline = setTimeout(() => {
223
+ if (settled) return;
224
+ settled = true;
225
+ child.kill("SIGKILL");
226
+ reject(new MacOsNativeKeychainTimeoutError(`macOS Keychain did not respond within ${formatTimeout(timeoutMs)}`));
227
+ }, timeoutMs);
228
+ child.stdout.setEncoding("utf8");
229
+ child.stderr.setEncoding("utf8");
230
+ child.stdout.on("data", (chunk) => {
231
+ stdout += String(chunk);
232
+ if (Buffer.byteLength(stdout, "utf8") > HELPER_OUTPUT_MAX_BYTES) {
233
+ child.kill("SIGKILL");
234
+ rejectOnce(/* @__PURE__ */ new Error("macOS Keychain helper output was too large"));
235
+ }
236
+ });
237
+ child.stderr.on("data", (chunk) => {
238
+ stderr += String(chunk);
239
+ if (Buffer.byteLength(stderr, "utf8") > HELPER_OUTPUT_MAX_BYTES) stderr = stderr.slice(-131072);
240
+ });
241
+ child.once("error", (error) => {
242
+ rejectOnce(/* @__PURE__ */ new Error(`macOS Keychain helper could not start: ${toErrorMessage$2(error)}`));
243
+ });
244
+ child.stdin.once("error", (error) => {
245
+ rejectOnce(/* @__PURE__ */ new Error(`macOS Keychain helper input failed: ${toErrorMessage$2(error)}`));
246
+ });
247
+ child.once("close", (code) => {
248
+ if (settled) return;
249
+ clearDeadline();
250
+ settled = true;
251
+ try {
252
+ resolve(parseMacOsKeychainHelperResult({
253
+ code,
254
+ operation: request.operation,
255
+ stderr,
256
+ stdout
257
+ }));
258
+ } catch (error) {
259
+ reject(toError(error));
260
+ }
261
+ });
262
+ child.stdin.end(JSON.stringify(request), "utf8");
263
+ });
264
+ }
265
+ async function runMacOsNativeKeychainHelperIfRequested(argv = process.argv) {
266
+ if (!argv.includes(MAC_OS_KEYCHAIN_HELPER_ARG)) return false;
267
+ if (!(isBinaryDistribution() && process.platform === "darwin")) throw new Error("the internal macOS Keychain helper is only available in the macOS binary");
268
+ if (!(await loadAddon()).isParentSameExecutable()) throw new Error("the internal macOS Keychain helper is reserved for an OpenMeld child process");
269
+ const rawRequest = await readHelperStdin();
270
+ let json;
271
+ try {
272
+ json = JSON.parse(rawRequest);
273
+ } catch {
274
+ throw new Error("invalid macOS Keychain helper request");
275
+ }
276
+ const request = macOsKeychainHelperRequestSchema.safeParse(json);
277
+ if (!request.success) throw new Error("invalid macOS Keychain helper request");
278
+ const response = await executeHelperRequest(request.data).catch((error) => ({
279
+ schemaVersion: 2,
280
+ ok: false,
281
+ operation: request.data.operation,
282
+ errorMessage: truncateErrorMessage(toErrorMessage$2(error))
283
+ }));
284
+ process.stdout.write(JSON.stringify(response));
285
+ return true;
286
+ }
287
+ async function runBoundedMacOsNativeKeychainRequest(input) {
288
+ if (unresponsiveKeychainError) throw unresponsiveKeychainError;
289
+ try {
290
+ if (input.operation === "read") return await runMacOsNativeKeychainRequestInChild(input);
291
+ await runMacOsNativeKeychainRequestInChild(input);
292
+ } catch (error) {
293
+ if (error instanceof MacOsNativeKeychainTimeoutError) unresponsiveKeychainError = error;
294
+ throw error;
295
+ }
296
+ }
297
+ function parseMacOsKeychainHelperResult(input) {
298
+ if (input.code !== 0) throw new Error(`macOS Keychain helper exited with code ${input.code ?? "unknown"}${input.stderr.trim() ? `: ${input.stderr.trim()}` : ""}`);
299
+ let rawResponse;
300
+ try {
301
+ rawResponse = JSON.parse(input.stdout);
302
+ } catch {
303
+ throw new Error("macOS Keychain helper returned an invalid response");
304
+ }
305
+ const parsed = macOsKeychainHelperResponseSchema.safeParse(rawResponse);
306
+ if (!(parsed.success && parsed.data.operation === input.operation)) throw new Error("macOS Keychain helper returned an invalid response");
307
+ if (!parsed.data.ok) throw new Error(parsed.data.errorMessage);
308
+ return parsed.data.operation === "read" ? parsed.data.accessToken : void 0;
309
+ }
310
+ async function executeHelperRequest(input) {
311
+ const addon = await loadAddon();
312
+ if (input.operation === "store") {
313
+ addon.store(input.service, input.account, input.accessToken);
314
+ return {
315
+ schemaVersion: 2,
316
+ ok: true,
317
+ operation: "store"
318
+ };
319
+ }
320
+ if (input.operation === "delete") {
321
+ addon.remove(input.service, input.account);
322
+ return {
323
+ schemaVersion: 2,
324
+ ok: true,
325
+ operation: "delete"
326
+ };
327
+ }
328
+ return {
329
+ schemaVersion: 2,
330
+ ok: true,
331
+ operation: "read",
332
+ accessToken: addon.read(input.service, input.account)
333
+ };
334
+ }
335
+ async function readHelperStdin() {
336
+ let raw = "";
337
+ process.stdin.setEncoding("utf8");
338
+ for await (const chunk of process.stdin) {
339
+ raw += String(chunk);
340
+ if (Buffer.byteLength(raw, "utf8") > HELPER_OUTPUT_MAX_BYTES) throw new Error("macOS Keychain helper request was too large");
341
+ }
342
+ return raw;
343
+ }
344
+ function truncateErrorMessage(message) {
345
+ return (message.trim() || "macOS Keychain operation failed").slice(0, 2048);
346
+ }
347
+ function formatTimeout(timeoutMs) {
348
+ return timeoutMs % 1e3 === 0 ? `${timeoutMs / 1e3} seconds` : `${timeoutMs} ms`;
349
+ }
350
+ function toErrorMessage$2(error) {
351
+ return error instanceof Error ? error.message : String(error);
352
+ }
353
+ function toError(error) {
354
+ return error instanceof Error ? error : new Error(String(error));
355
+ }
356
+ var MacOsNativeKeychainTimeoutError = class extends Error {
357
+ name = "MacOsNativeKeychainTimeoutError";
358
+ };
359
+ async function loadAddon() {
360
+ if (loadedAddon) return loadedAddon;
361
+ if (process.platform !== "darwin") throw new Error("macOS Keychain is only available on macOS");
362
+ if (isBinaryDistribution()) {
363
+ loadedAddon = (await import("./config/macos-native-keychain-embedded")).loadEmbeddedMacOsKeychainAddon();
364
+ return loadedAddon;
365
+ }
366
+ loadedAddon = createRequire(import.meta.url)(fileURLToPath(new URL("./native/openmeld-keychain.node", import.meta.url)));
367
+ return loadedAddon;
368
+ }
369
+ //#endregion
370
+ //#region src/config/token-store.ts
371
+ const TOKEN_STORE_KEYCHAIN_SERVICE = "sh.openmeld.auth.token";
372
+ const INSECURE_FALLBACK_ENV_KEY = "OPENMELD_AUTH_ALLOW_INSECURE_FILE_TOKEN";
373
+ const FORCE_INSECURE_STORE_ENV_KEY = "OPENMELD_AUTH_FORCE_INSECURE_FILE_TOKEN";
374
+ const MAC_OS_KEYCHAIN_NONINTERACTIVE_UNAVAILABLE_MESSAGE = "macOS Keychain access is unavailable in this OpenMeld distribution. OpenMeld will not open an authorization window from an unattended process. Run setup or login with the current packaged OpenMeld CLI.";
375
+ const COMMAND_MAX_BUFFER_BYTES = 1024 * 1024;
376
+ const COMMAND_TIMEOUT_MS = 3e4;
377
+ const TOKEN_FILE_KEY_PATTERN = /^[a-f0-9]{64}$/u;
378
+ const EXEC_FILE_BASE_OPTIONS = {
379
+ windowsHide: true,
380
+ maxBuffer: COMMAND_MAX_BUFFER_BYTES,
381
+ timeout: COMMAND_TIMEOUT_MS
382
+ };
383
+ let insecureFallbackWarningShown = false;
384
+ let macOsPrivateStorageWarningShown = false;
385
+ async function storeAccessToken(input) {
386
+ const key = buildTokenKey({
387
+ authBaseUrl: input.authBaseUrl,
388
+ clientId: input.clientId
389
+ });
390
+ const storageKey = input.unique ? buildUniqueTokenFileKey(key) : key;
391
+ if (shouldForceInsecureStore()) {
392
+ await setInsecureFileToken({
393
+ key: storageKey,
394
+ accessToken: input.accessToken
395
+ });
396
+ return {
397
+ provider: "insecure-file",
398
+ key: storageKey
399
+ };
400
+ }
401
+ if (process.platform === "darwin") try {
402
+ const account = buildUniqueMacOsAccount(key);
403
+ if (shouldUseNativeMacOsKeychain()) await storeMacOsNativeKeychainToken({
404
+ account,
405
+ service: TOKEN_STORE_KEYCHAIN_SERVICE,
406
+ accessToken: input.accessToken
407
+ });
408
+ else throw new Error(MAC_OS_KEYCHAIN_NONINTERACTIVE_UNAVAILABLE_MESSAGE);
409
+ return {
410
+ provider: "macos-keychain",
411
+ service: TOKEN_STORE_KEYCHAIN_SERVICE,
412
+ account
413
+ };
414
+ } catch (error) {
415
+ if (allowInsecureFallback()) {
416
+ await setInsecureFileToken({
417
+ key: storageKey,
418
+ accessToken: input.accessToken
419
+ });
420
+ return {
421
+ provider: "insecure-file",
422
+ key: storageKey
423
+ };
424
+ }
425
+ const privateKey = buildUniqueTokenFileKey(key);
426
+ await setInsecureFileToken({
427
+ key: privateKey,
428
+ accessToken: input.accessToken
429
+ });
430
+ warnMacOsPrivateStorageFallback(error);
431
+ return {
432
+ provider: "insecure-file",
433
+ key: privateKey
434
+ };
435
+ }
436
+ if (process.platform === "win32") try {
437
+ await setWindowsDpapiToken({
438
+ key: storageKey,
439
+ accessToken: input.accessToken
440
+ });
441
+ return {
442
+ provider: "windows-dpapi",
443
+ key: storageKey
444
+ };
445
+ } catch (error) {
446
+ if (allowInsecureFallback()) {
447
+ await setInsecureFileToken({
448
+ key: storageKey,
449
+ accessToken: input.accessToken
450
+ });
451
+ return {
452
+ provider: "insecure-file",
453
+ key: storageKey
454
+ };
455
+ }
456
+ throw new Error(`failed to store access token via Windows DPAPI: ${toErrorMessage$1(error)}`);
457
+ }
458
+ if (allowInsecureFallback()) {
459
+ await setInsecureFileToken({
460
+ key: storageKey,
461
+ accessToken: input.accessToken
462
+ });
463
+ return {
464
+ provider: "insecure-file",
465
+ key: storageKey
466
+ };
467
+ }
468
+ throw new Error(`secure token storage is unavailable on platform "${process.platform}". Use ${INSECURE_FALLBACK_ENV_KEY}=1 only for local testing fallback.`);
469
+ }
470
+ async function readAccessToken(ref) {
471
+ try {
472
+ if (ref.provider === "macos-keychain") {
473
+ if (!shouldUseNativeMacOsKeychain()) throw new Error(MAC_OS_KEYCHAIN_NONINTERACTIVE_UNAVAILABLE_MESSAGE);
474
+ return toAccessTokenReadResult(await readMacOsNativeKeychainToken(ref));
475
+ }
476
+ if (ref.provider === "windows-dpapi") return toAccessTokenReadResult(await getWindowsDpapiToken(ref));
477
+ if (ref.provider === "insecure-file") return toAccessTokenReadResult(await getInsecureFileToken(ref));
478
+ return { status: "missing" };
479
+ } catch (error) {
480
+ return {
481
+ errorMessage: toErrorMessage$1(error),
482
+ status: "unavailable"
483
+ };
484
+ }
485
+ }
486
+ async function deleteAccessToken(ref) {
487
+ if (ref.provider === "macos-keychain") {
488
+ if (!shouldUseNativeMacOsKeychain()) throw new Error(MAC_OS_KEYCHAIN_NONINTERACTIVE_UNAVAILABLE_MESSAGE);
489
+ await deleteMacOsNativeKeychainToken(ref);
490
+ return;
491
+ }
492
+ if (ref.provider === "windows-dpapi") {
493
+ await deleteWindowsDpapiToken(ref);
494
+ return;
495
+ }
496
+ if (ref.provider === "insecure-file") await deleteInsecureFileToken(ref);
497
+ }
498
+ function isStoredTokenRef(value) {
499
+ if (!(value && typeof value === "object")) return false;
500
+ const record = value;
501
+ const provider = normalizeString(record.provider);
502
+ if (provider === "macos-keychain") return Boolean(normalizeString(record.service) && normalizeString(record.account) && record.accessGroup === void 0);
503
+ if (provider === "windows-dpapi" || provider === "insecure-file") return normalizeTokenFileKey(record.key) !== null;
504
+ return false;
505
+ }
506
+ function buildTokenKey(input) {
507
+ const rootDir = resolve(openMeldRootDir());
508
+ return createHash("sha256").update(`${input.clientId}\n${input.authBaseUrl}\n${rootDir}`).digest("hex");
509
+ }
510
+ function buildUniqueMacOsAccount(key) {
511
+ return `openmeld-auth-${key}-${randomUUID()}`;
512
+ }
513
+ function buildUniqueTokenFileKey(key) {
514
+ return createHash("sha256").update(`${key}\n${randomUUID()}`).digest("hex");
515
+ }
516
+ function shouldUseNativeMacOsKeychain() {
517
+ return isBinaryDistribution();
518
+ }
519
+ async function setWindowsDpapiToken(input) {
520
+ const encrypted = await runPowerShellScript(WINDOWS_DPAPI_ENCRYPT_SCRIPT, input.accessToken, input.key);
521
+ await mkdir(tokenDirectoryPath(), { recursive: true });
522
+ await writeFile(windowsDpapiTokenPath(input.key), `${encrypted.trim()}\n`, {
523
+ encoding: "utf8",
524
+ mode: 384
525
+ });
526
+ }
527
+ async function getWindowsDpapiToken(input) {
528
+ const encrypted = await readFile(windowsDpapiTokenPath(input.key), "utf8").catch((error) => {
529
+ if (isFileNotFoundError$1(error)) return null;
530
+ throw error;
531
+ });
532
+ if (!encrypted) return null;
533
+ return runPowerShellScript(WINDOWS_DPAPI_DECRYPT_SCRIPT, encrypted.trim(), input.key);
534
+ }
535
+ async function deleteWindowsDpapiToken(input) {
536
+ await rm(windowsDpapiTokenPath(input.key), { force: true });
537
+ }
538
+ async function setInsecureFileToken(input) {
539
+ await ensurePrivateTokenDirectory();
540
+ const path = insecureTokenPath(input.key);
541
+ await writeFile(path, `${input.accessToken}\n`, {
542
+ encoding: "utf8",
543
+ mode: 384
544
+ });
545
+ if (process.platform !== "win32") await chmod(path, 384);
546
+ }
547
+ async function getInsecureFileToken(input) {
548
+ const raw = await readFile(insecureTokenPath(input.key), "utf8").catch((error) => {
549
+ if (isFileNotFoundError$1(error)) return null;
550
+ throw error;
551
+ });
552
+ return raw ? raw.trim() : null;
553
+ }
554
+ async function deleteInsecureFileToken(input) {
555
+ await rm(insecureTokenPath(input.key), { force: true });
556
+ }
557
+ function tokenDirectoryPath() {
558
+ return join(openMeldRootDir(), "auth", "tokens");
559
+ }
560
+ function windowsDpapiTokenPath(key) {
561
+ return join(tokenDirectoryPath(), `${requireValidTokenFileKey(key)}.dpapi`);
562
+ }
563
+ function insecureTokenPath(key) {
564
+ return join(tokenDirectoryPath(), `${requireValidTokenFileKey(key)}.token`);
565
+ }
566
+ function allowInsecureFallback() {
567
+ if (process.env[INSECURE_FALLBACK_ENV_KEY] === "1") {
568
+ warnInsecureFallback("env");
569
+ return true;
570
+ }
571
+ const fallbackEnabled = !isNativeSecureStorePlatform();
572
+ if (fallbackEnabled) warnInsecureFallback("platform");
573
+ return fallbackEnabled;
574
+ }
575
+ function warnMacOsPrivateStorageFallback(error) {
576
+ if (macOsPrivateStorageWarningShown) return;
577
+ macOsPrivateStorageWarningShown = true;
578
+ const storageExpectation = isBinaryDistribution() ? "This session stays in private local storage unless a later sign-in replaces it." : "This npm installation cannot use macOS Keychain. This session stays in private local storage.";
579
+ console.warn(`[openmeld auth] macOS Keychain is unavailable. OpenMeld saved this session in a private file protected for your macOS user account, so setup can continue. ${storageExpectation} Details: ${toErrorMessage$1(error)}`);
580
+ }
581
+ function warnInsecureFallback(reason) {
582
+ if (insecureFallbackWarningShown) return;
583
+ insecureFallbackWarningShown = true;
584
+ const reasonText = reason === "env" ? `enabled by ${INSECURE_FALLBACK_ENV_KEY}=1` : `enabled automatically on platform "${process.platform}"`;
585
+ console.warn(`[openmeld auth] plaintext file token storage fallback is active (${reasonText}). Unset ${INSECURE_FALLBACK_ENV_KEY} to disable explicit opt-in, and prefer macOS or Windows for native secure token storage.`);
586
+ }
587
+ function shouldForceInsecureStore() {
588
+ return process.env[FORCE_INSECURE_STORE_ENV_KEY] === "1";
589
+ }
590
+ function isNativeSecureStorePlatform() {
591
+ return process.platform === "darwin" || process.platform === "win32";
592
+ }
593
+ async function ensurePrivateTokenDirectory() {
594
+ const directory = tokenDirectoryPath();
595
+ await mkdir(directory, {
596
+ recursive: true,
597
+ mode: 448
598
+ });
599
+ if (process.platform !== "win32") await chmod(directory, 448);
600
+ }
601
+ async function runPowerShellScript(script, token, entropy) {
602
+ const payload = JSON.stringify({
603
+ token,
604
+ entropy
605
+ });
606
+ return (await runCommand("powershell.exe", [
607
+ "-NoProfile",
608
+ "-NonInteractive",
609
+ "-ExecutionPolicy",
610
+ "Bypass",
611
+ "-Command",
612
+ script
613
+ ], payload)).stdout.trim();
614
+ }
615
+ async function runCommand(command, args, stdinPayload) {
616
+ try {
617
+ const { execFile } = await import("node:child_process");
618
+ return await new Promise((resolve, reject) => {
619
+ let stdout = "";
620
+ let stderr = "";
621
+ const child = execFile(command, args, { ...EXEC_FILE_BASE_OPTIONS });
622
+ child.stdout?.setEncoding("utf8");
623
+ child.stderr?.setEncoding("utf8");
624
+ child.stdout?.on("data", (chunk) => {
625
+ stdout += String(chunk);
626
+ });
627
+ child.stderr?.on("data", (chunk) => {
628
+ stderr += String(chunk);
629
+ });
630
+ child.on("error", (error) => {
631
+ reject(toCommandError(error, command));
632
+ });
633
+ child.on("close", (code) => {
634
+ if (code === 0) {
635
+ resolve({
636
+ stdout,
637
+ stderr
638
+ });
639
+ return;
640
+ }
641
+ reject(toCommandError({ message: `command failed (${command}) with exit code ${code}` }, command));
642
+ });
643
+ child.stdin?.write(stdinPayload);
644
+ child.stdin?.end();
645
+ });
646
+ } catch (error) {
647
+ throw toCommandError(error, command);
648
+ }
649
+ }
650
+ function toCommandError(error, command) {
651
+ if (!(error && typeof error === "object")) return /* @__PURE__ */ new Error(`command failed (${command}): ${String(error)}`);
652
+ const e = error;
653
+ const code = typeof e.code === "number" ? e.code : null;
654
+ const messageParts = [`command failed (${command})`];
655
+ if (typeof e.stderr === "string" && e.stderr.trim()) messageParts.push(`stderr: ${e.stderr.trim()}`);
656
+ else if (e.message) messageParts.push(e.message);
657
+ const wrapped = new Error(messageParts.join("; "));
658
+ wrapped.code = code;
659
+ wrapped.stdout = e.stdout;
660
+ wrapped.stderr = e.stderr;
661
+ return wrapped;
662
+ }
663
+ function normalizeString(value) {
664
+ return String(value ?? "").trim();
665
+ }
666
+ function normalizeTokenFileKey(value) {
667
+ const normalized = normalizeString(value);
668
+ if (!TOKEN_FILE_KEY_PATTERN.test(normalized)) return null;
669
+ return normalized;
670
+ }
671
+ function requireValidTokenFileKey(value) {
672
+ const normalized = normalizeTokenFileKey(value);
673
+ if (normalized === null) throw new Error("stored token key is invalid");
674
+ return normalized;
675
+ }
676
+ function normalizeToken(value) {
677
+ if (value === null) return null;
678
+ const normalized = value.trim();
679
+ return normalized.length > 0 ? normalized : null;
680
+ }
681
+ function toAccessTokenReadResult(value) {
682
+ const accessToken = normalizeToken(value);
683
+ if (!accessToken) return { status: "missing" };
684
+ return {
685
+ accessToken,
686
+ status: "found"
687
+ };
688
+ }
689
+ function toErrorMessage$1(error) {
690
+ if (error instanceof Error) return error.message;
691
+ return String(error);
692
+ }
693
+ function isFileNotFoundError$1(error) {
694
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
695
+ }
696
+ const WINDOWS_DPAPI_ENCRYPT_SCRIPT = [
697
+ "$ErrorActionPreference='Stop'",
698
+ "$rawInput = [Console]::In.ReadToEnd()",
699
+ "$payload = $rawInput | ConvertFrom-Json",
700
+ "$plain=[System.Text.Encoding]::UTF8.GetBytes($payload.token)",
701
+ "$entropy=[System.Text.Encoding]::UTF8.GetBytes($payload.entropy)",
702
+ "$cipher=[System.Security.Cryptography.ProtectedData]::Protect($plain,$entropy,[System.Security.Cryptography.DataProtectionScope]::CurrentUser)",
703
+ "[System.Convert]::ToBase64String($cipher)"
704
+ ].join(";");
705
+ const WINDOWS_DPAPI_DECRYPT_SCRIPT = [
706
+ "$ErrorActionPreference='Stop'",
707
+ "$rawInput = [Console]::In.ReadToEnd()",
708
+ "$payload = $rawInput | ConvertFrom-Json",
709
+ "$cipher=[System.Convert]::FromBase64String($payload.token)",
710
+ "$entropy=[System.Text.Encoding]::UTF8.GetBytes($payload.entropy)",
711
+ "$plain=[System.Security.Cryptography.ProtectedData]::Unprotect($cipher,$entropy,[System.Security.Cryptography.DataProtectionScope]::CurrentUser)",
712
+ "[System.Text.Encoding]::UTF8.GetString($plain)"
713
+ ].join(";");
714
+ //#endregion
715
+ //#region src/config/auth-session.ts
716
+ var auth_session_exports = /* @__PURE__ */ __exportAll({
717
+ AuthSessionRecoveryInProgressError: () => AuthSessionRecoveryInProgressError,
718
+ AuthSessionTransitionConflictError: () => AuthSessionTransitionConflictError,
719
+ assertAuthSessionMutationAvailable: () => assertAuthSessionMutationAvailable,
720
+ beginAuthSessionTransition: () => beginAuthSessionTransition,
721
+ clearAuthSession: () => clearAuthSession,
722
+ completeInterruptedComputerAuthSessionRecovery: () => completeInterruptedComputerAuthSessionRecovery,
723
+ getAuthSessionMetadata: () => getAuthSessionMetadata,
724
+ getAuthSessionState: () => getAuthSessionState,
725
+ getCurrentAuthOwnerUserId: () => getCurrentAuthOwnerUserId,
726
+ getInterruptedComputerAuthSessionRecovery: () => getInterruptedComputerAuthSessionRecovery,
727
+ markInterruptedComputerAuthSessionRecovery: () => markInterruptedComputerAuthSessionRecovery,
728
+ normalizeStoredActiveOrganization: () => normalizeStoredActiveOrganization,
729
+ recordInterruptedComputerAuthSessionRecoveryFailure: () => recordInterruptedComputerAuthSessionRecoveryFailure,
730
+ setAuthSession: () => setAuthSession,
731
+ updateAuthSessionActiveOrganization: () => updateAuthSessionActiveOrganization
732
+ });
733
+ var AuthSessionStorageError = class extends Error {
734
+ reason;
735
+ constructor(input) {
736
+ super(input.message, input.cause === void 0 ? void 0 : { cause: input.cause });
737
+ this.name = "AuthSessionStorageError";
738
+ this.reason = input.reason;
739
+ }
740
+ };
741
+ var AuthSessionRecoveryInProgressError = class extends Error {
742
+ constructor() {
743
+ super("OpenMeld is still finishing an interrupted Computer sign-in recovery. The current sign-in was not changed; retry after the recovery cleanup succeeds.");
744
+ this.name = "AuthSessionRecoveryInProgressError";
745
+ }
746
+ };
747
+ var AuthSessionTransitionConflictError = class extends Error {
748
+ previousOwnerRestored;
749
+ reason;
750
+ constructor(input) {
751
+ const conflict = {
752
+ journal_missing: "missing",
753
+ journal_not_pending: "no longer pending",
754
+ journal_replaced: "owned by another sign-in"
755
+ }[input.reason];
756
+ const outcome = input.previousOwnerRestored ? "The previous sign-in was restored." : "No local sign-in state was changed.";
757
+ super(`The auth session transition journal is ${conflict}. ${outcome}`);
758
+ this.name = "AuthSessionTransitionConflictError";
759
+ this.reason = input.reason;
760
+ this.previousOwnerRestored = input.previousOwnerRestored;
761
+ }
762
+ };
763
+ const TRAILING_SLASHES_RE = /\/+$/u;
764
+ let cachedAuthSession = null;
765
+ const activeAuthSessionTransitionIds = /* @__PURE__ */ new Set();
766
+ async function getAuthSessionState(options = {}) {
767
+ const localState = await getLocalAuthSessionState();
768
+ const localPayloadKey = cachedAuthSession?.payloadKey ?? null;
769
+ const shouldValidateRemote = options.validateRemote === true || options.refreshExpired === true && localState.state === "expired";
770
+ switch (localState.state) {
771
+ case "missing":
772
+ case "invalid": return localState;
773
+ case "expired":
774
+ if (!shouldValidateRemote) return localState;
775
+ break;
776
+ case "valid": break;
777
+ default: return localState;
778
+ }
779
+ if (!shouldValidateRemote) return localState;
780
+ const remoteValidation = await getRemoteAuthSessionState(localState.session);
781
+ if (remoteValidation.state === "valid") {
782
+ if (!remoteValidation.expiresAt) return localState;
783
+ if (isExpired(remoteValidation.expiresAt)) return localState;
784
+ const refreshedSession = await persistRemoteSessionRefresh({
785
+ accessToken: remoteValidation.accessToken ?? localState.session.accessToken,
786
+ expectedPayloadKey: localPayloadKey,
787
+ expiresAt: remoteValidation.expiresAt,
788
+ previousAccessToken: localState.session.accessToken
789
+ });
790
+ if (refreshedSession) return {
791
+ state: "valid",
792
+ session: refreshedSession
793
+ };
794
+ return await getLocalAuthSessionState();
795
+ }
796
+ if (remoteValidation.state === "unknown") {
797
+ if (localState.state === "expired" && options.refreshExpired === true) return {
798
+ state: "valid",
799
+ session: localState.session
800
+ };
801
+ return localState;
802
+ }
803
+ return {
804
+ reasonCode: resolveRemoteAuthSessionReasonCode(remoteValidation.state),
805
+ state: remoteValidation.state,
806
+ session: null
807
+ };
808
+ }
809
+ async function getCurrentAuthOwnerUserId() {
810
+ const ownerUserId = (await getAuthSessionState({ validateRemote: false }).catch(() => null))?.session?.user?.id?.trim() ?? "";
811
+ return ownerUserId.length > 0 ? ownerUserId : null;
812
+ }
813
+ async function setAuthSession(input) {
814
+ const accessToken = String(input.accessToken ?? "").trim();
815
+ if (!accessToken) throw new Error("access token is required");
816
+ const authBaseUrl = String(input.authBaseUrl ?? "").trim();
817
+ if (!authBaseUrl) throw new Error("auth base URL is required");
818
+ const clientId = String(input.clientId ?? "").trim();
819
+ if (!clientId) throw new Error("client_id is required");
820
+ await withAuthSessionTransitionMutationLock(async () => {
821
+ await assertAuthSessionMutationAvailableWithOwnership();
822
+ await retryPendingTokenCleanup();
823
+ const previousTokenRef = normalizeTokenRef((await readSessionPayloadFile())?.tokenRef);
824
+ const tokenRef = await storeAccessToken({
825
+ accessToken,
826
+ authBaseUrl,
827
+ clientId
828
+ });
829
+ const payload = {
830
+ v: 1,
831
+ tokenRef,
832
+ tokenType: String(input.tokenType ?? "Bearer").trim() || "Bearer",
833
+ authBaseUrl,
834
+ clientId,
835
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
836
+ ...input.expiresAt ? { expiresAt: input.expiresAt } : {},
837
+ ...input.scope ? { scope: input.scope } : {},
838
+ ...buildAuthUserPayload(input.user),
839
+ ...buildActiveOrganizationPayload(input.activeOrganization)
840
+ };
841
+ const path = authSessionPath();
842
+ await ensureAuthSessionDirectory();
843
+ try {
844
+ await assertStoredAccessTokenReloads({
845
+ accessToken,
846
+ tokenRef
847
+ });
848
+ await writeSessionPayloadAtomically(path, payload);
849
+ } catch (error) {
850
+ await deleteAccessTokenOrRetainForCleanup(tokenRef);
851
+ throw error;
852
+ }
853
+ cacheAuthSession({
854
+ payload,
855
+ session: buildStoredAuthSession({
856
+ accessToken,
857
+ payload
858
+ })
859
+ });
860
+ if (previousTokenRef && !areStoredTokenRefsEqual(previousTokenRef, tokenRef)) await deleteAccessTokenOrRetainForCleanup(previousTokenRef);
861
+ });
862
+ }
863
+ async function beginAuthSessionTransition(input, context = {}) {
864
+ const accessToken = String(input.accessToken ?? "").trim();
865
+ if (!accessToken) throw new Error("access token is required");
866
+ const authBaseUrl = String(input.authBaseUrl ?? "").trim();
867
+ if (!authBaseUrl) throw new Error("auth base URL is required");
868
+ const clientId = String(input.clientId ?? "").trim();
869
+ if (!clientId) throw new Error("client_id is required");
870
+ return await withAuthSessionTransitionMutationLock(async () => {
871
+ await assertAuthSessionMutationAvailableWithOwnership();
872
+ await retryPendingTokenCleanup();
873
+ await ensureAuthSessionDirectory();
874
+ const previousPayload = await readSessionPayloadFile();
875
+ const previousState = await getLocalAuthSessionState({ recover: false });
876
+ const previousSession = previousState.state === "valid" || previousState.state === "expired" ? previousState.session : null;
877
+ const tokenRef = await storeAccessToken({
878
+ accessToken,
879
+ authBaseUrl,
880
+ clientId,
881
+ unique: true
882
+ });
883
+ const nextPayload = {
884
+ v: 1,
885
+ tokenRef,
886
+ tokenType: String(input.tokenType ?? "Bearer").trim() || "Bearer",
887
+ authBaseUrl,
888
+ clientId,
889
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
890
+ ...input.expiresAt ? { expiresAt: input.expiresAt } : {},
891
+ ...input.scope ? { scope: input.scope } : {},
892
+ ...buildAuthUserPayload(input.user),
893
+ ...buildActiveOrganizationPayload(input.activeOrganization)
894
+ };
895
+ const journal = {
896
+ v: 1,
897
+ id: randomUUID(),
898
+ state: "pending",
899
+ ownerPid: process.pid,
900
+ ownerProcessStartedAt: CURRENT_PROCESS_START_IDENTITY,
901
+ previousPayload: previousPayload?.v === 1 ? previousPayload : null,
902
+ candidatePayload: nextPayload,
903
+ ...context.computerHandoff ? { computerHandoff: { gatewayUrl: context.computerHandoff.gatewayUrl } } : {}
904
+ };
905
+ let journalClaimed = false;
906
+ try {
907
+ await assertStoredAccessTokenReloads({
908
+ accessToken,
909
+ tokenRef
910
+ });
911
+ await claimAuthSessionTransitionJournal(journal);
912
+ journalClaimed = true;
913
+ activeAuthSessionTransitionIds.add(journal.id);
914
+ await writeSessionPayloadAtomically(authSessionPath(), nextPayload);
915
+ } catch (error) {
916
+ activeAuthSessionTransitionIds.delete(journal.id);
917
+ if (journalClaimed) {
918
+ await restoreTransitionPreviousPayload(journal).catch(() => void 0);
919
+ await removeAuthSessionTransitionJournalIfOwned(journal).catch(() => void 0);
920
+ }
921
+ await deleteAccessTokenOrRetainForCleanup(tokenRef);
922
+ throw error;
923
+ }
924
+ cacheAuthSession({
925
+ payload: nextPayload,
926
+ session: buildStoredAuthSession({
927
+ accessToken,
928
+ payload: nextPayload
929
+ })
930
+ });
931
+ let settlement = "pending";
932
+ const assertTransitionPending = () => {
933
+ if (settlement !== "pending") throw new Error("auth session transition is already settled");
934
+ };
935
+ const isCandidateSessionCurrent = (currentPayload) => {
936
+ return !(currentPayload?.v !== 1 || buildAuthSessionPayloadKey(currentPayload) !== buildAuthSessionPayloadKey(nextPayload));
937
+ };
938
+ const assertCandidateSessionCurrent = async () => {
939
+ const currentPayload = await readSessionPayloadFile();
940
+ if (!isCandidateSessionCurrent(currentPayload)) throw new Error("auth session changed before the setup transition completed");
941
+ };
942
+ const restoreMissingJournalTransition = async () => {
943
+ const currentPayload = await readSessionPayloadFile();
944
+ if (!isCandidateSessionCurrent(currentPayload)) {
945
+ try {
946
+ await cleanupTransitionTokensNotReferencedByCurrentSession({
947
+ currentPayload,
948
+ journal
949
+ });
950
+ } finally {
951
+ activeAuthSessionTransitionIds.delete(journal.id);
952
+ }
953
+ throw new AuthSessionTransitionConflictError({
954
+ previousOwnerRestored: false,
955
+ reason: "journal_missing"
956
+ });
957
+ }
958
+ await claimAuthSessionTransitionJournal(journal);
959
+ try {
960
+ await restoreTransitionPreviousPayload(journal, previousSession);
961
+ settlement = "rolled_back";
962
+ await deleteAccessTokenOrRetainForCleanup(tokenRef).catch((error) => {
963
+ logDeferredAuthSessionTransitionCleanup({
964
+ error,
965
+ transitionId: journal.id
966
+ });
967
+ });
968
+ } finally {
969
+ activeAuthSessionTransitionIds.delete(journal.id);
970
+ await removeAuthSessionTransitionJournalIfOwned(journal);
971
+ }
972
+ };
973
+ return {
974
+ previousSession,
975
+ commit: async () => await withAuthSessionTransitionMutationLock(async () => {
976
+ assertTransitionPending();
977
+ const currentJournal = await readOwnedPendingAuthSessionTransition(journal);
978
+ if (currentJournal.status === "missing") {
979
+ await restoreMissingJournalTransition();
980
+ throw new AuthSessionTransitionConflictError({
981
+ previousOwnerRestored: true,
982
+ reason: "journal_missing"
983
+ });
984
+ }
985
+ if (currentJournal.status !== "current") {
986
+ activeAuthSessionTransitionIds.delete(journal.id);
987
+ throw new AuthSessionTransitionConflictError({
988
+ previousOwnerRestored: false,
989
+ reason: currentJournal.status
990
+ });
991
+ }
992
+ await assertCandidateSessionCurrent();
993
+ const committedJournal = {
994
+ ...currentJournal.journal,
995
+ state: "committed"
996
+ };
997
+ await writeAuthSessionTransitionJournalIfOwned(currentJournal.journal, committedJournal);
998
+ settlement = "committed";
999
+ activeAuthSessionTransitionIds.delete(journal.id);
1000
+ await finalizeCommittedAuthSessionTransition(committedJournal).catch((error) => {
1001
+ logDeferredAuthSessionTransitionCleanup({
1002
+ error,
1003
+ transitionId: journal.id
1004
+ });
1005
+ });
1006
+ }),
1007
+ rollback: async () => await withAuthSessionTransitionMutationLock(async () => {
1008
+ if (settlement === "rolled_back") return;
1009
+ assertTransitionPending();
1010
+ const currentJournal = await readOwnedPendingAuthSessionTransition(journal);
1011
+ if (currentJournal.status === "missing") {
1012
+ await restoreMissingJournalTransition();
1013
+ return;
1014
+ }
1015
+ if (currentJournal.status !== "current") {
1016
+ activeAuthSessionTransitionIds.delete(journal.id);
1017
+ throw new AuthSessionTransitionConflictError({
1018
+ previousOwnerRestored: false,
1019
+ reason: currentJournal.status
1020
+ });
1021
+ }
1022
+ await assertCandidateSessionCurrent();
1023
+ await restoreTransitionPreviousPayload(currentJournal.journal, previousSession);
1024
+ settlement = "rolled_back";
1025
+ activeAuthSessionTransitionIds.delete(journal.id);
1026
+ stopRegisteredCandidateService(currentJournal.journal);
1027
+ if (currentJournal.journal.computerHandoff) {
1028
+ await writeAuthSessionTransitionJournalIfOwned(currentJournal.journal, {
1029
+ ...currentJournal.journal,
1030
+ state: "recovery_required"
1031
+ });
1032
+ return;
1033
+ }
1034
+ await deleteAccessTokenOrRetainForCleanup(tokenRef);
1035
+ await removeAuthSessionTransitionJournalIfOwned(currentJournal.journal);
1036
+ })
1037
+ };
1038
+ });
1039
+ }
1040
+ async function readOwnedPendingAuthSessionTransition(expected) {
1041
+ const currentJournal = await readAuthSessionTransitionJournal();
1042
+ if (!currentJournal) return { status: "missing" };
1043
+ if (!hasSameAuthSessionTransitionIdentity(expected, currentJournal)) return {
1044
+ status: "journal_replaced",
1045
+ journal: currentJournal
1046
+ };
1047
+ if (currentJournal.state !== "pending") return {
1048
+ status: "journal_not_pending",
1049
+ journal: currentJournal
1050
+ };
1051
+ return {
1052
+ status: "current",
1053
+ journal: currentJournal
1054
+ };
1055
+ }
1056
+ async function getInterruptedComputerAuthSessionRecovery() {
1057
+ return await withAuthSessionTransitionMutationLock(async () => {
1058
+ await recoverInterruptedAuthSessionTransitionWithOwnership();
1059
+ const journal = await readAuthSessionTransitionJournal();
1060
+ if (!(journal?.state === "recovery_required" && journal.computerHandoff)) return null;
1061
+ const candidateSession = await readStoredAuthSessionFromPayloadIfPresent(journal.candidatePayload);
1062
+ if (!candidateSession) {
1063
+ if (journal.computerHandoff.serviceReconciledAt && journal.computerHandoff.remoteSessionRevokedAt) {
1064
+ await removeAuthSessionTransitionJournalIfOwned(journal);
1065
+ return null;
1066
+ }
1067
+ throw new AuthSessionStorageError({
1068
+ message: "auth session recovery token is missing",
1069
+ reason: "corrupt"
1070
+ });
1071
+ }
1072
+ const candidateOwnerUserId = normalizeOptionalString(candidateSession.user?.id);
1073
+ if (!candidateOwnerUserId) throw new AuthSessionStorageError({
1074
+ message: "computer auth recovery candidate is missing its owner user id",
1075
+ reason: "corrupt"
1076
+ });
1077
+ return {
1078
+ candidateSession: {
1079
+ ...candidateSession,
1080
+ user: {
1081
+ ...candidateSession.user,
1082
+ id: candidateOwnerUserId
1083
+ }
1084
+ },
1085
+ gatewayUrl: journal.computerHandoff.gatewayUrl,
1086
+ id: journal.id,
1087
+ previousSession: journal.previousPayload ? await readStoredAuthSessionFromPayload(journal.previousPayload) : null,
1088
+ remoteSessionRevoked: Boolean(journal.computerHandoff.remoteSessionRevokedAt),
1089
+ serviceReconciled: Boolean(journal.computerHandoff.serviceReconciledAt)
1090
+ };
1091
+ });
1092
+ }
1093
+ async function markInterruptedComputerAuthSessionRecovery(input) {
1094
+ await withAuthSessionTransitionMutationLock(async () => {
1095
+ const journal = await readRequiredComputerAuthRecoveryJournal(input.id);
1096
+ await writeAuthSessionTransitionJournalIfOwned(journal, {
1097
+ ...journal,
1098
+ computerHandoff: {
1099
+ ...journal.computerHandoff,
1100
+ ...input.phase === "service" ? { serviceReconciledAt: (/* @__PURE__ */ new Date()).toISOString() } : { remoteSessionRevokedAt: (/* @__PURE__ */ new Date()).toISOString() },
1101
+ lastRecoveryFailure: void 0
1102
+ }
1103
+ });
1104
+ });
1105
+ }
1106
+ async function recordInterruptedComputerAuthSessionRecoveryFailure(input) {
1107
+ await withAuthSessionTransitionMutationLock(async () => {
1108
+ await recordInterruptedComputerAuthSessionRecoveryFailureWithOwnership(input);
1109
+ });
1110
+ }
1111
+ async function recordInterruptedComputerAuthSessionRecoveryFailureWithOwnership(input) {
1112
+ const journal = await readRequiredComputerAuthRecoveryJournal(input.id);
1113
+ await writeAuthSessionTransitionJournalIfOwned(journal, {
1114
+ ...journal,
1115
+ computerHandoff: {
1116
+ ...journal.computerHandoff,
1117
+ lastRecoveryFailure: {
1118
+ at: (/* @__PURE__ */ new Date()).toISOString(),
1119
+ message: input.message,
1120
+ phase: input.phase,
1121
+ ...input.endpoint ? { endpoint: input.endpoint } : {},
1122
+ ...input.status === void 0 ? {} : { status: input.status }
1123
+ }
1124
+ }
1125
+ });
1126
+ }
1127
+ async function completeInterruptedComputerAuthSessionRecovery(id) {
1128
+ return await withAuthSessionTransitionMutationLock(async () => {
1129
+ const journal = await readRequiredComputerAuthRecoveryJournal(id);
1130
+ if (!(journal.computerHandoff.serviceReconciledAt && journal.computerHandoff.remoteSessionRevokedAt)) throw new Error("computer auth recovery cannot complete before service and remote-session cleanup");
1131
+ try {
1132
+ await deleteAccessTokenOrRetainForCleanup(journal.candidatePayload.tokenRef);
1133
+ await removeAuthSessionTransitionJournalIfOwned(journal);
1134
+ return true;
1135
+ } catch (error) {
1136
+ await recordInterruptedComputerAuthSessionRecoveryFailureWithOwnership({
1137
+ id,
1138
+ message: toErrorMessage(error),
1139
+ phase: "local_cleanup"
1140
+ }).catch(() => void 0);
1141
+ logDeferredAuthSessionTransitionCleanup({
1142
+ error,
1143
+ transitionId: id
1144
+ });
1145
+ return false;
1146
+ }
1147
+ });
1148
+ }
1149
+ async function getAuthSessionMetadata() {
1150
+ const payload = await readSessionPayload();
1151
+ if (payload?.v !== 1) return null;
1152
+ const authBaseUrl = normalizeOptionalString(payload.authBaseUrl);
1153
+ const clientId = normalizeOptionalString(payload.clientId);
1154
+ const createdAt = normalizeOptionalString(payload.createdAt);
1155
+ if (!(authBaseUrl && clientId && createdAt)) return null;
1156
+ return {
1157
+ authBaseUrl,
1158
+ clientId,
1159
+ createdAt,
1160
+ ...typeof payload.expiresAt === "string" && payload.expiresAt.trim() ? { expiresAt: payload.expiresAt.trim() } : {},
1161
+ ...typeof payload.scope === "string" && payload.scope.trim() ? { scope: payload.scope.trim() } : {},
1162
+ ...buildAuthUserPayload(payload.user),
1163
+ ...buildActiveOrganizationPayload(payload.activeOrganization)
1164
+ };
1165
+ }
1166
+ async function updateAuthSessionActiveOrganization(activeOrganization) {
1167
+ await withAuthSessionTransitionMutationLock(async () => {
1168
+ await assertAuthSessionMutationAvailableWithOwnership();
1169
+ const payload = await readSessionPayloadFile();
1170
+ if (payload?.v !== 1) throw new Error("cannot update active organization without auth session");
1171
+ const tokenRef = normalizeTokenRef(payload.tokenRef);
1172
+ const tokenType = normalizeOptionalString(payload.tokenType);
1173
+ const authBaseUrl = normalizeOptionalString(payload.authBaseUrl);
1174
+ const clientId = normalizeOptionalString(payload.clientId);
1175
+ const createdAt = normalizeOptionalString(payload.createdAt);
1176
+ if (!(tokenRef && tokenType && authBaseUrl && clientId && createdAt)) throw new Error("cannot update active organization for invalid auth session");
1177
+ const nextPayload = {
1178
+ v: 1,
1179
+ tokenRef,
1180
+ tokenType,
1181
+ authBaseUrl,
1182
+ clientId,
1183
+ createdAt,
1184
+ ...typeof payload.expiresAt === "string" && payload.expiresAt.trim() ? { expiresAt: payload.expiresAt.trim() } : {},
1185
+ ...typeof payload.scope === "string" && payload.scope.trim() ? { scope: payload.scope.trim() } : {},
1186
+ ...buildAuthUserPayload(payload.user),
1187
+ ...buildActiveOrganizationPayload(activeOrganization)
1188
+ };
1189
+ await writeSessionPayloadAtomically(authSessionPath(), nextPayload);
1190
+ const currentCachedSession = readCachedAuthSession(payload);
1191
+ if (currentCachedSession) cacheAuthSession({
1192
+ payload: nextPayload,
1193
+ session: buildStoredAuthSession({
1194
+ accessToken: currentCachedSession.accessToken,
1195
+ payload: nextPayload
1196
+ })
1197
+ });
1198
+ });
1199
+ }
1200
+ async function clearAuthSession() {
1201
+ return await withAuthSessionTransitionMutationLock(async () => {
1202
+ await assertAuthSessionMutationAvailableWithOwnership();
1203
+ cachedAuthSession = null;
1204
+ await retryPendingTokenCleanup();
1205
+ const hadLocalSession = await authSessionFileExists();
1206
+ const payload = await readSessionPayloadFile();
1207
+ if (payload?.v === 1 && isStoredTokenRef(payload.tokenRef)) await deleteAccessTokenOrRetainForCleanup(payload.tokenRef);
1208
+ await removeSessionFile();
1209
+ return { hadLocalSession };
1210
+ });
1211
+ }
1212
+ async function assertAuthSessionMutationAvailable() {
1213
+ await withAuthSessionTransitionMutationLock(assertAuthSessionMutationAvailableWithOwnership);
1214
+ }
1215
+ async function assertAuthSessionMutationAvailableWithOwnership() {
1216
+ await recoverInterruptedAuthSessionTransitionWithOwnership();
1217
+ if (await readAuthSessionTransitionJournal()) throw new AuthSessionRecoveryInProgressError();
1218
+ }
1219
+ async function retryPendingTokenCleanup() {
1220
+ const pending = await readPendingTokenCleanup();
1221
+ if (pending.tokenRefs.length === 0) return;
1222
+ const remaining = [];
1223
+ for (const tokenRef of pending.tokenRefs) try {
1224
+ await deleteAccessToken(tokenRef);
1225
+ } catch {
1226
+ remaining.push(tokenRef);
1227
+ }
1228
+ await persistPendingTokenCleanup(remaining);
1229
+ }
1230
+ async function deleteAccessTokenOrRetainForCleanup(tokenRef) {
1231
+ try {
1232
+ await deleteAccessToken(tokenRef);
1233
+ } catch {
1234
+ const pending = await readPendingTokenCleanup();
1235
+ if (pending.tokenRefs.some((ref) => areStoredTokenRefsEqual(ref, tokenRef))) return;
1236
+ await persistPendingTokenCleanup([...pending.tokenRefs, tokenRef]);
1237
+ }
1238
+ }
1239
+ async function readPendingTokenCleanup() {
1240
+ const raw = await readFile(pendingTokenCleanupPath(), "utf8").catch((error) => {
1241
+ if (isFileNotFoundError(error)) return null;
1242
+ throw error;
1243
+ });
1244
+ if (raw === null) return {
1245
+ v: 1,
1246
+ tokenRefs: []
1247
+ };
1248
+ let parsed;
1249
+ try {
1250
+ parsed = JSON.parse(raw);
1251
+ } catch {
1252
+ throw new Error("pending access-token cleanup state is invalid");
1253
+ }
1254
+ if (!(isRecord(parsed) && parsed.v === 1 && Array.isArray(parsed.tokenRefs))) throw new Error("pending access-token cleanup state is invalid");
1255
+ const tokenRefs = parsed.tokenRefs.filter(isStoredTokenRef);
1256
+ if (tokenRefs.length !== parsed.tokenRefs.length) throw new Error("pending access-token cleanup state is invalid");
1257
+ return {
1258
+ v: 1,
1259
+ tokenRefs
1260
+ };
1261
+ }
1262
+ async function persistPendingTokenCleanup(tokenRefs) {
1263
+ const path = pendingTokenCleanupPath();
1264
+ if (tokenRefs.length === 0) {
1265
+ await rm(path, { force: true });
1266
+ return;
1267
+ }
1268
+ await mkdir(join(openMeldRootDir(), "auth"), { recursive: true });
1269
+ await writeJsonAtomically(path, {
1270
+ v: 1,
1271
+ tokenRefs
1272
+ });
1273
+ }
1274
+ function pendingTokenCleanupPath() {
1275
+ return join(openMeldRootDir(), "auth", "pending-token-cleanup.json");
1276
+ }
1277
+ async function authSessionFileExists() {
1278
+ try {
1279
+ await readFile(authSessionPath(), "utf8");
1280
+ return true;
1281
+ } catch (error) {
1282
+ if (isFileNotFoundError(error)) return false;
1283
+ throw error;
1284
+ }
1285
+ }
1286
+ async function getLocalAuthSessionState(options = {}) {
1287
+ let payload;
1288
+ try {
1289
+ payload = options.recover === false ? await readSessionPayloadFile() : await readSessionPayload();
1290
+ } catch (error) {
1291
+ if (error instanceof AuthSessionStorageError) return {
1292
+ errorMessage: error.message,
1293
+ reasonCode: "session_metadata_invalid",
1294
+ state: "invalid",
1295
+ session: null
1296
+ };
1297
+ throw error;
1298
+ }
1299
+ if (payload?.v !== 1) return {
1300
+ reasonCode: "session_missing",
1301
+ state: "missing",
1302
+ session: null
1303
+ };
1304
+ const tokenRef = normalizeTokenRef(payload.tokenRef);
1305
+ if (!tokenRef) return {
1306
+ reasonCode: "session_token_ref_invalid",
1307
+ state: "invalid",
1308
+ session: null
1309
+ };
1310
+ const tokenType = normalizeOptionalString(payload.tokenType);
1311
+ const authBaseUrl = normalizeOptionalString(payload.authBaseUrl);
1312
+ const clientId = normalizeOptionalString(payload.clientId);
1313
+ const createdAt = normalizeOptionalString(payload.createdAt);
1314
+ if (!(tokenType && authBaseUrl && clientId && createdAt)) return {
1315
+ reasonCode: "session_metadata_invalid",
1316
+ state: "invalid",
1317
+ session: null
1318
+ };
1319
+ let session = readCachedAuthSession(payload);
1320
+ if (!session) {
1321
+ const accessToken = await readAccessToken(tokenRef);
1322
+ if (accessToken.status === "missing") return {
1323
+ reasonCode: "session_token_missing",
1324
+ state: "invalid",
1325
+ session: null
1326
+ };
1327
+ if (accessToken.status === "unavailable") return {
1328
+ errorMessage: accessToken.errorMessage,
1329
+ reasonCode: "session_token_unavailable",
1330
+ state: "invalid",
1331
+ session: null
1332
+ };
1333
+ session = buildStoredAuthSession({
1334
+ accessToken: accessToken.accessToken,
1335
+ payload: {
1336
+ ...payload,
1337
+ v: 1,
1338
+ tokenRef,
1339
+ tokenType,
1340
+ authBaseUrl,
1341
+ clientId,
1342
+ createdAt
1343
+ }
1344
+ });
1345
+ cacheAuthSession({
1346
+ payload,
1347
+ session
1348
+ });
1349
+ }
1350
+ const expiryEligibility = resolveAuthSessionExpiryEligibility(session.expiresAt);
1351
+ if (expiryEligibility.status === "invalid") return {
1352
+ reasonCode: "session_expiry_invalid",
1353
+ state: "invalid",
1354
+ session: null
1355
+ };
1356
+ if (expiryEligibility.status === "expired") return {
1357
+ reasonCode: "session_expired",
1358
+ state: "expired",
1359
+ session
1360
+ };
1361
+ return {
1362
+ state: "valid",
1363
+ session
1364
+ };
1365
+ }
1366
+ async function assertStoredAccessTokenReloads(input) {
1367
+ const reloaded = await readAccessToken(input.tokenRef);
1368
+ if (reloaded.status === "found" && reloaded.accessToken === input.accessToken) return;
1369
+ if (reloaded.status === "unavailable") throw new Error(`stored access token could not be reloaded: ${reloaded.errorMessage}`);
1370
+ throw new Error("stored access token could not be reloaded");
1371
+ }
1372
+ function buildStoredAuthSession(input) {
1373
+ return {
1374
+ v: 1,
1375
+ accessToken: input.accessToken,
1376
+ tokenType: input.payload.tokenType,
1377
+ authBaseUrl: input.payload.authBaseUrl,
1378
+ clientId: input.payload.clientId,
1379
+ createdAt: input.payload.createdAt,
1380
+ ...typeof input.payload.expiresAt === "string" && input.payload.expiresAt.trim() ? { expiresAt: input.payload.expiresAt.trim() } : {},
1381
+ ...typeof input.payload.scope === "string" && input.payload.scope.trim() ? { scope: input.payload.scope.trim() } : {},
1382
+ ...buildAuthUserPayload(input.payload.user),
1383
+ ...buildActiveOrganizationPayload(input.payload.activeOrganization)
1384
+ };
1385
+ }
1386
+ async function cleanupTransitionTokensNotReferencedByCurrentSession(input) {
1387
+ const currentTokenRef = normalizeTokenRef(input.currentPayload?.tokenRef);
1388
+ const previousTokenRef = normalizeTokenRef(input.journal.previousPayload?.tokenRef);
1389
+ const transitionTokenRefs = [...previousTokenRef ? [previousTokenRef] : [], input.journal.candidatePayload.tokenRef];
1390
+ for (const [index, tokenRef] of transitionTokenRefs.entries()) {
1391
+ if (transitionTokenRefs.slice(0, index).some((previousRef) => areStoredTokenRefsEqual(previousRef, tokenRef)) || currentTokenRef && areStoredTokenRefsEqual(currentTokenRef, tokenRef)) continue;
1392
+ await deleteAccessTokenOrRetainForCleanup(tokenRef);
1393
+ }
1394
+ }
1395
+ function cacheAuthSession(input) {
1396
+ cachedAuthSession = {
1397
+ payloadKey: buildAuthSessionPayloadKey(input.payload),
1398
+ session: input.session
1399
+ };
1400
+ }
1401
+ function readCachedAuthSession(payload) {
1402
+ const payloadKey = buildAuthSessionPayloadKey(payload);
1403
+ return cachedAuthSession?.payloadKey === payloadKey ? cachedAuthSession.session : null;
1404
+ }
1405
+ function buildAuthSessionPayloadKey(payload) {
1406
+ return `${authSessionPath()}\n${JSON.stringify(payload)}`;
1407
+ }
1408
+ function areStoredTokenRefsEqual(left, right) {
1409
+ return JSON.stringify(left) === JSON.stringify(right);
1410
+ }
1411
+ async function persistRemoteSessionRefresh(input) {
1412
+ return await withAuthSessionTransitionMutationLock(async () => {
1413
+ await assertAuthSessionMutationAvailableWithOwnership();
1414
+ const payload = await readSessionPayloadFile();
1415
+ if (payload?.v !== 1 || input.expectedPayloadKey === null || buildAuthSessionPayloadKey(payload) !== input.expectedPayloadKey) return null;
1416
+ const tokenRef = normalizeTokenRef(payload.tokenRef);
1417
+ const tokenType = normalizeOptionalString(payload.tokenType);
1418
+ const authBaseUrl = normalizeOptionalString(payload.authBaseUrl);
1419
+ const clientId = normalizeOptionalString(payload.clientId);
1420
+ const createdAt = normalizeOptionalString(payload.createdAt);
1421
+ if (!(tokenRef && tokenType && authBaseUrl && clientId && createdAt)) return null;
1422
+ const nextAccessToken = normalizeOptionalString(input.accessToken);
1423
+ if (!nextAccessToken) return null;
1424
+ const nextTokenRef = nextAccessToken === input.previousAccessToken ? tokenRef : await storeAccessToken({
1425
+ accessToken: nextAccessToken,
1426
+ authBaseUrl,
1427
+ clientId
1428
+ });
1429
+ const nextPayload = {
1430
+ v: 1,
1431
+ tokenRef: nextTokenRef,
1432
+ tokenType,
1433
+ authBaseUrl,
1434
+ clientId,
1435
+ createdAt,
1436
+ expiresAt: input.expiresAt,
1437
+ ...typeof payload.scope === "string" && payload.scope.trim() ? { scope: payload.scope.trim() } : {},
1438
+ ...buildAuthUserPayload(payload.user),
1439
+ ...buildActiveOrganizationPayload(payload.activeOrganization)
1440
+ };
1441
+ const nextSession = buildStoredAuthSession({
1442
+ accessToken: nextAccessToken,
1443
+ payload: nextPayload
1444
+ });
1445
+ try {
1446
+ await assertStoredAccessTokenReloads({
1447
+ accessToken: nextAccessToken,
1448
+ tokenRef: nextTokenRef
1449
+ });
1450
+ await writeSessionPayloadAtomically(authSessionPath(), nextPayload);
1451
+ } catch (error) {
1452
+ if (!areStoredTokenRefsEqual(tokenRef, nextTokenRef)) await deleteAccessTokenOrRetainForCleanup(nextTokenRef);
1453
+ throw error;
1454
+ }
1455
+ cacheAuthSession({
1456
+ payload: nextPayload,
1457
+ session: nextSession
1458
+ });
1459
+ if (!areStoredTokenRefsEqual(tokenRef, nextTokenRef)) await deleteAccessTokenOrRetainForCleanup(tokenRef);
1460
+ return nextSession;
1461
+ });
1462
+ }
1463
+ function normalizeTokenRef(input) {
1464
+ if (!isStoredTokenRef(input)) return null;
1465
+ return input;
1466
+ }
1467
+ async function getRemoteAuthSessionState(session) {
1468
+ let endpoint = "";
1469
+ try {
1470
+ endpoint = toAuthEndpoint(session.authBaseUrl, "/api/auth/get-session");
1471
+ } catch {
1472
+ return { state: "invalid" };
1473
+ }
1474
+ try {
1475
+ const timeoutMs = resolveRemoteSessionTimeoutMs(endpoint);
1476
+ const response = await fetch(endpoint, {
1477
+ method: "GET",
1478
+ headers: { Authorization: `${normalizeTokenType(session.tokenType)} ${session.accessToken}` },
1479
+ signal: AbortSignal.timeout(timeoutMs)
1480
+ });
1481
+ if (response.status === 401 || response.status === 403) return { state: "revoked" };
1482
+ if (!response.ok) return { state: "unknown" };
1483
+ const payload = await parseResponseJson(response);
1484
+ if (!hasActiveSessionPayload(payload)) return { state: "invalid" };
1485
+ return {
1486
+ state: "valid",
1487
+ ...readRemoteAccessToken(response),
1488
+ ...readRemoteSessionExpiration(payload)
1489
+ };
1490
+ } catch {
1491
+ return { state: "unknown" };
1492
+ }
1493
+ }
1494
+ function readRemoteAccessToken(response) {
1495
+ const accessToken = normalizeOptionalString(response.headers.get("set-auth-token"));
1496
+ return accessToken ? { accessToken } : {};
1497
+ }
1498
+ function readRemoteSessionExpiration(payload) {
1499
+ if (!isRecord(payload)) return {};
1500
+ const session = payload.session;
1501
+ if (!isRecord(session)) return {};
1502
+ const expiresAt = normalizeOptionalString(session.expiresAt);
1503
+ if (!expiresAt) return {};
1504
+ const expiresAtMs = Date.parse(expiresAt);
1505
+ if (Number.isNaN(expiresAtMs)) return {};
1506
+ return { expiresAt: new Date(expiresAtMs).toISOString() };
1507
+ }
1508
+ function resolveRemoteSessionTimeoutMs(endpoint) {
1509
+ const url = parseUrlOrNull(endpoint);
1510
+ if (url && isLoopbackHostname(url.hostname)) return LOOPBACK_REMOTE_SESSION_TIMEOUT_MS;
1511
+ return DEFAULT_REMOTE_SESSION_TIMEOUT_MS;
1512
+ }
1513
+ function parseUrlOrNull(value) {
1514
+ try {
1515
+ return new URL(value);
1516
+ } catch {
1517
+ return null;
1518
+ }
1519
+ }
1520
+ function isLoopbackHostname(hostname) {
1521
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
1522
+ }
1523
+ function hasActiveSessionPayload(payload) {
1524
+ if (!isRecord(payload)) return false;
1525
+ return isRecord(payload.session) && isRecord(payload.user);
1526
+ }
1527
+ function isExpired(expiresAt) {
1528
+ return resolveAuthSessionExpiryEligibility(expiresAt).status === "expired";
1529
+ }
1530
+ function resolveRemoteAuthSessionReasonCode(state) {
1531
+ switch (state) {
1532
+ case "invalid": return "remote_session_invalid";
1533
+ case "revoked": return "remote_session_revoked";
1534
+ default: throw new Error(`unsupported remote auth session state: ${state}`);
1535
+ }
1536
+ }
1537
+ async function readSessionPayload() {
1538
+ await recoverInterruptedAuthSessionTransition();
1539
+ return await readSessionPayloadFile();
1540
+ }
1541
+ async function readSessionPayloadFile() {
1542
+ const path = authSessionPath();
1543
+ const raw = await readFile(path, "utf8").catch((error) => {
1544
+ if (isFileNotFoundError(error)) return null;
1545
+ throw new AuthSessionStorageError({
1546
+ message: `current auth session metadata could not be read at ${path}: ${toErrorMessage(error)}`,
1547
+ reason: "unreadable",
1548
+ cause: error
1549
+ });
1550
+ });
1551
+ if (raw === null) return null;
1552
+ try {
1553
+ return JSON.parse(raw);
1554
+ } catch (error) {
1555
+ throw new AuthSessionStorageError({
1556
+ message: `current auth session metadata is corrupt at ${path}`,
1557
+ reason: "corrupt",
1558
+ cause: error
1559
+ });
1560
+ }
1561
+ }
1562
+ async function recoverInterruptedAuthSessionTransition() {
1563
+ await withAuthSessionTransitionMutationLock(recoverInterruptedAuthSessionTransitionWithOwnership);
1564
+ }
1565
+ async function recoverInterruptedAuthSessionTransitionWithOwnership() {
1566
+ let journal = await readAuthSessionTransitionJournal();
1567
+ if (!journal) return;
1568
+ if (activeAuthSessionTransitionIds.has(journal.id)) return;
1569
+ if (journal.state === "pending" && isProcessIdentityAlive({
1570
+ ownerPid: journal.ownerPid,
1571
+ ownerProcessStartedAt: journal.ownerProcessStartedAt
1572
+ })) {
1573
+ journal = await registerCurrentCandidateServiceProcess(journal);
1574
+ return;
1575
+ }
1576
+ if (journal.state === "pending") {
1577
+ await restoreTransitionPreviousPayload(journal);
1578
+ stopRegisteredCandidateService(journal);
1579
+ if (journal.computerHandoff) {
1580
+ await writeAuthSessionTransitionJournalIfOwned(journal, {
1581
+ ...journal,
1582
+ state: "recovery_required"
1583
+ });
1584
+ return;
1585
+ }
1586
+ await deleteAccessTokenOrRetainForCleanup(journal.candidatePayload.tokenRef);
1587
+ await removeAuthSessionTransitionJournalIfOwned(journal);
1588
+ return;
1589
+ }
1590
+ if (journal.state === "recovery_required") {
1591
+ stopRegisteredCandidateService(journal);
1592
+ return;
1593
+ }
1594
+ if (journal.state === "committed") {
1595
+ const currentPayload = await readSessionPayloadFile();
1596
+ if (currentPayload?.v !== 1 || buildAuthSessionPayloadKey(currentPayload) !== buildAuthSessionPayloadKey(journal.candidatePayload)) throw new AuthSessionStorageError({
1597
+ message: "committed auth session transition does not match current session metadata",
1598
+ reason: "corrupt"
1599
+ });
1600
+ await finalizeCommittedAuthSessionTransition(journal).catch((error) => {
1601
+ logDeferredAuthSessionTransitionCleanup({
1602
+ error,
1603
+ transitionId: journal.id
1604
+ });
1605
+ });
1606
+ }
1607
+ }
1608
+ async function finalizeCommittedAuthSessionTransition(journal) {
1609
+ const previousTokenRef = normalizeTokenRef(journal.previousPayload?.tokenRef);
1610
+ if (previousTokenRef && !areStoredTokenRefsEqual(previousTokenRef, journal.candidatePayload.tokenRef)) await deleteAccessTokenOrRetainForCleanup(previousTokenRef);
1611
+ await removeAuthSessionTransitionJournalIfOwned(journal);
1612
+ }
1613
+ async function registerCurrentCandidateServiceProcess(journal) {
1614
+ if (!isCurrentProcessCandidateService()) return journal;
1615
+ const currentProcess = {
1616
+ ownerPid: process.pid,
1617
+ ownerProcessStartedAt: CURRENT_PROCESS_START_IDENTITY
1618
+ };
1619
+ if (journal.candidateServiceProcess?.ownerPid === currentProcess.ownerPid && journal.candidateServiceProcess.ownerProcessStartedAt === currentProcess.ownerProcessStartedAt) return journal;
1620
+ const currentJournal = await readAuthSessionTransitionJournal();
1621
+ if (currentJournal?.id !== journal.id || currentJournal.state !== "pending") return currentJournal ?? journal;
1622
+ const updatedJournal = {
1623
+ ...currentJournal,
1624
+ candidateServiceProcess: currentProcess
1625
+ };
1626
+ await writeAuthSessionTransitionJournalIfOwned(currentJournal, updatedJournal);
1627
+ return updatedJournal;
1628
+ }
1629
+ function stopRegisteredCandidateService(journal) {
1630
+ const candidateServiceProcess = journal.candidateServiceProcess;
1631
+ if (!(candidateServiceProcess && isProcessIdentityAlive(candidateServiceProcess))) return;
1632
+ try {
1633
+ process.kill(candidateServiceProcess.ownerPid, "SIGTERM");
1634
+ } catch (error) {
1635
+ if (!isFileNotFoundErrorCode(error, "ESRCH")) throw new AuthSessionStorageError({
1636
+ message: `candidate OpenMeld Service process ${String(candidateServiceProcess.ownerPid)} could not be stopped: ${toErrorMessage(error)}`,
1637
+ reason: "unreadable",
1638
+ cause: error
1639
+ });
1640
+ }
1641
+ }
1642
+ function isCurrentProcessCandidateService() {
1643
+ const runtimeMode = String(process.env.OPENMELD_DAEMON_RUNTIME_MODE ?? "").trim();
1644
+ return runtimeMode === "background" || runtimeMode === "foreground";
1645
+ }
1646
+ async function readStoredAuthSessionFromPayload(payload) {
1647
+ const session = await readStoredAuthSessionFromPayloadIfPresent(payload);
1648
+ if (!session) throw new AuthSessionStorageError({
1649
+ message: "auth session recovery token is missing",
1650
+ reason: "corrupt"
1651
+ });
1652
+ return session;
1653
+ }
1654
+ async function readStoredAuthSessionFromPayloadIfPresent(payload) {
1655
+ const accessToken = await readAccessToken(payload.tokenRef);
1656
+ if (accessToken.status === "missing") return null;
1657
+ if (accessToken.status === "unavailable") throw new AuthSessionStorageError({
1658
+ message: accessToken.errorMessage,
1659
+ reason: "unreadable"
1660
+ });
1661
+ return buildStoredAuthSession({
1662
+ accessToken: accessToken.accessToken,
1663
+ payload
1664
+ });
1665
+ }
1666
+ async function readRequiredComputerAuthRecoveryJournal(id) {
1667
+ const journal = await readAuthSessionTransitionJournal();
1668
+ if (journal?.id !== id || journal.state !== "recovery_required" || !journal.computerHandoff) throw new Error("computer auth recovery is no longer current");
1669
+ return journal;
1670
+ }
1671
+ function logDeferredAuthSessionTransitionCleanup(input) {
1672
+ console.warn("[openmeld.auth.session_transition_cleanup_deferred]", {
1673
+ error: toErrorMessage(input.error),
1674
+ transitionId: input.transitionId
1675
+ });
1676
+ }
1677
+ async function restoreTransitionPreviousPayload(journal, previousSession) {
1678
+ cachedAuthSession = null;
1679
+ if (!journal.previousPayload) {
1680
+ await removeSessionFile();
1681
+ return;
1682
+ }
1683
+ await writeSessionPayloadAtomically(authSessionPath(), journal.previousPayload);
1684
+ if (previousSession) cacheAuthSession({
1685
+ payload: journal.previousPayload,
1686
+ session: previousSession
1687
+ });
1688
+ }
1689
+ async function readAuthSessionTransitionJournal() {
1690
+ const path = authSessionTransitionPath();
1691
+ const raw = await readFile(path, "utf8").catch((error) => {
1692
+ if (isFileNotFoundError(error)) return null;
1693
+ throw new AuthSessionStorageError({
1694
+ message: `auth session transition state could not be read at ${path}: ${toErrorMessage(error)}`,
1695
+ reason: "unreadable",
1696
+ cause: error
1697
+ });
1698
+ });
1699
+ if (raw === null) return null;
1700
+ let value;
1701
+ try {
1702
+ value = JSON.parse(raw);
1703
+ } catch (error) {
1704
+ throw new AuthSessionStorageError({
1705
+ message: `auth session transition state is corrupt at ${path}`,
1706
+ reason: "corrupt",
1707
+ cause: error
1708
+ });
1709
+ }
1710
+ if (!isAuthSessionTransitionJournal(value)) throw new AuthSessionStorageError({
1711
+ message: `auth session transition state is corrupt at ${path}`,
1712
+ reason: "corrupt"
1713
+ });
1714
+ return value;
1715
+ }
1716
+ function isAuthSessionTransitionJournal(value) {
1717
+ if (!isRecord(value)) return false;
1718
+ return value.v === 1 && typeof value.id === "string" && value.id.length > 0 && (value.state === "pending" || value.state === "recovery_required" || value.state === "committed") && Number.isSafeInteger(value.ownerPid) && Number(value.ownerPid) > 0 && typeof value.ownerProcessStartedAt === "string" && value.ownerProcessStartedAt.length > 0 && (value.previousPayload === null || isAuthSessionPayload(value.previousPayload)) && isAuthSessionPayload(value.candidatePayload) && isOptionalProcessIdentity(value.candidateServiceProcess) && isOptionalComputerHandoffRecovery(value.computerHandoff);
1719
+ }
1720
+ function isOptionalProcessIdentity(value) {
1721
+ return value === void 0 || isRecord(value) && Number.isSafeInteger(value.ownerPid) && Number(value.ownerPid) > 0 && typeof value.ownerProcessStartedAt === "string" && value.ownerProcessStartedAt.length > 0;
1722
+ }
1723
+ function isOptionalComputerHandoffRecovery(value) {
1724
+ if (value === void 0) return true;
1725
+ if (!(isRecord(value) && typeof value.gatewayUrl === "string")) return false;
1726
+ return (value.serviceReconciledAt === void 0 || typeof value.serviceReconciledAt === "string") && (value.remoteSessionRevokedAt === void 0 || typeof value.remoteSessionRevokedAt === "string") && (value.lastRecoveryFailure === void 0 || isComputerHandoffRecoveryFailure(value.lastRecoveryFailure));
1727
+ }
1728
+ function isComputerHandoffRecoveryFailure(value) {
1729
+ return isRecord(value) && typeof value.at === "string" && typeof value.message === "string" && (value.phase === "service" || value.phase === "remote_session" || value.phase === "local_cleanup") && (value.endpoint === void 0 || typeof value.endpoint === "string") && (value.status === void 0 || value.status === null || typeof value.status === "number");
1730
+ }
1731
+ function isAuthSessionPayload(value) {
1732
+ return isRecord(value) && value.v === 1 && isStoredTokenRef(value.tokenRef);
1733
+ }
1734
+ async function writeAuthSessionTransitionJournalIfOwned(expected, next) {
1735
+ if (!hasSameAuthSessionTransitionIdentity(expected, next)) throw new Error("auth session transition identity cannot change");
1736
+ const current = await readAuthSessionTransitionJournal();
1737
+ if (!current) throw new AuthSessionTransitionConflictError({
1738
+ previousOwnerRestored: false,
1739
+ reason: "journal_missing"
1740
+ });
1741
+ if (!hasSameAuthSessionTransitionIdentity(expected, current)) throw new AuthSessionTransitionConflictError({
1742
+ previousOwnerRestored: false,
1743
+ reason: "journal_replaced"
1744
+ });
1745
+ await writeJsonAtomically(authSessionTransitionPath(), next);
1746
+ }
1747
+ async function claimAuthSessionTransitionJournal(journal) {
1748
+ const path = authSessionTransitionPath();
1749
+ const claimPath = `${path}.claim-${process.pid}-${Date.now()}-${randomUUID()}`;
1750
+ const file = await open(claimPath, "wx", 384);
1751
+ let failure;
1752
+ try {
1753
+ await file.writeFile(`${JSON.stringify(journal, null, 2)}\n`, "utf8");
1754
+ await file.sync();
1755
+ } catch (error) {
1756
+ failure = error;
1757
+ }
1758
+ try {
1759
+ await file.close();
1760
+ } catch (error) {
1761
+ failure ??= error;
1762
+ }
1763
+ if (failure !== void 0) {
1764
+ await rm(claimPath, { force: true }).catch(() => void 0);
1765
+ throw failure;
1766
+ }
1767
+ try {
1768
+ await link(claimPath, path);
1769
+ } catch (error) {
1770
+ if (isFileNotFoundErrorCode(error, "EEXIST")) throw new AuthSessionRecoveryInProgressError();
1771
+ throw error;
1772
+ } finally {
1773
+ await rm(claimPath, { force: true }).catch(() => void 0);
1774
+ }
1775
+ }
1776
+ async function removeAuthSessionTransitionJournalIfOwned(expected) {
1777
+ const currentJournal = await readAuthSessionTransitionJournal();
1778
+ if (!currentJournal) return;
1779
+ if (!hasSameAuthSessionTransitionIdentity(expected, currentJournal)) throw new AuthSessionTransitionConflictError({
1780
+ previousOwnerRestored: false,
1781
+ reason: "journal_replaced"
1782
+ });
1783
+ await rm(authSessionTransitionPath(), { force: true });
1784
+ }
1785
+ function hasSameAuthSessionTransitionIdentity(left, right) {
1786
+ return left.id === right.id && left.ownerPid === right.ownerPid && left.ownerProcessStartedAt === right.ownerProcessStartedAt;
1787
+ }
1788
+ function authSessionTransitionPath() {
1789
+ return join(openMeldRootDir(), "auth", "session-transition.json");
1790
+ }
1791
+ function authSessionPath() {
1792
+ return join(openMeldRootDir(), "auth", "session.json");
1793
+ }
1794
+ async function ensureAuthSessionDirectory() {
1795
+ await mkdir(join(openMeldRootDir(), "auth"), { recursive: true });
1796
+ }
1797
+ async function writeSessionPayloadAtomically(path, payload) {
1798
+ await writeJsonAtomically(path, payload);
1799
+ }
1800
+ async function writeJsonAtomically(path, payload) {
1801
+ const tempPath = `${path}.tmp-${process.pid}-${Date.now()}-${randomUUID()}`;
1802
+ try {
1803
+ const file = await open(tempPath, "wx", 384);
1804
+ try {
1805
+ await file.writeFile(`${JSON.stringify(payload, null, 2)}\n`, "utf8");
1806
+ await file.sync();
1807
+ } finally {
1808
+ await file.close();
1809
+ }
1810
+ await rename(tempPath, path);
1811
+ } catch (error) {
1812
+ await rm(tempPath, { force: true }).catch(() => void 0);
1813
+ throw error;
1814
+ }
1815
+ }
1816
+ function isFileNotFoundError(error) {
1817
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
1818
+ }
1819
+ function isFileNotFoundErrorCode(error, code) {
1820
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === code);
1821
+ }
1822
+ function toErrorMessage(error) {
1823
+ return error instanceof Error && error.message.trim() ? error.message.trim() : String(error ?? "unknown error");
1824
+ }
1825
+ function buildAuthUserPayload(value) {
1826
+ if (!(value && typeof value === "object")) return {};
1827
+ const record = value;
1828
+ const id = normalizeOptionalString(record.id);
1829
+ const email = normalizeOptionalString(record.email);
1830
+ const name = normalizeOptionalString(record.name);
1831
+ if (!(id || email || name)) return {};
1832
+ return { user: {
1833
+ ...id ? { id } : {},
1834
+ ...email ? { email } : {},
1835
+ ...name ? { name } : {}
1836
+ } };
1837
+ }
1838
+ function buildActiveOrganizationPayload(value) {
1839
+ const activeOrganization = normalizeStoredActiveOrganization(value);
1840
+ return activeOrganization ? { activeOrganization } : {};
1841
+ }
1842
+ function normalizeStoredActiveOrganization(value) {
1843
+ if (!isRecord(value)) return null;
1844
+ const id = normalizeOptionalString(value.id);
1845
+ const slug = normalizeOptionalString(value.slug);
1846
+ const name = normalizeOptionalString(value.name);
1847
+ const role = normalizeOptionalString(value.role);
1848
+ const personal = readOrganizationIsPersonal(value);
1849
+ if (!(id && slug && name)) return null;
1850
+ return {
1851
+ id,
1852
+ slug,
1853
+ name,
1854
+ ...role ? { role } : {},
1855
+ ...personal ? { personal } : {}
1856
+ };
1857
+ }
1858
+ function normalizeTokenType(value) {
1859
+ const normalized = value.trim();
1860
+ return normalized.length > 0 ? normalized : "Bearer";
1861
+ }
1862
+ function normalizeOptionalString(value) {
1863
+ const normalized = String(value ?? "").trim();
1864
+ return normalized.length > 0 ? normalized : null;
1865
+ }
1866
+ function readOrganizationIsPersonal(value) {
1867
+ if (value.personal === true || value.isPersonal === true) return true;
1868
+ return readOrganizationMetadata(value.metadata)?.personal === true;
1869
+ }
1870
+ function readOrganizationMetadata(metadata) {
1871
+ if (metadata === null || metadata === void 0) return null;
1872
+ if (typeof metadata === "string") try {
1873
+ const parsed = JSON.parse(metadata);
1874
+ return isRecord(parsed) ? parsed : null;
1875
+ } catch {
1876
+ return null;
1877
+ }
1878
+ return isRecord(metadata) ? metadata : null;
1879
+ }
1880
+ function toAuthEndpoint(baseUrl, pathname) {
1881
+ const url = new URL(baseUrl);
1882
+ url.pathname = `${url.pathname.replace(TRAILING_SLASHES_RE, "")}${pathname.startsWith("/") ? pathname : `/${pathname}`}` || "/";
1883
+ url.search = "";
1884
+ url.hash = "";
1885
+ return url.toString();
1886
+ }
1887
+ function isRecord(value) {
1888
+ return Boolean(value && typeof value === "object");
1889
+ }
1890
+ async function parseResponseJson(response) {
1891
+ const raw = await response.text();
1892
+ if (!raw) return null;
1893
+ try {
1894
+ return JSON.parse(raw);
1895
+ } catch {
1896
+ return { message: raw };
1897
+ }
1898
+ }
1899
+ async function removeSessionFile() {
1900
+ await rm(authSessionPath(), { force: true });
1901
+ }
1902
+ //#endregion
1903
+ export { MAX_HEARTBEAT_INTERVAL_MS as A, RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_RETRY_INTERVAL_MS as B, DAEMON_STREAM_CONNECT_TIMEOUT_MS as C, DEFAULT_HEARTBEAT_INTERVAL_MS as D, DEFAULT_GATEWAY_CHAIN_TIMEOUT_MS as E, PROVIDER_CONVERSATION_PROOF_SYNC_INTERVAL_MS as F, PROVIDER_CONVERSATION_PROOF_SYNC_RETRY_INTERVAL_MS as I, REGISTER_RESPONSE_TIMEOUT_MS as L, MIN_HEARTBEAT_INTERVAL_MS as M, MIN_SPACE_REQUEST_TIMEOUT_MS as N, DEFAULT_SPACE_REQUEST_TIMEOUT_MS as O, OPENCLAW_CLI_TIMEOUT_MS as P, ROUTE_CATALOG_LOAD_TIMEOUT_MS as R, DAEMON_RUNTIME_CONTRACT_EPOCH as S, DAEMON_STREAM_KEEPALIVE_PONG_TIMEOUT_MS as T, RUNTIME_STATE_PERSIST_MIN_INTERVAL_MS as V, isBinaryDistribution as _, clearAuthSession as a, CATALOG_SYNC_RETRY_INTERVAL_MS as b, getAuthSessionState as c, markInterruptedComputerAuthSessionRecovery as d, normalizeStoredActiveOrganization as f, runMacOsNativeKeychainHelperIfRequested as g, updateAuthSessionActiveOrganization as h, beginAuthSessionTransition as i, MAX_SPACE_REQUEST_TIMEOUT_MS as j, HEARTBEAT_RESPONSE_TIMEOUT_MS as k, getCurrentAuthOwnerUserId as l, setAuthSession as m, assertAuthSessionMutationAvailable as n, completeInterruptedComputerAuthSessionRecovery as o, recordInterruptedComputerAuthSessionRecoveryFailure as p, auth_session_exports as r, getAuthSessionMetadata as s, AuthSessionRecoveryInProgressError as t, getInterruptedComputerAuthSessionRecovery as u, resolveOpenMeldDistribution as v, DAEMON_STREAM_KEEPALIVE_INTERVAL_MS as w, CATALOG_SYNC_SIGNAL_POLL_INTERVAL_MS as x, resolveAuthSessionExpiryEligibility as y, RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_INTERVAL_MS as z };
1904
+
1905
+ //# sourceMappingURL=auth-session-B1jSy0ws.js.map