openmeld 0.3.205 → 0.3.206

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 (53) hide show
  1. package/dist/{add-me-membership-jhCNTfdl.js → add-me-membership-BkHWMxE4.js} +2 -2
  2. package/dist/{add-me-membership-jhCNTfdl.js.map → add-me-membership-BkHWMxE4.js.map} +1 -1
  3. package/dist/{agents-9krfNX_L.js → agents-BOTlKiwS.js} +901 -499
  4. package/dist/agents-BOTlKiwS.js.map +1 -0
  5. package/dist/{api-client-foundation-BguumKMv.js → api-client-foundation-6ms5gSu8.js} +1 -1
  6. package/dist/{api-client-foundation-BMPOo4bG.js → api-client-foundation-DpgDs0rw.js} +17 -7
  7. package/dist/api-client-foundation-DpgDs0rw.js.map +1 -0
  8. package/dist/{auth-session-wmefguut.js → auth-session-BjSqMLTz.js} +187 -56
  9. package/dist/auth-session-BjSqMLTz.js.map +1 -0
  10. package/dist/auth-session-ahQ5VXiF.js +4 -0
  11. package/dist/{base-url-jWXPssF_.js → base-url-9A557X2K.js} +2 -2
  12. package/dist/{base-url-jWXPssF_.js.map → base-url-9A557X2K.js.map} +1 -1
  13. package/dist/{base-url-C89TOpPV.js → base-url-CRAYNW-4.js} +1 -1
  14. package/dist/{command-DKM3wO3V.js → command-CkbzbvXy.js} +10 -10
  15. package/dist/{command-DKM3wO3V.js.map → command-CkbzbvXy.js.map} +1 -1
  16. package/dist/{computer-setup-continuation-Dad0lLP9.js → computer-setup-continuation-Cd9nhLQ-.js} +4 -4
  17. package/dist/{computer-setup-continuation-Dad0lLP9.js.map → computer-setup-continuation-Cd9nhLQ-.js.map} +1 -1
  18. package/dist/dist-0boZRalP.js +4 -0
  19. package/dist/{dist-CkixulB-.js → dist-CxadJClH.js} +3692 -3557
  20. package/dist/dist-CxadJClH.js.map +1 -0
  21. package/dist/{elapsed-time-CjAPqg-B.js → elapsed-time-C7P-nWIO.js} +3 -3
  22. package/dist/{elapsed-time-CjAPqg-B.js.map → elapsed-time-C7P-nWIO.js.map} +1 -1
  23. package/dist/{installer-CZyyvNZr.js → installation-inventory-P49sTjhe.js} +359 -359
  24. package/dist/installation-inventory-P49sTjhe.js.map +1 -0
  25. package/dist/{openmeld-DVThrV4O.js → openmeld-ChOHuaqH.js} +20 -16
  26. package/dist/openmeld-ChOHuaqH.js.map +1 -0
  27. package/dist/openmeld-dev.js +1 -1
  28. package/dist/{openmeld-maintenance-worker-Cxp6fwB5.js → openmeld-maintenance-worker-C7WykyDt.js} +5 -5
  29. package/dist/{openmeld-maintenance-worker-Cxp6fwB5.js.map → openmeld-maintenance-worker-C7WykyDt.js.map} +1 -1
  30. package/dist/{openmeld-tools-update-coordinator-DJ65uI3O.js → openmeld-tools-update-coordinator-BBZhGo1A.js} +12 -12
  31. package/dist/{openmeld-tools-update-coordinator-DJ65uI3O.js.map → openmeld-tools-update-coordinator-BBZhGo1A.js.map} +1 -1
  32. package/dist/openmeld.js +3 -3
  33. package/dist/{prepare-session-executor-aE1YARgn.js → prepare-session-executor-CLmDoHom.js} +9 -9
  34. package/dist/{prepare-session-executor-aE1YARgn.js.map → prepare-session-executor-CLmDoHom.js.map} +1 -1
  35. package/dist/{profiles-Dx3gaXgQ.js → profiles-BCecj4Pj.js} +397 -397
  36. package/dist/profiles-BCecj4Pj.js.map +1 -0
  37. package/dist/upgrade-BKEAZKre.js +4 -0
  38. package/dist/{upgrade-Bk8t5oav.js → upgrade-l_5Tge_z.js} +4 -4
  39. package/dist/{upgrade-Bk8t5oav.js.map → upgrade-l_5Tge_z.js.map} +1 -1
  40. package/dist/{urls-4D7CaXe3.js → urls-CY2uzH2-.js} +2 -1
  41. package/dist/urls-CY2uzH2-.js.map +1 -0
  42. package/package.json +1 -1
  43. package/dist/agents-9krfNX_L.js.map +0 -1
  44. package/dist/api-client-foundation-BMPOo4bG.js.map +0 -1
  45. package/dist/auth-session-CpPqG8Xz.js +0 -4
  46. package/dist/auth-session-wmefguut.js.map +0 -1
  47. package/dist/dist-BFbC-9BX.js +0 -4
  48. package/dist/dist-CkixulB-.js.map +0 -1
  49. package/dist/installer-CZyyvNZr.js.map +0 -1
  50. package/dist/openmeld-DVThrV4O.js.map +0 -1
  51. package/dist/profiles-Dx3gaXgQ.js.map +0 -1
  52. package/dist/upgrade-BFGKy5He.js +0 -4
  53. package/dist/urls-4D7CaXe3.js.map +0 -1
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { t as createCliApiClientFoundation } from "./api-client-foundation-BMPOo4bG.js";
3
+ import { t as createCliApiClientFoundation } from "./api-client-foundation-DpgDs0rw.js";
4
4
  export { createCliApiClientFoundation };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { t as normalizeBaseUrl } from "./urls-4D7CaXe3.js";
3
+ import { t as normalizeBaseUrl } from "./urls-CY2uzH2-.js";
4
4
  import { t as isLoopbackHostname } from "./loopback-hostname-DHQPKq8N.js";
5
- import { Gt as createOpenMeldApiClient, In as buildOpenMeldRequestContextHeaders, Nn as OPENMELD_HEADER_REQUESTED_ORGANIZATION_ID } from "./dist-CkixulB-.js";
6
- import { I as MIN_SPACE_REQUEST_TIMEOUT_MS, P as MAX_SPACE_REQUEST_TIMEOUT_MS, S as resolveAuthSessionExpiryEligibility, j as DEFAULT_SPACE_REQUEST_TIMEOUT_MS, l as getAuthSessionState } from "./auth-session-wmefguut.js";
7
- import crypto from "node:crypto";
5
+ import { Gt as createOpenMeldApiClient, Ln as buildOpenMeldRequestContextHeaders, Pn as OPENMELD_HEADER_REQUESTED_ORGANIZATION_ID } from "./dist-CxadJClH.js";
6
+ import { I as MAX_SPACE_REQUEST_TIMEOUT_MS, N as DEFAULT_SPACE_REQUEST_TIMEOUT_MS, R as MIN_SPACE_REQUEST_TIMEOUT_MS, l as getAuthSessionState, w as resolveAuthSessionExpiryEligibility } from "./auth-session-BjSqMLTz.js";
7
+ import crypto, { createHash } from "node:crypto";
8
8
  //#region src/config/auth-request-compatibility.ts
9
9
  function resolveAuthRequestCompatibility(input) {
10
10
  const requestUrl = parseUrlOrNull(input.requestUrl);
@@ -145,7 +145,11 @@ function normalizeOptionalText(value) {
145
145
  //#region src/config/request-headers.ts
146
146
  const DEFAULT_TOKEN_TYPE = "Bearer";
147
147
  const AUTHORIZATION_HEADER = "Authorization";
148
+ function fingerprintRequestAuthorization(authorization) {
149
+ return createHash("sha256").update(authorization).digest("hex");
150
+ }
148
151
  var AuthRequestCredentialError = class extends Error {
152
+ retryAfterMs;
149
153
  authHost;
150
154
  expectedGatewayHost;
151
155
  reason;
@@ -159,6 +163,7 @@ var AuthRequestCredentialError = class extends Error {
159
163
  this.reason = input.reason;
160
164
  this.requestHost = input.requestHost;
161
165
  this.droppedAttachment = input.droppedAttachment;
166
+ this.retryAfterMs = input.retryAfterMs;
162
167
  }
163
168
  };
164
169
  async function buildRequestAuthHeaders(input) {
@@ -231,6 +236,7 @@ function requireAuthTokenAttachment(input) {
231
236
  }
232
237
  async function attachAuthHeader(headers, input) {
233
238
  const session = await resolveAuthSessionForHeaders(input);
239
+ if (input.expectedOwnerUserId && session?.user?.id !== input.expectedOwnerUserId) throw new Error("auth.session_owner_changed");
234
240
  if (session === null) return;
235
241
  let attachment;
236
242
  try {
@@ -258,6 +264,7 @@ async function resolveAuthSessionForHeaders(input) {
258
264
  if (sessionState.state === "missing") return null;
259
265
  if (sessionState.state !== "valid" || sessionState.session === null) {
260
266
  const error = new AuthRequestCredentialError({
267
+ retryAfterMs: sessionState.retryAfterMs,
261
268
  authHost: null,
262
269
  expectedGatewayHost: null,
263
270
  reason: sessionState.reasonCode ?? (sessionState.state === "revoked" ? "session_revoked" : "session_invalid"),
@@ -428,7 +435,10 @@ function createCliApiClientFoundation(baseUrl, options = {}) {
428
435
  timeoutMs: request.timeoutMs
429
436
  }),
430
437
  getAuthHeaders: async ({ requestUrl }) => {
431
- const headers = await buildRequestAuthHeaders({ requestUrl });
438
+ const headers = await buildRequestAuthHeaders({
439
+ requestUrl,
440
+ expectedOwnerUserId: options.expectedOwnerUserId
441
+ });
432
442
  if (options.organizationId) headers[OPENMELD_HEADER_REQUESTED_ORGANIZATION_ID] = options.organizationId;
433
443
  options.onAuthHeadersResolved?.(headers);
434
444
  return headers;
@@ -440,6 +450,6 @@ function createCliApiClientFoundation(baseUrl, options = {}) {
440
450
  });
441
451
  }
442
452
  //#endregion
443
- export { buildOpenMeldProfileIdentityRequestHeadersWithAuth as a, buildRequestAuthHeaders as c, buildOpenMeldRequestContextFromProfileIdentity as d, deriveAuthBaseUrlFromGatewayUrl as f, AuthRequestCredentialError as i, canAttachAuthTokenToRequest as l, fetchSpaceRequestWithTimeout as n, buildOpenMeldProfileRequestHeadersWithAuth as o, resolveAuthRequestCompatibility as p, resolveSpaceRequestTimeoutMsForDiagnostics as r, buildOpenMeldRequestContextHeadersWithAuth as s, createCliApiClientFoundation as t, buildOpenMeldRequestContextFromProfile as u };
453
+ export { buildOpenMeldProfileIdentityRequestHeadersWithAuth as a, buildRequestAuthHeaders as c, buildOpenMeldRequestContextFromProfile as d, buildOpenMeldRequestContextFromProfileIdentity as f, AuthRequestCredentialError as i, canAttachAuthTokenToRequest as l, resolveAuthRequestCompatibility as m, fetchSpaceRequestWithTimeout as n, buildOpenMeldProfileRequestHeadersWithAuth as o, deriveAuthBaseUrlFromGatewayUrl as p, resolveSpaceRequestTimeoutMsForDiagnostics as r, buildOpenMeldRequestContextHeadersWithAuth as s, createCliApiClientFoundation as t, fingerprintRequestAuthorization as u };
444
454
 
445
- //# sourceMappingURL=api-client-foundation-BMPOo4bG.js.map
455
+ //# sourceMappingURL=api-client-foundation-DpgDs0rw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client-foundation-DpgDs0rw.js","names":["resolveSpaceRequestTimeoutMsForDiagnostics","resolveSpaceRequestTimeoutMsForCliDiagnostics"],"sources":["../src/config/auth-request-compatibility.ts","../src/config/openmeld-request-context.ts","../src/config/request-headers.ts","../src/space/request-timeout.ts","../src/space/fetch-with-timeout.ts","../src/space/api-client-foundation.ts"],"sourcesContent":["import { normalizeBaseUrl } from \"../protocol/urls\";\nimport type { StoredAuthSession } from \"./auth-session\";\nimport { isLoopbackHostname } from \"./loopback-hostname\";\n\nexport type AuthRequestCompatibilityReason =\n | \"invalid_request_url\"\n | \"invalid_auth_url\"\n | \"insecure_transport\"\n | \"host_mismatch\"\n | \"loopback\"\n | \"same_host\"\n | \"gateway_sibling\";\n\nexport type AuthRequestCompatibility = {\n compatible: boolean;\n reason: AuthRequestCompatibilityReason;\n requestHost: string | null;\n authHost: string | null;\n expectedGatewayHost: string | null;\n};\n\nexport function resolveAuthRequestCompatibility(input: {\n session: StoredAuthSession;\n requestUrl: string;\n}): AuthRequestCompatibility {\n const requestUrl = parseUrlOrNull(input.requestUrl);\n if (!requestUrl) {\n return {\n compatible: false,\n reason: \"invalid_request_url\",\n requestHost: null,\n authHost: null,\n expectedGatewayHost: null,\n };\n }\n\n const authBaseUrl = parseUrlOrNull(input.session.authBaseUrl);\n if (!authBaseUrl) {\n return {\n compatible: false,\n reason: \"invalid_auth_url\",\n requestHost: requestUrl.host,\n authHost: null,\n expectedGatewayHost: null,\n };\n }\n\n const expectedGatewayHost = deriveGatewayHost(authBaseUrl);\n const requestHost = requestUrl.host;\n const authHost = authBaseUrl.host;\n\n if (\n (isLoopbackHostname(requestUrl.hostname) &&\n isLoopbackHostname(authBaseUrl.hostname)) ||\n // Isolated worktrees share a hostname across Auth and Gateway ports.\n // Never treat different named localhost lanes as interchangeable.\n (requestUrl.hostname.endsWith(\".localhost\") &&\n requestUrl.hostname === authBaseUrl.hostname &&\n isHttpTransportProtocol(authBaseUrl.protocol) &&\n [\"http:\", \"https:\", \"ws:\", \"wss:\"].includes(requestUrl.protocol))\n ) {\n return {\n compatible: true,\n reason: \"loopback\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n if (!isSecureTransportProtocol(requestUrl.protocol)) {\n return {\n compatible: false,\n reason: \"insecure_transport\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n if (requestHost === authHost) {\n return {\n compatible: true,\n reason: \"same_host\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n if (expectedGatewayHost && requestHost === expectedGatewayHost) {\n return {\n compatible: true,\n reason: \"gateway_sibling\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n return {\n compatible: false,\n reason: \"host_mismatch\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n}\n\nexport function deriveAuthBaseUrlFromGatewayUrl(\n gatewayUrl: string\n): string | null {\n const parsed = parseUrlOrNull(gatewayUrl);\n if (!parsed) {\n return null;\n }\n if (!isHttpTransportProtocol(parsed.protocol)) {\n return null;\n }\n if (!parsed.hostname.startsWith(\"gateway.\")) {\n return null;\n }\n\n const authUrl = new URL(parsed.toString());\n authUrl.hostname = `auth.${parsed.hostname.slice(\"gateway.\".length)}`;\n authUrl.pathname = \"/\";\n authUrl.search = \"\";\n authUrl.hash = \"\";\n return normalizeBaseUrl(authUrl.toString());\n}\n\nfunction deriveGatewayHost(authBaseUrl: URL): string | null {\n if (!authBaseUrl.hostname.startsWith(\"auth.\")) {\n return null;\n }\n\n const gatewayUrl = new URL(authBaseUrl.toString());\n gatewayUrl.hostname = `gateway.${authBaseUrl.hostname.slice(\"auth.\".length)}`;\n return gatewayUrl.host;\n}\n\nfunction parseUrlOrNull(value: string): URL | null {\n try {\n return new URL(value);\n } catch {\n return null;\n }\n}\n\nfunction isSecureTransportProtocol(protocol: string): boolean {\n return protocol === \"https:\" || protocol === \"wss:\";\n}\n\nfunction isHttpTransportProtocol(protocol: string): boolean {\n return protocol === \"http:\" || protocol === \"https:\";\n}\n","import crypto from \"node:crypto\";\nimport type { OpenMeldRequestContext } from \"@openmeld/schemas/types\";\nimport type { OpenMeldProfile } from \"./openmeld-profiles-api\";\n\nexport type OpenMeldRequestContextProfileIdentity = {\n openMeldProfileId: string;\n profileKind?: \"human\" | \"agent\" | \"system\";\n kind?: \"human\" | \"agent\";\n profileHandle?: string;\n profileName: string;\n ownerUserId?: string;\n ownerName?: string;\n agentControllerConversationId?: string;\n};\n\nexport function buildOpenMeldRequestContextFromProfile(input: {\n openMeldProfile: OpenMeldProfile;\n requestId?: string;\n agentControllerConversationId?: string;\n}): OpenMeldRequestContext {\n const requestId =\n normalizeOptionalText(input.requestId) ?? crypto.randomUUID();\n const agentControllerConversationId = normalizeOptionalText(\n input.agentControllerConversationId\n );\n const ownerName = normalizeOptionalText(input.openMeldProfile.ownerName);\n\n return {\n actorContext: {\n requestId,\n openMeldProfileId: input.openMeldProfile.openMeldProfileId,\n profileKind: input.openMeldProfile.profileKind,\n profileHandle: input.openMeldProfile.profileHandle,\n profileName: input.openMeldProfile.profileName,\n ownerUserId: input.openMeldProfile.ownerUserId,\n ...(ownerName ? { ownerName } : {}),\n },\n ...(agentControllerConversationId ? { agentControllerConversationId } : {}),\n };\n}\n\nexport function buildOpenMeldRequestContextFromProfileIdentity(input: {\n profileIdentity: OpenMeldRequestContextProfileIdentity;\n requestId?: string;\n}): OpenMeldRequestContext {\n const requestId =\n normalizeOptionalText(input.requestId) ?? crypto.randomUUID();\n const profileHandle = normalizeOptionalText(\n input.profileIdentity.profileHandle\n );\n const ownerUserId = normalizeOptionalText(input.profileIdentity.ownerUserId);\n const ownerName = normalizeOptionalText(input.profileIdentity.ownerName);\n const agentControllerConversationId = normalizeOptionalText(\n input.profileIdentity.agentControllerConversationId\n );\n const profileKind =\n input.profileIdentity.profileKind ??\n (input.profileIdentity.kind === \"human\" ||\n input.profileIdentity.kind === \"agent\"\n ? input.profileIdentity.kind\n : \"system\");\n\n return {\n actorContext: {\n requestId,\n openMeldProfileId: input.profileIdentity.openMeldProfileId,\n profileKind,\n ...(profileHandle ? { profileHandle } : {}),\n profileName: input.profileIdentity.profileName,\n ...(ownerUserId ? { ownerUserId } : {}),\n ...(ownerName ? { ownerName } : {}),\n },\n ...(agentControllerConversationId ? { agentControllerConversationId } : {}),\n };\n}\n\nfunction normalizeOptionalText(value: unknown): string | null {\n const normalized = String(value ?? \"\").trim();\n return normalized.length > 0 ? normalized : null;\n}\n","import { createHash } from \"node:crypto\";\nimport {\n buildOpenMeldRequestContextHeaders,\n type OpenMeldRequestContextHeadersInput,\n} from \"@openmeld/gateway-contract\";\nimport type { OpenMeldRequestContext } from \"@openmeld/schemas/types\";\nimport {\n type AuthRequestCompatibilityReason,\n resolveAuthRequestCompatibility,\n} from \"./auth-request-compatibility\";\nimport {\n type AuthSessionStateReasonCode,\n getAuthSessionState,\n type StoredAuthSession,\n} from \"./auth-session\";\nimport { resolveAuthSessionExpiryEligibility } from \"./auth-session-expiry\";\nimport type { OpenMeldProfile } from \"./openmeld-profiles-api\";\nimport {\n buildOpenMeldRequestContextFromProfile,\n buildOpenMeldRequestContextFromProfileIdentity,\n type OpenMeldRequestContextProfileIdentity,\n} from \"./openmeld-request-context\";\n\nconst DEFAULT_TOKEN_TYPE = \"Bearer\";\nconst AUTHORIZATION_HEADER = \"Authorization\";\n\n// Ephemeral correlation for the exact credential attached to a request/socket.\n// Never include this fingerprint in persisted or uploaded diagnostics.\nexport function fingerprintRequestAuthorization(authorization: string): string {\n return createHash(\"sha256\").update(authorization).digest(\"hex\");\n}\n\ntype RequestAuthHeadersInput = {\n authSession?: StoredAuthSession | null;\n expectedOwnerUserId?: string;\n requestUrl: string;\n};\n\ntype OpenMeldRequestContextHeadersWithAuthInput =\n OpenMeldRequestContextHeadersInput & {\n authSession?: StoredAuthSession | null;\n requestUrl: string;\n };\n\nexport type AuthTokenAttachment =\n | {\n status: \"attachable\";\n token: string;\n tokenType: string;\n }\n | {\n status: \"dropped\";\n reason:\n | \"empty_token\"\n | \"session_expired\"\n | \"session_expiry_invalid\"\n | AuthRequestCompatibilityReason;\n requestHost: string | null;\n authHost: string | null;\n expectedGatewayHost: string | null;\n };\n\nexport type DroppedAuthTokenAttachment = Extract<\n AuthTokenAttachment,\n { status: \"dropped\" }\n>;\n\nexport type AuthRequestCredentialFailureReason =\n | DroppedAuthTokenAttachment[\"reason\"]\n | AuthSessionStateReasonCode\n | \"session_invalid\"\n | \"session_revoked\";\n\nexport class AuthRequestCredentialError extends Error {\n readonly retryAfterMs?: number;\n readonly authHost: string | null;\n readonly expectedGatewayHost: string | null;\n readonly reason: AuthRequestCredentialFailureReason;\n readonly requestHost: string | null;\n readonly droppedAttachment?: DroppedAuthTokenAttachment;\n\n constructor(input: {\n retryAfterMs?: number;\n authHost: string | null;\n expectedGatewayHost: string | null;\n reason: AuthRequestCredentialFailureReason;\n requestHost: string | null;\n droppedAttachment?: DroppedAuthTokenAttachment;\n }) {\n super(\n `OpenMeld refused to send a request with unusable stored credentials (${input.reason}).`\n );\n this.name = \"AuthRequestCredentialError\";\n this.authHost = input.authHost;\n this.expectedGatewayHost = input.expectedGatewayHost;\n this.reason = input.reason;\n this.requestHost = input.requestHost;\n this.droppedAttachment = input.droppedAttachment;\n this.retryAfterMs = input.retryAfterMs;\n }\n}\n\nexport async function buildRequestAuthHeaders(\n input: RequestAuthHeadersInput\n): Promise<Record<string, string>> {\n const headers: Record<string, string> = {};\n await attachAuthHeader(headers, input);\n return headers;\n}\n\nexport async function buildOpenMeldRequestContextHeadersWithAuth(\n input: OpenMeldRequestContextHeadersWithAuthInput\n): Promise<Record<string, string>> {\n const headers = buildOpenMeldRequestContextHeaders(input);\n await attachAuthHeader(headers, input);\n return headers;\n}\n\nexport async function buildOpenMeldProfileRequestHeadersWithAuth(input: {\n openMeldProfile: OpenMeldProfile;\n requestUrl: string;\n authSession?: StoredAuthSession | null;\n agentControllerConversationId?: string;\n spacePassword?: string;\n}): Promise<Record<string, string>> {\n return await buildOpenMeldRequestContextHeadersWithAuth({\n requestContext: buildOpenMeldRequestContextFromProfile({\n openMeldProfile: input.openMeldProfile,\n agentControllerConversationId: input.agentControllerConversationId,\n }),\n requestUrl: input.requestUrl,\n ...(input.authSession === undefined\n ? {}\n : { authSession: input.authSession }),\n ...(input.spacePassword === undefined\n ? {}\n : { spacePassword: input.spacePassword }),\n });\n}\n\nexport async function buildOpenMeldProfileIdentityRequestHeadersWithAuth(input: {\n profileIdentity: OpenMeldRequestContextProfileIdentity;\n requestUrl: string;\n authSession?: StoredAuthSession | null;\n spacePassword?: string;\n}): Promise<Record<string, string>> {\n return await buildOpenMeldRequestContextHeadersWithAuth({\n requestContext: buildOpenMeldRequestContextFromProfileIdentity({\n profileIdentity: input.profileIdentity,\n }),\n requestUrl: input.requestUrl,\n ...(input.authSession === undefined\n ? {}\n : { authSession: input.authSession }),\n ...(input.spacePassword === undefined\n ? {}\n : { spacePassword: input.spacePassword }),\n });\n}\n\nexport function withSpacePassword(\n requestContext: OpenMeldRequestContext,\n spacePassword?: string\n): OpenMeldRequestContextHeadersInput {\n return {\n requestContext,\n ...(spacePassword === undefined ? {} : { spacePassword }),\n };\n}\n\n// One decision for \"can this stored session authenticate this request\", with\n// the drop reason preserved. Header building and the daemon stream connect\n// gate must share this so they cannot drift apart.\nexport function resolveAuthTokenAttachment(input: {\n session: StoredAuthSession;\n requestUrl: string;\n}): AuthTokenAttachment {\n const compatibility = resolveAuthRequestCompatibility({\n session: input.session,\n requestUrl: input.requestUrl,\n });\n const token = normalizeAccessToken(input.session);\n if (!token) {\n return {\n status: \"dropped\",\n reason: \"empty_token\",\n requestHost: compatibility.requestHost,\n authHost: compatibility.authHost,\n expectedGatewayHost: compatibility.expectedGatewayHost,\n };\n }\n if (!compatibility.compatible) {\n return {\n status: \"dropped\",\n reason: compatibility.reason,\n requestHost: compatibility.requestHost,\n authHost: compatibility.authHost,\n expectedGatewayHost: compatibility.expectedGatewayHost,\n };\n }\n const expiryReason = resolveSessionExpiryReason(input.session);\n if (expiryReason) {\n return {\n status: \"dropped\",\n reason: expiryReason,\n requestHost: compatibility.requestHost,\n authHost: compatibility.authHost,\n expectedGatewayHost: compatibility.expectedGatewayHost,\n };\n }\n return {\n status: \"attachable\",\n token,\n tokenType: normalizeTokenType(input.session.tokenType),\n };\n}\n\nexport function requireAuthTokenAttachment(input: {\n session: StoredAuthSession;\n requestUrl: string;\n}): Extract<AuthTokenAttachment, { status: \"attachable\" }> {\n const attachment = resolveAuthTokenAttachment(input);\n if (attachment.status === \"dropped\") {\n throw createAuthRequestCredentialError(attachment);\n }\n return attachment;\n}\n\nasync function attachAuthHeader(\n headers: Record<string, string>,\n input: RequestAuthHeadersInput\n): Promise<void> {\n const session = await resolveAuthSessionForHeaders(input);\n if (\n input.expectedOwnerUserId &&\n session?.user?.id !== input.expectedOwnerUserId\n ) {\n throw new Error(\"auth.session_owner_changed\");\n }\n if (session === null) {\n // No stored credentials exist, so there is nothing to strip: the caller\n // is knowingly sending an unauthenticated request.\n return;\n }\n\n let attachment: Extract<AuthTokenAttachment, { status: \"attachable\" }>;\n try {\n attachment = requireAuthTokenAttachment({\n session,\n requestUrl: input.requestUrl,\n });\n } catch (error) {\n if (error instanceof AuthRequestCredentialError) {\n logRejectedAuthRequestCredential(error);\n }\n throw error;\n }\n headers[AUTHORIZATION_HEADER] = `${attachment.tokenType} ${attachment.token}`;\n}\n\nfunction logRejectedAuthRequestCredential(\n error: AuthRequestCredentialError\n): void {\n console.error(\"[openmeld.auth.request_credential_rejected]\", {\n authHost: error.authHost,\n expectedGatewayHost: error.expectedGatewayHost,\n reason: error.reason,\n requestHost: error.requestHost,\n });\n}\n\nasync function resolveAuthSessionForHeaders(\n input: RequestAuthHeadersInput\n): Promise<StoredAuthSession | null> {\n if (input.authSession !== undefined) {\n return input.authSession;\n }\n\n const sessionState = await getAuthSessionState({ refreshExpired: true });\n if (sessionState.state === \"missing\") {\n return null;\n }\n if (sessionState.state !== \"valid\" || sessionState.session === null) {\n const error = new AuthRequestCredentialError({\n retryAfterMs: sessionState.retryAfterMs,\n authHost: null,\n expectedGatewayHost: null,\n reason:\n sessionState.reasonCode ??\n (sessionState.state === \"revoked\"\n ? \"session_revoked\"\n : \"session_invalid\"),\n requestHost: parseRequestHost(input.requestUrl),\n });\n logRejectedAuthRequestCredential(error);\n throw error;\n }\n\n return sessionState.session;\n}\n\nfunction createAuthRequestCredentialError(\n attachment: DroppedAuthTokenAttachment\n): AuthRequestCredentialError {\n return new AuthRequestCredentialError({\n authHost: attachment.authHost,\n expectedGatewayHost: attachment.expectedGatewayHost,\n reason: attachment.reason,\n requestHost: attachment.requestHost,\n droppedAttachment: attachment,\n });\n}\n\nfunction parseRequestHost(requestUrl: string): string | null {\n try {\n return new URL(requestUrl).host || null;\n } catch {\n return null;\n }\n}\n\nfunction normalizeAccessToken(session: StoredAuthSession): string {\n return String(session.accessToken ?? \"\").trim();\n}\n\nfunction normalizeTokenType(tokenType: string | undefined): string {\n const normalized = String(tokenType ?? \"\").trim();\n return normalized.length > 0 ? normalized : DEFAULT_TOKEN_TYPE;\n}\n\nfunction resolveSessionExpiryReason(\n session: StoredAuthSession\n): \"session_expired\" | \"session_expiry_invalid\" | null {\n const eligibility = resolveAuthSessionExpiryEligibility(session.expiresAt);\n if (eligibility.status === \"invalid\") {\n return \"session_expiry_invalid\";\n }\n return eligibility.status === \"expired\" ? \"session_expired\" : null;\n}\n\nexport function canAttachAuthTokenToRequest(\n session: StoredAuthSession,\n requestUrl: string\n): boolean {\n return (\n resolveAuthTokenAttachment({\n session,\n requestUrl,\n }).status === \"attachable\"\n );\n}\n","import {\n DEFAULT_SPACE_CONVERSATION_VALIDATE_TIMEOUT_MS,\n DEFAULT_SPACE_REQUEST_TIMEOUT_MS,\n MAX_SPACE_REQUEST_TIMEOUT_MS,\n MIN_SPACE_REQUEST_TIMEOUT_MS,\n} from \"../strategy-constants\";\n\nconst SPACE_REQUEST_TIMEOUT_ENV_KEY = \"OPENMELD_SPACE_REQUEST_TIMEOUT_MS\";\n\nexport function resolveSpaceRequestTimeoutMs(override?: number): number {\n if (isFinitePositiveNumber(override)) {\n return clampSpaceRequestTimeoutMs(override);\n }\n\n const fromEnv = Number.parseInt(\n String(process.env[SPACE_REQUEST_TIMEOUT_ENV_KEY] ?? \"\"),\n 10\n );\n if (isFinitePositiveNumber(fromEnv)) {\n return clampSpaceRequestTimeoutMs(fromEnv);\n }\n\n return DEFAULT_SPACE_REQUEST_TIMEOUT_MS;\n}\n\nexport function resolveSpaceRequestTimeoutMsForDiagnostics(): number {\n return resolveSpaceRequestTimeoutMs(undefined);\n}\n\nexport function resolveSpaceConversationValidateTimeoutMs(): number {\n return Math.max(\n resolveSpaceRequestTimeoutMs(undefined),\n DEFAULT_SPACE_CONVERSATION_VALIDATE_TIMEOUT_MS\n );\n}\n\nfunction clampSpaceRequestTimeoutMs(value: number): number {\n const normalized = Math.trunc(value);\n return Math.max(\n MIN_SPACE_REQUEST_TIMEOUT_MS,\n Math.min(MAX_SPACE_REQUEST_TIMEOUT_MS, normalized)\n );\n}\n\nfunction isFinitePositiveNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n","import {\n resolveSpaceRequestTimeoutMs,\n resolveSpaceRequestTimeoutMsForDiagnostics as resolveSpaceRequestTimeoutMsForCliDiagnostics,\n} from \"./request-timeout\";\n\nexport async function fetchSpaceRequestWithTimeout(input: {\n url: string;\n operation: string;\n init?: RequestInit;\n timeoutMs?: number;\n}): Promise<Response> {\n const timeoutMs = resolveSpaceRequestTimeoutMs(input.timeoutMs);\n const timeoutSignal = AbortSignal.timeout(timeoutMs);\n const composed = composeAbortSignals(input.init?.signal, timeoutSignal);\n\n try {\n try {\n return await fetch(input.url, {\n ...input.init,\n signal: composed.signal,\n });\n } catch (error) {\n // A keep-alive connection that a proxy silently dropped fails exactly\n // once and undici evicts it; the retry rides a fresh connection. This\n // is what keeps a long-lived service working behind flaky proxies\n // without asking users to touch their network config.\n if (\n timeoutSignal.aborted ||\n composed.signal.aborted ||\n !shouldWrapNetworkRequestError(error)\n ) {\n throw error;\n }\n return await fetch(input.url, {\n ...input.init,\n signal: composed.signal,\n });\n }\n } catch (error) {\n if (timeoutSignal.aborted) {\n throw createSpaceRequestTimeoutError({\n operation: input.operation,\n timeoutMs,\n cause: error,\n });\n }\n if (shouldWrapNetworkRequestError(error)) {\n throw createSpaceRequestNetworkError({\n operation: input.operation,\n url: input.url,\n cause: error,\n });\n }\n throw error;\n } finally {\n composed.cleanup();\n }\n}\n\nexport function resolveSpaceRequestTimeoutMsForDiagnostics(): number {\n return resolveSpaceRequestTimeoutMsForCliDiagnostics();\n}\n\nfunction createSpaceRequestTimeoutError(input: {\n operation: string;\n timeoutMs: number;\n cause: unknown;\n}): Error {\n const error = new Error(\n `${input.operation} request timed out after ${input.timeoutMs}ms`,\n { cause: input.cause }\n ) as Error & { code?: string };\n error.code = \"network.timeout\";\n return error;\n}\n\nfunction createSpaceRequestNetworkError(input: {\n operation: string;\n url: string;\n cause: unknown;\n}): Error {\n const error = new Error(\n `${input.operation} request could not reach ${describeRequestTarget(input.url)} (${toErrorMessage(input.cause)})`,\n { cause: input.cause }\n ) as Error & { code?: string };\n error.code = \"network.request_failed\";\n return error;\n}\n\nfunction composeAbortSignals(\n parent: AbortSignal | null | undefined,\n timeout: AbortSignal\n): { signal: AbortSignal; cleanup: () => void } {\n if (!parent) {\n return {\n signal: timeout,\n cleanup: () => undefined,\n };\n }\n\n if (parent.aborted || timeout.aborted) {\n const controller = new AbortController();\n controller.abort();\n return {\n signal: controller.signal,\n cleanup: () => undefined,\n };\n }\n\n const controller = new AbortController();\n const abort = () => {\n controller.abort();\n };\n\n parent.addEventListener(\"abort\", abort, { once: true });\n timeout.addEventListener(\"abort\", abort, { once: true });\n\n return {\n signal: controller.signal,\n cleanup: () => {\n parent.removeEventListener(\"abort\", abort);\n timeout.removeEventListener(\"abort\", abort);\n },\n };\n}\n\nfunction describeRequestTarget(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return url;\n }\n}\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n const message = error.message.trim();\n return message.length > 0 ? message : \"request failed\";\n }\n const message = String(error ?? \"\").trim();\n return message.length > 0 ? message : \"request failed\";\n}\n\nfunction shouldWrapNetworkRequestError(error: unknown): boolean {\n if (error instanceof TypeError) {\n return true;\n }\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n error.code.startsWith(\"ERR_SSL_\")\n ) {\n return true;\n }\n const message = toErrorMessage(error).toLowerCase();\n return (\n message.includes(\"fetch failed\") ||\n message.includes(\"failed to fetch\") ||\n message.includes(\"network request failed\") ||\n message.includes(\"ssl_decryption_failed_or_bad_record_mac\")\n );\n}\n","import {\n createOpenMeldApiClient,\n type OpenMeldApiClientFoundation,\n} from \"@openmeld/api-client\";\nimport {\n buildOpenMeldRequestContextHeaders,\n OPENMELD_HEADER_REQUESTED_ORGANIZATION_ID,\n} from \"@openmeld/gateway-contract\";\nimport { buildRequestAuthHeaders } from \"../config/request-headers\";\nimport { fetchSpaceRequestWithTimeout } from \"./fetch-with-timeout\";\n\nexport function createCliApiClientFoundation(\n baseUrl: string,\n options: {\n onAuthHeadersResolved?: (headers: Record<string, string>) => void;\n organizationId?: string;\n expectedOwnerUserId?: string;\n } = {}\n): OpenMeldApiClientFoundation {\n return createOpenMeldApiClient({\n baseUrl,\n transport: async (request) =>\n await fetchSpaceRequestWithTimeout({\n url: request.url,\n operation: request.operation,\n init: request.init,\n timeoutMs: request.timeoutMs,\n }),\n getAuthHeaders: async ({ requestUrl }) => {\n const headers = await buildRequestAuthHeaders({\n requestUrl,\n expectedOwnerUserId: options.expectedOwnerUserId,\n });\n if (options.organizationId) {\n headers[OPENMELD_HEADER_REQUESTED_ORGANIZATION_ID] =\n options.organizationId;\n }\n options.onAuthHeadersResolved?.(headers);\n return headers;\n },\n getRequestContextHeaders: async ({ requestContext, spacePassword }) =>\n buildOpenMeldRequestContextHeaders({\n requestContext,\n ...(spacePassword === undefined ? {} : { spacePassword }),\n }),\n });\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { t as isLoopbackHostname } from "./loopback-hostname-DHQPKq8N.js";
4
4
  import { S as isProcessIdentityAlive, r as isOpenMeldLockError, t as acquireLock, tt as openMeldRootDir, u as runWithHeldLock, x as CURRENT_PROCESS_START_IDENTITY } from "./lock-CvBnBcFK.js";
5
- import { $r as int, Dn as START_ISO_DATE_TIME_SCHEMA, En as START_BOUNDED_VERSION_SCHEMA, Jr as boolean, Oi as openMeldProfileIdSchema, Qr as enumFactory, Tn as START_BOUNDED_ID_SCHEMA, Xr as discriminatedUnion, ci as record, d as CURRENT_DAEMON_EXECUTION_CONTRACT_EPOCH, ei as iso, i as authProfileManagedRoleSchema, ii as nullFactory, jn as localAgentCatalogSchema, kn as startReplyReadinessSummarySchema, li as strictObject, mi as unknown, ni as literal, oi as object, pi as union, qr as array, r as authProfileKindSchema, ui as string } from "./profiles-Dx3gaXgQ.js";
5
+ import { $r as int, Jr as boolean, Oi as openMeldProfileIdSchema, Qr as enumFactory, Xr as discriminatedUnion, _ as localAgentCatalogSchema, ci as record, d as START_BOUNDED_ID_SCHEMA, ei as iso, f as START_BOUNDED_VERSION_SCHEMA, h as startReplyReadinessSummarySchema, i as authProfileManagedRoleSchema, ii as nullFactory, li as strictObject, mi as unknown, ni as literal, oi as object, p as START_ISO_DATE_TIME_SCHEMA, pi as union, qr as array, r as authProfileKindSchema, ui as string, y as CURRENT_DAEMON_EXECUTION_CONTRACT_EPOCH } from "./profiles-BCecj4Pj.js";
6
6
  import { r as daemonServiceLaneSchema } from "./service-contract-CRyDcIIf.js";
7
7
  import { createRequire } from "node:module";
8
8
  import { createHash, randomUUID } from "node:crypto";
@@ -816,6 +816,9 @@ let unresponsiveKeychainError = null;
816
816
  let keychainRetryAt = 0;
817
817
  let lastKeychainFailureCode = null;
818
818
  const MAC_OS_KEYCHAIN_RETRY_DELAY_MS = 3e4;
819
+ function getMacOsKeychainRetryAfterMs() {
820
+ return Math.max(0, keychainRetryAt - Date.now());
821
+ }
819
822
  async function storeMacOsNativeKeychainToken(input) {
820
823
  if (isBinaryDistribution()) {
821
824
  await runBoundedMacOsNativeKeychainRequest({
@@ -1172,6 +1175,7 @@ async function readAccessToken(ref) {
1172
1175
  } catch (error) {
1173
1176
  return {
1174
1177
  errorMessage: toErrorMessage$1(error),
1178
+ ...ref.provider === "macos-keychain" ? { retryAfterMs: getMacOsKeychainRetryAfterMs() } : {},
1175
1179
  status: "unavailable"
1176
1180
  };
1177
1181
  }
@@ -1447,13 +1451,50 @@ var AuthSessionTransitionConflictError = class extends Error {
1447
1451
  };
1448
1452
  const TRAILING_SLASHES_RE = /\/+$/u;
1449
1453
  let cachedAuthSession = null;
1454
+ const pendingCredentialReads = /* @__PURE__ */ new Map();
1455
+ const credentialAvailabilityListeners = /* @__PURE__ */ new Set();
1456
+ function onAuthSessionCredentialAvailable(notify) {
1457
+ const listener = {
1458
+ path: authSessionPath(),
1459
+ notify
1460
+ };
1461
+ credentialAvailabilityListeners.add(listener);
1462
+ return () => {
1463
+ credentialAvailabilityListeners.delete(listener);
1464
+ };
1465
+ }
1450
1466
  const activeAuthSessionTransitionIds = /* @__PURE__ */ new Set();
1467
+ const credentialObservationListeners = /* @__PURE__ */ new Set();
1468
+ function onAuthSessionCredentialObservation(notify) {
1469
+ const listener = {
1470
+ path: authSessionPath(),
1471
+ notify
1472
+ };
1473
+ credentialObservationListeners.add(listener);
1474
+ return () => {
1475
+ credentialObservationListeners.delete(listener);
1476
+ };
1477
+ }
1478
+ function observeCredential(reason) {
1479
+ const path = authSessionPath();
1480
+ for (const listener of credentialObservationListeners) if (listener.path === path) try {
1481
+ listener.notify(reason);
1482
+ } catch {}
1483
+ }
1451
1484
  async function getAuthSessionState(options = {}) {
1452
- return await getAuthSessionStateWithCandidateRefreshFence(options, false);
1485
+ const result = await getAuthSessionStateWithCandidateRefreshFence(options, false);
1486
+ if (result.reasonCode === "session_metadata_invalid") observeCredential("metadata_unavailable");
1487
+ return {
1488
+ state: result.state,
1489
+ session: result.session,
1490
+ ...result.reasonCode ? { reasonCode: result.reasonCode } : {},
1491
+ ...result.errorMessage ? { errorMessage: result.errorMessage } : {},
1492
+ ...result.retryAfterMs !== void 0 ? { retryAfterMs: result.retryAfterMs } : {}
1493
+ };
1453
1494
  }
1454
1495
  async function getAuthSessionStateWithCandidateRefreshFence(options, candidateRefreshFenceHeld) {
1455
1496
  const localState = await getLocalAuthSessionState();
1456
- const localPayloadKey = cachedAuthSession?.payloadKey ?? null;
1497
+ const localPayloadKey = "payloadKey" in localState ? localState.payloadKey : null;
1457
1498
  const shouldValidateRemote = options.validateRemote === true || options.refreshExpired === true && localState.state === "expired";
1458
1499
  switch (localState.state) {
1459
1500
  case "missing":
@@ -2124,65 +2165,59 @@ async function getLocalAuthSessionState(options = {}) {
2124
2165
  try {
2125
2166
  payload = options.recover === false ? await readSessionPayloadFile() : await readSessionPayload();
2126
2167
  } catch (error) {
2127
- if (error instanceof AuthSessionStorageError) return {
2128
- errorMessage: error.message,
2129
- reasonCode: "session_metadata_invalid",
2130
- state: "invalid",
2168
+ if (error instanceof AuthSessionStorageError) {
2169
+ cachedAuthSession = null;
2170
+ return {
2171
+ errorMessage: error.message,
2172
+ reasonCode: "session_metadata_invalid",
2173
+ state: "invalid",
2174
+ session: null
2175
+ };
2176
+ }
2177
+ throw error;
2178
+ }
2179
+ if (payload?.v !== 1) {
2180
+ cachedAuthSession = null;
2181
+ return {
2182
+ reasonCode: "session_missing",
2183
+ state: "missing",
2131
2184
  session: null
2132
2185
  };
2133
- throw error;
2134
2186
  }
2135
- if (payload?.v !== 1) return {
2136
- reasonCode: "session_missing",
2137
- state: "missing",
2138
- session: null
2139
- };
2140
2187
  const tokenRef = normalizeTokenRef(payload.tokenRef);
2141
- if (!tokenRef) return {
2142
- reasonCode: "session_token_ref_invalid",
2143
- state: "invalid",
2144
- session: null
2145
- };
2188
+ if (!tokenRef) {
2189
+ cachedAuthSession = null;
2190
+ return {
2191
+ reasonCode: "session_token_ref_invalid",
2192
+ state: "invalid",
2193
+ session: null
2194
+ };
2195
+ }
2146
2196
  const tokenType = normalizeOptionalString(payload.tokenType);
2147
2197
  const authBaseUrl = normalizeOptionalString(payload.authBaseUrl);
2148
2198
  const clientId = normalizeOptionalString(payload.clientId);
2149
2199
  const createdAt = normalizeOptionalString(payload.createdAt);
2150
- if (!(tokenType && authBaseUrl && clientId && createdAt)) return {
2151
- reasonCode: "session_metadata_invalid",
2152
- state: "invalid",
2153
- session: null
2154
- };
2155
- let session = readCachedAuthSession(payload);
2156
- if (!session) {
2157
- const accessToken = await readAccessToken(tokenRef);
2158
- if (accessToken.status === "missing") return {
2159
- reasonCode: "session_token_missing",
2160
- state: "invalid",
2161
- session: null
2162
- };
2163
- if (accessToken.status === "unavailable") return {
2164
- errorMessage: accessToken.errorMessage,
2165
- reasonCode: "session_token_unavailable",
2200
+ if (!(tokenType && authBaseUrl && clientId && createdAt)) {
2201
+ cachedAuthSession = null;
2202
+ return {
2203
+ reasonCode: "session_metadata_invalid",
2166
2204
  state: "invalid",
2167
2205
  session: null
2168
2206
  };
2169
- session = buildStoredAuthSession({
2170
- accessToken: accessToken.accessToken,
2171
- payload: {
2172
- ...payload,
2173
- v: 1,
2174
- tokenRef,
2175
- tokenType,
2176
- authBaseUrl,
2177
- clientId,
2178
- createdAt
2179
- }
2180
- });
2181
- cacheAuthSession({
2182
- payload,
2183
- session
2184
- });
2185
2207
  }
2208
+ const session = readCachedAuthSession(payload);
2209
+ if (!session) return await loadCurrentSessionCredential({
2210
+ ...payload,
2211
+ v: 1,
2212
+ tokenRef,
2213
+ tokenType,
2214
+ authBaseUrl,
2215
+ clientId,
2216
+ createdAt
2217
+ }, options);
2218
+ return resolveLocalStoredSessionState(session, buildAuthSessionPayloadKey(payload));
2219
+ }
2220
+ function resolveLocalStoredSessionState(session, payloadKey) {
2186
2221
  const expiryEligibility = resolveAuthSessionExpiryEligibility(session.expiresAt);
2187
2222
  if (expiryEligibility.status === "invalid") return {
2188
2223
  reasonCode: "session_expiry_invalid",
@@ -2192,13 +2227,68 @@ async function getLocalAuthSessionState(options = {}) {
2192
2227
  if (expiryEligibility.status === "expired") return {
2193
2228
  reasonCode: "session_expired",
2194
2229
  state: "expired",
2230
+ payloadKey,
2195
2231
  session
2196
2232
  };
2197
2233
  return {
2198
2234
  state: "valid",
2235
+ payloadKey,
2199
2236
  session
2200
2237
  };
2201
2238
  }
2239
+ async function loadCurrentSessionCredential(payload, options) {
2240
+ const credentialKey = buildAuthSessionCredentialCacheKey(payload);
2241
+ const accessToken = await readSessionCredential(credentialKey, payload.tokenRef);
2242
+ let currentPayload;
2243
+ try {
2244
+ currentPayload = options.recover === false ? await readSessionPayloadFile() : await readSessionPayload();
2245
+ } catch (error) {
2246
+ if (!(error instanceof AuthSessionStorageError)) throw error;
2247
+ cachedAuthSession = null;
2248
+ return {
2249
+ state: "invalid",
2250
+ session: null,
2251
+ reasonCode: "session_metadata_invalid",
2252
+ errorMessage: error.message
2253
+ };
2254
+ }
2255
+ if (!currentPayload || buildAuthSessionCredentialCacheKey(currentPayload) !== credentialKey) {
2256
+ if ((options.reloadCount ?? 0) >= 2) {
2257
+ cachedAuthSession = null;
2258
+ return {
2259
+ state: "invalid",
2260
+ session: null,
2261
+ reasonCode: "session_metadata_invalid",
2262
+ errorMessage: "The local login changed while reading its credentials. Try again."
2263
+ };
2264
+ }
2265
+ return await getLocalAuthSessionState({
2266
+ ...options,
2267
+ reloadCount: (options.reloadCount ?? 0) + 1
2268
+ });
2269
+ }
2270
+ if (accessToken.status === "missing") return {
2271
+ reasonCode: "session_token_missing",
2272
+ state: "invalid",
2273
+ session: null
2274
+ };
2275
+ if (accessToken.status === "unavailable") return {
2276
+ errorMessage: accessToken.errorMessage,
2277
+ retryAfterMs: accessToken.retryAfterMs,
2278
+ reasonCode: "session_token_unavailable",
2279
+ state: "invalid",
2280
+ session: null
2281
+ };
2282
+ const session = buildStoredAuthSession({
2283
+ accessToken: accessToken.accessToken,
2284
+ payload: currentPayload
2285
+ });
2286
+ cacheAuthSession({
2287
+ payload: currentPayload,
2288
+ session
2289
+ });
2290
+ return resolveLocalStoredSessionState(session, buildAuthSessionPayloadKey(currentPayload));
2291
+ }
2202
2292
  async function assertStoredAccessTokenReloads(input) {
2203
2293
  const reloaded = await readAccessToken(input.tokenRef);
2204
2294
  if (reloaded.status === "found" && reloaded.accessToken === input.accessToken) return;
@@ -2243,14 +2333,55 @@ async function cleanupTransitionTokensNotReferencedByCurrentSession(input) {
2243
2333
  }
2244
2334
  }
2245
2335
  function cacheAuthSession(input) {
2336
+ const credentialKey = buildAuthSessionCredentialCacheKey(input.payload);
2337
+ const becameAvailable = cachedAuthSession?.credentialKey !== credentialKey;
2338
+ const previous = cachedAuthSession;
2246
2339
  cachedAuthSession = {
2247
- payloadKey: buildAuthSessionPayloadKey(input.payload),
2340
+ credentialKey,
2248
2341
  session: input.session
2249
2342
  };
2343
+ if (!previous) observeCredential("credential_available");
2344
+ else if (previous.session.user?.id !== input.session.user?.id) observeCredential("account_changed");
2345
+ else if (becameAvailable) observeCredential("credential_changed");
2346
+ else if (JSON.stringify([previous.session.activeOrganization, previous.session.user]) !== JSON.stringify([input.session.activeOrganization, input.session.user])) observeCredential("context_changed");
2347
+ if (becameAvailable) {
2348
+ const path = authSessionPath();
2349
+ for (const listener of credentialAvailabilityListeners) if (listener.path === path) listener.notify();
2350
+ }
2250
2351
  }
2251
2352
  function readCachedAuthSession(payload) {
2252
- const payloadKey = buildAuthSessionPayloadKey(payload);
2253
- return cachedAuthSession?.payloadKey === payloadKey ? cachedAuthSession.session : null;
2353
+ if (cachedAuthSession?.credentialKey !== buildAuthSessionCredentialCacheKey(payload)) return null;
2354
+ const session = buildStoredAuthSession({
2355
+ accessToken: cachedAuthSession.session.accessToken,
2356
+ payload
2357
+ });
2358
+ cacheAuthSession({
2359
+ payload,
2360
+ session
2361
+ });
2362
+ return session;
2363
+ }
2364
+ function buildAuthSessionCredentialCacheKey(payload) {
2365
+ return `${authSessionPath()}\n${JSON.stringify({
2366
+ v: payload.v,
2367
+ tokenRef: payload.tokenRef,
2368
+ tokenType: payload.tokenType,
2369
+ authBaseUrl: payload.authBaseUrl,
2370
+ clientId: payload.clientId,
2371
+ createdAt: payload.createdAt,
2372
+ expiresAt: payload.expiresAt,
2373
+ scope: payload.scope,
2374
+ ownerUserId: payload.user?.id
2375
+ })}`;
2376
+ }
2377
+ async function readSessionCredential(key, ref) {
2378
+ const pending = pendingCredentialReads.get(key);
2379
+ if (pending) return await pending;
2380
+ const read = readAccessToken(ref).finally(() => {
2381
+ if (pendingCredentialReads.get(key) === read) pendingCredentialReads.delete(key);
2382
+ });
2383
+ pendingCredentialReads.set(key, read);
2384
+ return await read;
2254
2385
  }
2255
2386
  function buildAuthSessionPayloadKey(payload) {
2256
2387
  return `${authSessionPath()}\n${JSON.stringify(payload)}`;
@@ -2292,7 +2423,7 @@ async function persistCommittedRemoteSessionRefresh(input) {
2292
2423
  const refresh = await prepareRemoteSessionRefresh({
2293
2424
  ...input,
2294
2425
  payload,
2295
- uniqueTokenRef: false
2426
+ uniqueTokenRef: true
2296
2427
  });
2297
2428
  if (!refresh) return null;
2298
2429
  try {
@@ -2873,6 +3004,6 @@ async function removeSessionFile() {
2873
3004
  await rm(authSessionPath(), { force: true });
2874
3005
  }
2875
3006
  //#endregion
2876
- export { redactPrepareStepDiagnosticsValue as $, DEFAULT_HEARTBEAT_INTERVAL_MS as A, REGISTER_RESPONSE_TIMEOUT_MS as B, CATALOG_SYNC_RETRY_INTERVAL_MS as C, DAEMON_STREAM_KEEPALIVE_INTERVAL_MS as D, DAEMON_STREAM_CONNECT_TIMEOUT_MS as E, MIN_HEARTBEAT_INTERVAL_MS as F, PREPARE_STEP_DIAGNOSTICS_MAX_CHARS as G, RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_INTERVAL_MS as H, MIN_SPACE_REQUEST_TIMEOUT_MS as I, prepareSessionWithTokenResponseSchema as J, prepareSessionResponseSchema as K, OPENCLAW_CLI_TIMEOUT_MS as L, HEARTBEAT_RESPONSE_TIMEOUT_MS as M, MAX_HEARTBEAT_INTERVAL_MS as N, DAEMON_STREAM_KEEPALIVE_PONG_TIMEOUT_MS as O, MAX_SPACE_REQUEST_TIMEOUT_MS as P, redactPrepareStepDiagnosticsText as Q, PROVIDER_CONVERSATION_PROOF_SYNC_INTERVAL_MS as R, resolveAuthSessionExpiryEligibility as S, DAEMON_RUNTIME_CONTRACT_EPOCH as T, RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_RETRY_INTERVAL_MS as U, ROUTE_CATALOG_LOAD_TIMEOUT_MS as V, RUNTIME_STATE_PERSIST_MIN_INTERVAL_MS as W, prepareStepDiagnosticsBundleSchema as X, prepareSetupBootstrapWriteSchema as Y, redactPrepareStepDiagnosticsBundle as Z, setAuthSession as _, beginAuthSessionTransition as a, isBinaryDistribution as b, getAuthSessionMetadata as c, getInterruptedComputerAuthSessionRecovery as d, hasPendingComputerSetupContinuation as f, resumeInterruptedComputerSetup as g, recordInterruptedComputerAuthSessionRecoveryFailure as h, assertAuthSessionMutationAvailable as i, DEFAULT_SPACE_REQUEST_TIMEOUT_MS as j, DEFAULT_GATEWAY_CHAIN_TIMEOUT_MS as k, getAuthSessionState as l, normalizeStoredActiveOrganization as m, AuthSessionRecoveryInProgressError as n, clearAuthSession as o, markInterruptedComputerAuthSessionRecovery as p, prepareSessionStreamServerFrameSchema as q, AuthSessionTransitionConflictError as r, completeInterruptedComputerAuthSessionRecovery as s, AuthSessionChangedBeforeTransitionError as t, getCurrentAuthOwnerUserId as u, updateAuthSessionActiveOrganization as v, CATALOG_SYNC_SIGNAL_POLL_INTERVAL_MS as w, resolveOpenMeldDistribution as x, runMacOsNativeKeychainHelperIfRequested as y, PROVIDER_CONVERSATION_PROOF_SYNC_RETRY_INTERVAL_MS as z };
3007
+ export { redactPrepareStepDiagnosticsBundle as $, DAEMON_STREAM_KEEPALIVE_PONG_TIMEOUT_MS as A, PROVIDER_CONVERSATION_PROOF_SYNC_INTERVAL_MS as B, resolveOpenMeldDistribution as C, DAEMON_RUNTIME_CONTRACT_EPOCH as D, CATALOG_SYNC_SIGNAL_POLL_INTERVAL_MS as E, MAX_HEARTBEAT_INTERVAL_MS as F, RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_RETRY_INTERVAL_MS as G, REGISTER_RESPONSE_TIMEOUT_MS as H, MAX_SPACE_REQUEST_TIMEOUT_MS as I, prepareSessionResponseSchema as J, RUNTIME_STATE_PERSIST_MIN_INTERVAL_MS as K, MIN_HEARTBEAT_INTERVAL_MS as L, DEFAULT_HEARTBEAT_INTERVAL_MS as M, DEFAULT_SPACE_REQUEST_TIMEOUT_MS as N, DAEMON_STREAM_CONNECT_TIMEOUT_MS as O, HEARTBEAT_RESPONSE_TIMEOUT_MS as P, prepareStepDiagnosticsBundleSchema as Q, MIN_SPACE_REQUEST_TIMEOUT_MS as R, isBinaryDistribution as S, CATALOG_SYNC_RETRY_INTERVAL_MS as T, ROUTE_CATALOG_LOAD_TIMEOUT_MS as U, PROVIDER_CONVERSATION_PROOF_SYNC_RETRY_INTERVAL_MS as V, RUNTIME_AGENT_CONTROLLER_REPORT_SYNC_INTERVAL_MS as W, prepareSessionWithTokenResponseSchema as X, prepareSessionStreamServerFrameSchema as Y, prepareSetupBootstrapWriteSchema as Z, recordInterruptedComputerAuthSessionRecoveryFailure as _, beginAuthSessionTransition as a, updateAuthSessionActiveOrganization as b, getAuthSessionMetadata as c, getInterruptedComputerAuthSessionRecovery as d, redactPrepareStepDiagnosticsText as et, hasPendingComputerSetupContinuation as f, onAuthSessionCredentialObservation as g, onAuthSessionCredentialAvailable as h, assertAuthSessionMutationAvailable as i, DEFAULT_GATEWAY_CHAIN_TIMEOUT_MS as j, DAEMON_STREAM_KEEPALIVE_INTERVAL_MS as k, getAuthSessionState as l, normalizeStoredActiveOrganization as m, AuthSessionRecoveryInProgressError as n, clearAuthSession as o, markInterruptedComputerAuthSessionRecovery as p, PREPARE_STEP_DIAGNOSTICS_MAX_CHARS as q, AuthSessionTransitionConflictError as r, completeInterruptedComputerAuthSessionRecovery as s, AuthSessionChangedBeforeTransitionError as t, redactPrepareStepDiagnosticsValue as tt, getCurrentAuthOwnerUserId as u, resumeInterruptedComputerSetup as v, resolveAuthSessionExpiryEligibility as w, runMacOsNativeKeychainHelperIfRequested as x, setAuthSession as y, OPENCLAW_CLI_TIMEOUT_MS as z };
2877
3008
 
2878
- //# sourceMappingURL=auth-session-wmefguut.js.map
3009
+ //# sourceMappingURL=auth-session-BjSqMLTz.js.map