@calimero-network/mero-js 16.1.0 → 18.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin-api/admin-client.d.ts +6 -8
- package/dist/admin-api/admin-client.js +7 -26
- package/dist/admin-api/admin-types.d.ts +9 -11
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +3 -3
- package/dist/index.cjs +10 -28
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +10 -28
- package/dist/index.mjs.map +2 -2
- package/dist/namespace-op/namespace-op.d.ts +1 -1
- package/dist/namespace-op/namespace-op.js +16 -4
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/http-client/signal-utils.ts", "../src/http-client/web-client.ts", "../src/http-client/http-factory.ts", "../src/http-client/retry.ts", "../src/auth-api/auth-client.ts", "../src/auth-api/auth-factory.ts", "../src/admin-api/admin-client.ts", "../src/admin-api/admin-factory.ts", "../src/auth/index.ts", "../src/rpc/index.ts", "../src/events/group.ts", "../src/events/sse.ts", "../src/events/ws.ts", "../src/ephemeral/codec.ts", "../src/ephemeral/index.ts", "../src/mero-js.ts", "../src/token-store/index.ts", "../src/cloud/cloud-client.ts", "../src/crypto/internal.ts", "../src/warrant/warrant.ts", "../src/device-cert/device-cert.ts", "../src/namespace-op/namespace-op.ts", "../src/capabilities.ts", "../src/nodeDiscovery.ts"],
|
|
4
|
-
"sourcesContent": ["// Mero.js - Pure JavaScript SDK for Calimero\n// This will contain the pure JavaScript SDK without React dependencies\n\n// Main SDK class\nexport { MeroJs, createMeroJs } from './mero-js.js';\nexport type { MeroJsConfig, TokenData } from './mero-js.js';\n\n// HTTP client module (Web Standards based)\nexport * from './http-client/index.js';\n\n// Auth API client\nexport * from './auth-api/index.js';\n\n// Admin API client\nexport * from './admin-api/index.js';\n\n// Auth utilities\nexport { parseAuthCallback, buildAuthLoginUrl } from './auth/index.js';\nexport type { AuthCallbackResult, AuthLoginOptions } from './auth/index.js';\n\n// Token store\nexport { MemoryTokenStore, LocalStorageTokenStore } from './token-store/index.js';\nexport type { TokenStore } from './token-store/index.js';\n\n// RPC client\nexport { RpcClient, RpcError } from './rpc/index.js';\nexport type { MigrateMyEntriesSummary } from './rpc/index.js';\nexport type { ExecuteParams } from './rpc/index.js';\n\n// Events (SSE / WebSocket)\nexport { SseClient, WsClient } from './events/index.js';\nexport type {\n SseEventData,\n WsEventData,\n AppVersionChangedEvent,\n GroupMembershipEventData,\n GroupMigrationEventData,\n MigrationStartedData,\n MigrationProgressData,\n CascadeProgressData,\n MigrationCompletedData,\n} from './events/index.js';\n\n// Ephemeral presence (cursors / typing / online)\nexport { EphemeralClient, jsonCodec } from './ephemeral/index.js';\nexport type { Codec, EphemeralEntry } from './ephemeral/index.js';\n\n// Cloud client (enable-HA, disable-HA)\nexport * from './cloud/index.js';\n\n// Warrant signing \u2014 mint the author's consent for a relay to run one intent\nexport { signWarrant, intentHash } from './warrant/index.js';\nexport {\n signDeviceCert,\n mintDeviceId,\n deviceCertPayload,\n accountForRoot,\n} from './device-cert/index.js';\nexport type { DeviceCertInput } from './device-cert/index.js';\nexport {\n signMemberJoinOp,\n encodeSignedInvitation,\n SIGNED_NAMESPACE_OP_SCHEMA_VERSION,\n} from './namespace-op/index.js';\nexport type { SignMemberJoinInput } from './namespace-op/index.js';\nexport type { WarrantInput } from './warrant/index.js';\n\n// Member capability bitmask constants & helpers\nexport * from './capabilities.js';\n\n// Utilities\nexport {\n DEFAULT_LOCAL_NODE_PORTS,\n localNodeUrl,\n nodeEndpoint,\n probeNodeHealth,\n discoverLocalNodes,\n} from './nodeDiscovery.js';\nexport type { DiscoverLocalNodesOptions } from './nodeDiscovery.js';\n", "// Utility for combining multiple AbortSignals\nexport function combineSignals(\n signals: Array<AbortSignal | undefined>,\n): AbortSignal | undefined {\n const list = signals.filter(Boolean) as AbortSignal[];\n if (list.length === 0) return undefined;\n\n // Prefer native any(), but fall back if unavailable or it throws\n const AbortSignalAny = AbortSignal as {\n any?: (signals: AbortSignal[]) => AbortSignal;\n };\n if (typeof AbortSignalAny.any === 'function') {\n try {\n return AbortSignalAny.any(list);\n } catch {\n // Fall through to manual implementation\n }\n }\n\n const controller = new AbortController();\n const onAbort = (evt: Event) => {\n controller.abort((evt.target as AbortSignal).reason);\n for (const s of list) s.removeEventListener('abort', onAbort);\n };\n\n for (const s of list) {\n if (s.aborted) return AbortSignal.abort(s.reason);\n s.addEventListener('abort', onAbort, { once: true });\n }\n\n return controller.signal;\n}\n\n// Helper to create a timeout signal\nexport function createTimeoutSignal(timeoutMs: number): AbortSignal {\n // Use AbortSignal.timeout if available (Node 18.17+, modern browsers)\n if (typeof AbortSignal.timeout === 'function') {\n return AbortSignal.timeout(timeoutMs);\n }\n\n // Fallback for older environments\n const controller = new AbortController();\n setTimeout(() => {\n controller.abort(new DOMException('Timeout', 'TimeoutError'));\n }, timeoutMs);\n\n return controller.signal;\n}\n", "// ErrorResponse import removed as it's not used\nimport {\n HttpClient,\n Transport,\n RequestOptions,\n ResponseParser,\n} from './http-types.js';\nimport { combineSignals, createTimeoutSignal } from './signal-utils.js';\n\n/**\n * `x-auth-error` reasons that mean the whole token family is gone.\n *\n * Refresh tokens are single-use (calimero-network/core#3083): presenting a\n * consumed refresh token is treated as token theft and the server revokes the\n * family. Refreshing or retrying afterwards is pointless \u2014 the only way out is\n * a fresh login.\n */\nconst TERMINAL_AUTH_ERRORS = new Set(['token_reuse', 'token_revoked']);\n\n/**\n * Pull the node's explanation out of an error body. Core answers every handled\n * failure with `{\"error\": \"<message>\"}` (`ApiError::into_response`); the nested\n * `{\"error\": {\"message\": ...}}` form is what proxies in front of a node emit.\n * Returns undefined for a non-JSON, empty, or envelope-less body.\n */\nfunction extractErrorMessage(bodyText?: string): string | undefined {\n if (!bodyText) return undefined;\n try {\n const error = (JSON.parse(bodyText) as { error?: unknown })?.error;\n if (typeof error === 'string' && error.trim() !== '') return error;\n const nested = (error as { message?: unknown } | null)?.message;\n if (typeof nested === 'string' && nested.trim() !== '') return nested;\n } catch {\n // Not JSON \u2014 the status line is all we can honestly report.\n }\n return undefined;\n}\n\n// Custom error class for HTTP errors\nexport class HTTPError extends Error {\n name = 'HTTPError';\n\n constructor(\n public status: number,\n public statusText: string,\n public url: string,\n public headers: Headers,\n public bodyText?: string, // cap at ~64KB\n ) {\n const explanation = extractErrorMessage(bodyText);\n super(\n explanation\n ? `HTTP ${status} ${statusText}: ${explanation}`\n : `HTTP ${status} ${statusText}`,\n );\n }\n\n toJSON(): {\n status: number;\n statusText: string;\n url: string;\n headers: Record<string, string>;\n bodyText?: string;\n } {\n return {\n status: this.status,\n statusText: this.statusText,\n url: this.url,\n headers: headersToRecord(this.headers),\n bodyText: this.bodyText,\n };\n }\n}\n\n/**\n * Terminal authentication error: the refresh-token family was revoked (single-use\n * refresh token replayed, or the token was explicitly revoked). Never retried and\n * never refreshed \u2014 apps should catch this and force a re-login.\n *\n * Extends {@link HTTPError} so existing `instanceof HTTPError` handling keeps working.\n */\nexport class AuthRevokedError extends HTTPError {\n name = 'AuthRevokedError';\n\n constructor(\n /** Value of the `x-auth-error` header, e.g. `token_reuse` or `token_revoked`. */\n public reason: string,\n status: number,\n statusText: string,\n url: string,\n headers: Headers,\n bodyText?: string,\n ) {\n super(status, statusText, url, headers, bodyText);\n this.message = `Authentication revoked (${reason}): HTTP ${status} ${statusText}`;\n }\n}\n\n// Helper function to convert Headers to Record\nfunction headersToRecord(headers: Headers): Record<string, string> {\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key] = value;\n });\n return record;\n}\n\n// Web Standards HTTP client implementation\nexport class WebHttpClient implements HttpClient {\n // Cache for concurrent refresh token calls to prevent race conditions\n private refreshTokenPromise: Promise<string> | null = null;\n // Cache for concurrent onTokenRefresh calls to prevent duplicate callbacks\n private onTokenRefreshPromise: Promise<void> | null = null;\n \n constructor(private transport: Transport) {}\n\n async get<T>(path: string, init?: RequestOptions): Promise<T> {\n return this.request<T>(path, { ...init, method: 'GET' });\n }\n\n async post<T>(\n path: string,\n body?: unknown,\n init?: RequestOptions,\n ): Promise<T> {\n return this.request<T>(path, {\n ...init,\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n headers: {\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n }\n\n async put<T>(\n path: string,\n body?: unknown,\n init?: RequestOptions,\n ): Promise<T> {\n return this.request<T>(path, {\n ...init,\n method: 'PUT',\n body: body ? JSON.stringify(body) : undefined,\n headers: {\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n }\n\n async delete<T>(path: string, init?: RequestOptions): Promise<T> {\n return this.request<T>(path, { ...init, method: 'DELETE' });\n }\n\n async patch<T>(\n path: string,\n body?: unknown,\n init?: RequestOptions,\n ): Promise<T> {\n return this.request<T>(path, {\n ...init,\n method: 'PATCH',\n body: body ? JSON.stringify(body) : undefined,\n headers: {\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n }\n\n async head(\n path: string,\n init?: RequestOptions,\n ): Promise<{ headers: Record<string, string>; status: number }> {\n const response = await this.makeRequest<Response>(path, {\n ...init,\n method: 'HEAD',\n parse: 'response',\n });\n return {\n headers: headersToRecord(response.headers),\n status: response.status,\n };\n }\n\n async request<T>(path: string, init?: RequestOptions): Promise<T> {\n return this.makeRequest<T>(path, init);\n }\n\n private async makeRequest<T>(\n path: string,\n init?: RequestOptions,\n retryCount = 0,\n requestStartTime?: number,\n ): Promise<T> {\n // Maximum retry attempts to prevent infinite loops\n const MAX_RETRY_ATTEMPTS = 1;\n const url = this.buildUrl(path);\n \n // Track request start time for timeout calculation (only on first attempt)\n // Use per-request start time to avoid corruption from concurrent requests\n const startTime = requestStartTime ?? Date.now();\n // Note: Tauri proxy script now handles AbortSignal, so we can use full RequestInit\n // Removed Tauri-specific minimal path - proxy script handles AbortSignal properly\n const signal = this.createAbortSignal(init);\n const headers = await this.buildHeaders(init?.headers);\n let headersObj: Record<string, string>;\n if (headers instanceof Headers) {\n headersObj = {};\n headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n } else {\n headersObj = headers;\n }\n \n const requestInit: RequestInit = {\n method: init?.method || 'GET',\n headers: headersObj,\n };\n \n // Check if body is a stream (ReadableStream) that can't be reused\n // Note: Blob is reusable, so it's not included here\n const isStreamBody = init?.body instanceof ReadableStream ||\n (typeof init?.body === 'object' && init?.body !== null && 'getReader' in init.body && !(init.body instanceof Blob));\n \n if (init?.body !== undefined && !isStreamBody) {\n requestInit.body = init.body;\n } else if (init?.body !== undefined && isStreamBody && retryCount === 0) {\n // Only include stream body on first attempt - can't retry with streams\n requestInit.body = init.body;\n }\n \n // For retries, calculate remaining timeout to prevent timeout reset\n // Track elapsed time and use remaining timeout for retry\n // Note: This is calculated before the request, so it doesn't include token refresh time\n // The actual remaining timeout check happens after token refresh completes\n let retrySignal: AbortSignal | undefined;\n if (retryCount > 0 && requestStartTime !== undefined) {\n const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;\n if (timeoutMs) {\n // Calculate elapsed time (will be recalculated after token refresh if needed)\n const elapsed = Date.now() - startTime;\n const remaining = Math.max(0, timeoutMs - elapsed);\n // Create signal with remaining timeout, preserving user's signal\n retrySignal = this.createAbortSignal({ ...init, timeoutMs: remaining });\n } else {\n // No timeout, just preserve user's signal\n retrySignal = this.createAbortSignal(init);\n }\n } else {\n retrySignal = signal;\n }\n \n if (retrySignal) {\n requestInit.signal = retrySignal;\n }\n \n if (this.transport.credentials !== undefined) {\n requestInit.credentials = this.transport.credentials;\n }\n \n if (init?.mode !== undefined) {\n requestInit.mode = init.mode;\n }\n if (init?.cache !== undefined) {\n requestInit.cache = init.cache;\n }\n if (init?.redirect !== undefined) {\n requestInit.redirect = init.redirect;\n }\n if (init?.referrer !== undefined) {\n requestInit.referrer = init.referrer;\n }\n if (init?.referrerPolicy !== undefined) {\n requestInit.referrerPolicy = init.referrerPolicy;\n }\n if (init?.integrity !== undefined) {\n requestInit.integrity = init.integrity;\n }\n if (init?.keepalive !== undefined) {\n requestInit.keepalive = init.keepalive;\n }\n\n try {\n const response = await this.transport.fetch(url, requestInit);\n\n if (!response.ok) {\n const bodyText = await this.getBodyText(response);\n const httpError = new HTTPError(\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n\n // Handle a revoked token family (single-use refresh token replayed, or an\n // explicitly revoked token). This is terminal: refreshing would only burn\n // another token and retrying would 401 again, so clear the tokens via the\n // onAuthRevoked hook and surface a distinguishable error.\n const authError = response.headers.get('x-auth-error');\n if (\n (response.status === 401 || response.status === 403) &&\n authError &&\n TERMINAL_AUTH_ERRORS.has(authError)\n ) {\n // Any in-flight refresh is based on a now-dead family \u2014 drop the caches.\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n\n if (this.transport.onAuthRevoked) {\n try {\n await this.transport.onAuthRevoked();\n } catch {\n // Never mask the auth error with a cleanup failure.\n }\n }\n\n throw new AuthRevokedError(\n authError,\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n }\n\n // Handle 401 with token_expired - attempt automatic token refresh\n const userAborted = init?.signal?.aborted === true;\n if (\n response.status === 401 &&\n this.transport.refreshToken &&\n authError === 'token_expired' &&\n retryCount < MAX_RETRY_ATTEMPTS &&\n !isStreamBody &&\n !userAborted\n ) {\n try {\n // Use cached refresh promise if one is in progress (prevents race conditions)\n let refreshPromise = this.refreshTokenPromise;\n if (!refreshPromise) {\n refreshPromise = this.transport.refreshToken();\n this.refreshTokenPromise = refreshPromise;\n }\n \n // Attempt to refresh the token\n const newToken = await refreshPromise;\n \n // Validate token - must be non-empty\n if (!newToken || newToken.trim() === '') {\n // Clear caches on error\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n throw new Error('Refresh token returned empty token');\n }\n \n // onTokenRefresh is required when refreshToken is provided\n // Without it, the new token cannot be stored and getAuthToken() will return the old token\n if (!this.transport.onTokenRefresh) {\n // Clear caches on error\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n throw new Error(\n 'onTokenRefresh callback is required when refreshToken is provided. ' +\n 'The callback must update the token storage so getAuthToken() returns the new token.'\n );\n }\n \n // Use cached onTokenRefresh promise if one is in progress (prevents duplicate callbacks)\n // This ensures onTokenRefresh is only called once per token refresh, even with concurrent requests\n let onTokenRefreshPromise = this.onTokenRefreshPromise;\n if (!onTokenRefreshPromise) {\n onTokenRefreshPromise = this.transport.onTokenRefresh(newToken);\n this.onTokenRefreshPromise = onTokenRefreshPromise;\n }\n \n // Update token via callback (only called once per refresh, even with concurrent requests)\n // Errors from onTokenRefresh callback should be preserved (don't mask as 401)\n // This helps developers debug token storage issues\n await onTokenRefreshPromise;\n \n // Clear caches after both refresh and callback complete\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n \n // Check if timeout has expired during token refresh\n // If so, throw the original 401 error instead of retrying with 0ms timeout\n // This prevents timeout/abort errors that obscure the root cause (expired token)\n const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;\n if (timeoutMs && requestStartTime !== undefined) {\n const elapsed = Date.now() - startTime;\n const remaining = timeoutMs - elapsed;\n if (remaining <= 0) {\n // Timeout expired during token refresh - throw original 401 error\n // This is better than retrying with 0ms timeout which would cause confusing timeout errors\n throw httpError;\n }\n }\n \n // Retry the request with the new token (increment retry count)\n // Preserve user's abort signal and start time in retry\n return this.makeRequest<T>(path, init, retryCount + 1, startTime);\n } catch (refreshError) {\n // Clear caches on error\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n // Configuration errors (missing onTokenRefresh) should be thrown as-is\n if (refreshError instanceof Error && refreshError.message.includes('onTokenRefresh')) {\n throw refreshError;\n }\n // Errors from onTokenRefresh callback are already thrown above, so if we get here,\n // it's either a refreshToken() failure or empty token - throw original 401\n // This matches the PR description: \"If refresh fails, throws the original 401 error\"\n throw httpError;\n }\n }\n\n throw httpError;\n }\n\n return this.parseResponse<T>(response, init?.parse);\n } catch (error) {\n if (error instanceof HTTPError) {\n throw error;\n }\n // Preserve configuration errors (like missing onTokenRefresh)\n if (error instanceof Error && error.message.includes('onTokenRefresh')) {\n throw error;\n }\n throw new HTTPError(\n 0,\n 'Network Error',\n url,\n new Headers(),\n error instanceof Error ? error.message : 'Unknown error',\n );\n }\n }\n\n private buildUrl(path: string): string {\n // Handle absolute URLs\n if (path.startsWith('http://') || path.startsWith('https://')) {\n return path;\n }\n\n // Handle baseUrl with path\n const baseUrl = this.transport.baseUrl;\n if (path.startsWith('/')) {\n // If path starts with /, combine with baseUrl\n const base = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n return `${base}${path}`;\n } else {\n // If path doesn't start with /, append to baseUrl\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n return `${base}${path}`;\n }\n }\n\n private createAbortSignal(init?: RequestOptions): AbortSignal | undefined {\n const signals: AbortSignal[] = [];\n\n if (this.transport.defaultAbortSignal) {\n signals.push(this.transport.defaultAbortSignal);\n }\n\n if (init?.signal) {\n signals.push(init.signal);\n }\n\n const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;\n if (timeoutMs) {\n signals.push(createTimeoutSignal(timeoutMs));\n }\n\n return signals.length > 0 ? combineSignals(signals) : undefined;\n }\n\n private async buildHeaders(\n initHeaders?: HeadersInit,\n ): Promise<Record<string, string>> {\n const headers: Record<string, string> = {\n ...this.transport.defaultHeaders,\n };\n\n // Add auth token if available and not empty\n if (this.transport.getAuthToken) {\n try {\n const token = await this.transport.getAuthToken();\n if (token && token.trim() !== '') {\n headers.Authorization = `Bearer ${token}`;\n }\n } catch (error) {\n // Ignore auth token errors\n }\n }\n\n // Add init headers\n if (initHeaders) {\n if (initHeaders instanceof Headers) {\n initHeaders.forEach((value, key) => {\n headers[key] = value;\n });\n } else if (Array.isArray(initHeaders)) {\n initHeaders.forEach(([key, value]) => {\n headers[key] = value;\n });\n } else {\n Object.assign(headers, initHeaders);\n }\n }\n\n return headers;\n }\n\n private async parseResponse<T>(\n response: Response,\n parse?: ResponseParser,\n ): Promise<T> {\n switch (parse) {\n case 'text':\n return (await response.text()) as T;\n case 'blob':\n return (await response.blob()) as T;\n case 'arrayBuffer':\n return (await response.arrayBuffer()) as T;\n case 'response':\n return response as T;\n case 'json':\n default: {\n // Tolerate empty 2xx bodies (e.g. 204 No Content from delete/resync):\n // `response.json()` throws on '', so read text and return null when empty.\n const text = await response.text();\n if (!text) return null as T;\n try {\n return JSON.parse(text) as T;\n } catch {\n // Non-JSON body on a 2xx (e.g. an HTML error page) \u2014 surface a clear\n // error with a snippet instead of a bare SyntaxError.\n throw new Error(\n `Expected a JSON response (status ${response.status}) but body was not JSON: ${text.slice(0, 200)}`,\n );\n }\n }\n }\n }\n\n private async getBodyText(response: Response): Promise<string> {\n try {\n const text = await response.text();\n return text.length > 65536 ? text.slice(0, 65536) + '...' : text;\n } catch {\n return '';\n }\n }\n}\n", "import { WebHttpClient } from './web-client.js';\nimport { Transport, HttpClient } from './http-types.js';\n\n// Factory function to create HTTP client with sensible defaults\nexport function createHttpClient(transport: Transport): HttpClient {\n return new WebHttpClient(transport);\n}\n\n// Factory function for browser environments\nexport function createBrowserHttpClient(options: {\n baseUrl: string;\n getAuthToken?: () => Promise<string | undefined>;\n onTokenRefresh?: (newToken: string) => Promise<void>;\n /**\n * Callback to refresh the access token when a 401 error with 'token_expired' is detected.\n * Should return the new access token, or throw an error if refresh fails.\n * If provided, the client will automatically retry the request after a successful refresh.\n */\n refreshToken?: () => Promise<string>;\n /**\n * Callback invoked when the server reports a revoked token family\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal \u2014 the request is\n * never retried; clear stored tokens and force a re-login.\n */\n onAuthRevoked?: () => Promise<void> | void;\n defaultHeaders?: Record<string, string>;\n timeoutMs?: number;\n credentials?: RequestCredentials;\n defaultAbortSignal?: AbortSignal;\n}): HttpClient {\n const transport: Transport = {\n // Wrap fetch in arrow function to prevent \"Illegal invocation\" error\n // This preserves the correct 'this' context when fetch is called\n fetch: (url: RequestInfo | URL, init?: RequestInit) => globalThis.fetch(url, init),\n baseUrl: options.baseUrl,\n getAuthToken: options.getAuthToken,\n onTokenRefresh: options.onTokenRefresh,\n refreshToken: options.refreshToken,\n onAuthRevoked: options.onAuthRevoked,\n defaultHeaders: options.defaultHeaders,\n timeoutMs: options.timeoutMs,\n credentials: options.credentials, // No default credentials\n defaultAbortSignal: options.defaultAbortSignal,\n };\n\n return createHttpClient(transport);\n}\n\n// Factory function for Node.js environments\nexport function createNodeHttpClient(options: {\n baseUrl: string;\n fetch?: typeof fetch; // Allow injection of undici.fetch or other fetch implementations\n getAuthToken?: () => Promise<string | undefined>;\n onTokenRefresh?: (newToken: string) => Promise<void>;\n /**\n * Callback to refresh the access token when a 401 error with 'token_expired' is detected.\n * Should return the new access token, or throw an error if refresh fails.\n * If provided, the client will automatically retry the request after a successful refresh.\n */\n refreshToken?: () => Promise<string>;\n /**\n * Callback invoked when the server reports a revoked token family\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal \u2014 the request is\n * never retried; clear stored tokens and force a re-login.\n */\n onAuthRevoked?: () => Promise<void> | void;\n defaultHeaders?: Record<string, string>;\n timeoutMs?: number;\n credentials?: RequestCredentials;\n defaultAbortSignal?: AbortSignal;\n}): HttpClient {\n // Use provided fetch or try to use global fetch (Node 18+)\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n if (!fetchImpl) {\n throw new Error(\n 'No fetch implementation available. Please provide a fetch implementation ' +\n '(e.g., undici.fetch) or use Node.js 18+ which has native fetch support.',\n );\n }\n\n // Check if we're using the default globalThis.fetch to preserve context\n // When fetchImpl is globalThis.fetch, we must call it directly, not through a variable\n // Custom fetch implementations (like undici.fetch) can be called through the variable\n const isDefaultFetch = fetchImpl === globalThis.fetch;\n\n const transport: Transport = {\n // Wrap fetch in arrow function to prevent \"Illegal invocation\" error\n // For globalThis.fetch, call it directly to preserve 'this' context\n // For custom implementations, calling through the variable is safe\n fetch: isDefaultFetch\n ? (url: RequestInfo | URL, init?: RequestInit) => globalThis.fetch(url, init)\n : (url: RequestInfo | URL, init?: RequestInit) => fetchImpl(url, init),\n baseUrl: options.baseUrl,\n getAuthToken: options.getAuthToken,\n onTokenRefresh: options.onTokenRefresh,\n refreshToken: options.refreshToken,\n onAuthRevoked: options.onAuthRevoked,\n defaultHeaders: options.defaultHeaders,\n timeoutMs: options.timeoutMs,\n credentials: options.credentials, // Node.js doesn't have default credentials\n defaultAbortSignal: options.defaultAbortSignal,\n };\n\n return createHttpClient(transport);\n}\n\n// Universal factory that works in both environments\nexport function createUniversalHttpClient(options: {\n baseUrl: string;\n fetch?: typeof fetch;\n getAuthToken?: () => Promise<string | undefined>;\n onTokenRefresh?: (newToken: string) => Promise<void>;\n /**\n * Callback to refresh the access token when a 401 error with 'token_expired' is detected.\n * Should return the new access token, or throw an error if refresh fails.\n * If provided, the client will automatically retry the request after a successful refresh.\n */\n refreshToken?: () => Promise<string>;\n /**\n * Callback invoked when the server reports a revoked token family\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal \u2014 the request is\n * never retried; clear stored tokens and force a re-login.\n */\n onAuthRevoked?: () => Promise<void> | void;\n defaultHeaders?: Record<string, string>;\n timeoutMs?: number;\n credentials?: RequestCredentials;\n defaultAbortSignal?: AbortSignal;\n}): HttpClient {\n // Try to detect environment and use appropriate factory\n if (typeof window !== 'undefined') {\n // Browser environment\n return createBrowserHttpClient(options);\n } else {\n // Node.js environment\n return createNodeHttpClient(options);\n }\n}\n", "// Retry helper for HTTP requests\nexport interface RetryOptions {\n attempts?: number;\n}\n\n// Error types for retry logic\ninterface ErrorWithName extends Error {\n name: string;\n}\n\ninterface ErrorWithStatus extends Error {\n status: number;\n}\n\ninterface ErrorWithHeaders extends Error {\n headers?: Headers;\n}\n\n// Default retry condition - retry on network errors and 5xx status codes\nfunction defaultRetryCondition(error: Error, attempt: number): boolean {\n // Don't retry on the last attempt\n if (attempt <= 0) return false;\n\n // Distinguish timeout vs. user abort:\n // - Timeout: name === 'TimeoutError' (per spec/platforms)\n // - User abort: name === 'AbortError'\n const errorWithName = error as ErrorWithName;\n const name = errorWithName?.name;\n if (name === 'TimeoutError') return true;\n if (name === 'AbortError') return false;\n\n // HTTP 5xx and 429 (including HTTPError from web-client)\n const errorWithStatus = error as ErrorWithStatus;\n if (\n 'status' in errorWithStatus &&\n typeof errorWithStatus.status === 'number'\n ) {\n const status = errorWithStatus.status;\n return status >= 500 || status === 429;\n }\n // Network TypeError (DNS/reset) is reasonably retryable\n if (name === 'TypeError') return true;\n\n return false;\n}\n\n// Calculate delay with exponential backoff and jitter\nfunction calculateDelay(attempt: number): number {\n const baseDelayMs = 250; // Base 250ms as per spec\n const delay = baseDelayMs * Math.pow(2, attempt - 1);\n\n // Add \u00B120% jitter to reduce stampedes\n const jitter = (Math.random() - 0.5) * 0.4 * delay;\n return Math.max(0, delay + jitter);\n}\n\n// Retry helper function with new signature\nexport async function withRetry<T>(\n fn: (attempt: number) => Promise<T>,\n options: RetryOptions = {},\n): Promise<T> {\n const { attempts = 3 } = options;\n\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= attempts; attempt++) {\n try {\n return await fn(attempt);\n } catch (error) {\n lastError = error as Error;\n\n // Check if we should retry (this handles the last attempt check)\n if (!defaultRetryCondition(lastError, attempts - attempt)) {\n throw lastError;\n }\n\n // Calculate delay\n let delayMs = calculateDelay(attempt);\n\n // Check for Retry-After header if it's an HTTP error\n const errorWithHeaders = lastError as ErrorWithHeaders;\n const hdrs = errorWithHeaders.headers;\n const retryAfter = hdrs?.get?.('Retry-After');\n if (retryAfter) {\n // If it's a number, treat as seconds\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n delayMs = Math.max(delayMs, seconds * 1000);\n } else {\n // If it's a date, calculate the difference\n const date = new Date(retryAfter);\n if (!isNaN(date.getTime())) {\n const waitTime = Math.max(0, date.getTime() - Date.now());\n // Cap wait at 60s per attempt as per spec\n delayMs = Math.max(delayMs, Math.min(waitTime, 60000));\n }\n }\n }\n\n // Wait before retrying\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n throw lastError || new Error('Retry failed without error');\n}\n\n// Helper to create a retry-enabled HTTP client method\nexport function createRetryableMethod<T extends unknown[], R>(\n method: (...args: T) => Promise<R>,\n retryOptions: RetryOptions = {},\n) {\n return async (...args: T): Promise<R> => {\n return withRetry(() => method(...args), retryOptions);\n };\n}\n", "import { HttpClient } from '../http-client/index.js';\nimport {\n // Common types\n ApiResponse,\n // Health and Status\n HealthResponse,\n IdentityResponse,\n ProvidersResponse,\n // Authentication\n TokenRequest,\n TokenResponse,\n RefreshTokenRequest,\n // Mock Token (testing)\n MockTokenRequest,\n // Token Management\n RevokeTokenRequest,\n RevokeTokenResponse,\n // Key Management\n CreateKeyRequest,\n CreateKeyResponse,\n DeleteKeyResponse,\n RootKey,\n // Client Management\n ClientKey,\n GenerateClientKeyRequest,\n DeleteClientResponse,\n // Permissions\n PermissionResponse,\n UpdateKeyPermissionsRequest,\n} from './auth-types.js';\n\nexport class AuthApiClient {\n constructor(private httpClient: HttpClient) {}\n\n // Health and Status Endpoints\n async getHealth(): Promise<HealthResponse> {\n const response =\n await this.httpClient.get<ApiResponse<HealthResponse>>('/auth/health');\n if (!response.data) {\n throw new Error('Health response data is null');\n }\n return response.data;\n }\n\n async getIdentity(): Promise<IdentityResponse> {\n const response =\n await this.httpClient.get<ApiResponse<IdentityResponse>>(\n '/admin/identity',\n );\n if (!response.data) {\n throw new Error('Identity response data is null');\n }\n return response.data;\n }\n\n async getProviders(): Promise<ProvidersResponse> {\n const response =\n await this.httpClient.get<ApiResponse<ProvidersResponse>>(\n '/auth/providers',\n );\n if (!response.data) {\n throw new Error('Providers response data is null');\n }\n return response.data;\n }\n\n // Authentication Endpoints\n async getLoginPage(): Promise<string> {\n return this.httpClient.get<string>('/auth/login', { parse: 'text' });\n }\n\n async generateTokens(request: TokenRequest): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/auth/token', request);\n }\n\n async refreshToken(request: RefreshTokenRequest): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/auth/refresh', request);\n }\n\n async generateMockTokens(request: MockTokenRequest): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/auth/mock-token', request);\n }\n\n async validateToken(token: string): Promise<{\n valid: boolean;\n headers: Record<string, string>;\n status: number;\n }> {\n try {\n const response = await this.validateTokenGet(token);\n return {\n valid: response.status === 200,\n headers: response.headers,\n status: response.status,\n };\n } catch (error) {\n return {\n valid: false,\n headers: {},\n status: 401,\n };\n }\n }\n\n async validateTokenGet(\n token: string,\n ): Promise<{ status: number; headers: Record<string, string> }> {\n const response = await this.httpClient.head('/auth/validate', {\n headers: { Authorization: `Bearer ${token}` },\n });\n return {\n status: response.status,\n headers: response.headers,\n };\n }\n\n // Token Management Endpoints\n // NOTE: node auth status lives on AdminApiClient.isAuthed() (/admin-api/is-authed);\n // there is no /auth/is-authed on the auth service.\n async revokeTokens(\n request: RevokeTokenRequest,\n ): Promise<RevokeTokenResponse> {\n const response = await this.httpClient.post<ApiResponse<RevokeTokenResponse>>(\n '/admin/revoke',\n request,\n );\n if (!response.data) {\n throw new Error('Revoke tokens response data is null');\n }\n return response.data;\n }\n\n // Key Management Endpoints\n async listRootKeys(): Promise<RootKey[]> {\n const response =\n await this.httpClient.get<ApiResponse<RootKey[]>>('/admin/keys');\n if (!response.data) {\n throw new Error('Root keys response data is null');\n }\n return response.data;\n }\n\n async createRootKey(request: CreateKeyRequest): Promise<CreateKeyResponse> {\n const response = await this.httpClient.post<ApiResponse<CreateKeyResponse>>(\n '/admin/keys',\n request,\n );\n if (!response.data) {\n throw new Error('Create root key response data is null');\n }\n return response.data;\n }\n\n async deleteRootKey(keyId: string): Promise<DeleteKeyResponse> {\n return this.httpClient.delete<DeleteKeyResponse>(`/admin/keys/${keyId}`);\n }\n\n // Client Management Endpoints\n async listClientKeys(): Promise<ClientKey[]> {\n const response = await this.httpClient.get<ApiResponse<ClientKey[]>>(\n '/admin/keys/clients',\n );\n if (!response.data) {\n throw new Error('Client keys response data is null');\n }\n return response.data;\n }\n\n async generateClientKey(\n request: GenerateClientKeyRequest,\n ): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/admin/client-key', request);\n }\n\n async deleteClientKey(\n keyId: string,\n clientId: string,\n ): Promise<DeleteClientResponse> {\n return this.httpClient.delete<DeleteClientResponse>(\n `/admin/keys/${keyId}/clients/${clientId}`,\n );\n }\n\n // Permission Management Endpoints\n async getKeyPermissions(keyId: string): Promise<PermissionResponse> {\n return this.httpClient.get<PermissionResponse>(\n `/admin/keys/${keyId}/permissions`,\n );\n }\n\n async updateKeyPermissions(\n keyId: string,\n changes: UpdateKeyPermissionsRequest,\n ): Promise<PermissionResponse> {\n // Core expects an { add, remove } delta, not a { permissions } replacement.\n return this.httpClient.put<PermissionResponse>(\n `/admin/keys/${keyId}/permissions`,\n { add: changes.add, remove: changes.remove },\n );\n }\n}\n", "import { AuthApiClient } from './auth-client.js';\nimport { AuthApiClientConfig } from './auth-types.js';\nimport { HttpClient } from '../http-client/index.js';\n\n// Mock HTTP client for testing\nclass MockHttpClient implements HttpClient {\n async get<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async post<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async put<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async delete<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async patch<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async head(): Promise<{ headers: Record<string, string>; status: number }> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async request<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n}\n\n// Factory functions for creating Auth API clients\nexport function createBrowserAuthApiClient(\n _config: AuthApiClientConfig,\n): AuthApiClient {\n const httpClient = new MockHttpClient();\n return new AuthApiClient(httpClient);\n}\n\nexport function createNodeAuthApiClient(\n _config: AuthApiClientConfig,\n): AuthApiClient {\n const httpClient = new MockHttpClient();\n return new AuthApiClient(httpClient);\n}\n\nexport function createAuthApiClient(\n _config: AuthApiClientConfig,\n): AuthApiClient {\n const httpClient = new MockHttpClient();\n return new AuthApiClient(httpClient);\n}\n\nexport function createAuthApiClientFromHttpClient(\n httpClient: HttpClient,\n _config: AuthApiClientConfig,\n): AuthApiClient {\n return new AuthApiClient(httpClient);\n}\n", "import { HttpClient, withRetry } from '../http-client/index.js';\nimport type {\n HealthStatus,\n AdminAuthStatus,\n InstallApplicationRequest,\n InstallApplicationResponseData,\n InstallDevApplicationRequest,\n UninstallApplicationResponseData,\n ListApplicationsResponseData,\n GetApplicationResponseData,\n ApplicationVersionEntry,\n GetApplicationAbiResponseData,\n GetLatestVersionResponseData,\n ListPackagesResponseData,\n ListVersionsResponseData,\n RegistryBundleManifest,\n CreateContextRequest,\n CreateContextResponseData,\n DeleteContextRequest,\n DeleteContextResponseData,\n GetContextsResponseData,\n Context,\n GenerateContextIdentityResponseData,\n GetContextIdentitiesResponseData,\n JoinContextResponseData,\n JoinSubgroupInheritanceResponseData,\n ContextGroupResponseData,\n ContextStorageResponseData,\n InviteSpecializedNodeRequest,\n InviteSpecializedNodeResponseData,\n UpdateContextApplicationRequest,\n ResyncContextRequest,\n ResyncContextResponseData,\n ContextsWithExecutorsResponseData,\n UploadBlobRequest,\n UploadBlobResponseData,\n DeleteBlobResponseData,\n ListBlobsResponseData,\n GetBlobInfoResponseData,\n CreateContextAliasRequest,\n CreateApplicationAliasRequest,\n CreateAliasResponseData,\n LookupAliasResponseData,\n DeleteAliasResponseData,\n ListAliasesResponseData,\n ListNamespacesResponseData,\n CreateNamespaceRequest,\n CreateNamespaceResponseData,\n DeleteNamespaceRequest,\n DeleteNamespaceResponseData,\n CreateNamespaceInvitationRequest,\n CreateNamespaceInvitationResponseData,\n CreateRecursiveInvitationResponseData,\n JoinNamespaceRequest,\n JoinNamespaceResponseData,\n CreateGroupInNamespaceRequest,\n CreateGroupInNamespaceResponseData,\n SubgroupEntry,\n Namespace,\n NamespaceIdentity,\n NodeIdentity,\n GroupInfoResponseData,\n DeleteGroupRequest,\n DeleteGroupResponseData,\n ListGroupMembersResponseData,\n ListGroupContextsResponseData,\n AddGroupMembersRequest,\n RemoveGroupMembersRequest,\n UpdateMemberRoleRequest,\n MemberCapabilities,\n SetMemberCapabilitiesRequest,\n SetDefaultCapabilitiesRequest,\n SetSubgroupVisibilityRequest,\n SetTeeAdmissionPolicyRequest,\n GetTeeAdmissionPolicyResponseData,\n SetGroupMetadataRequest,\n SetMemberMetadataRequest,\n SetContextMetadataRequest,\n MetadataRecord,\n GetMetadataResponseData,\n SyncGroupRequest,\n SyncGroupResponseData,\n UpgradeGroupRequest,\n UpgradeGroupResponseData,\n GroupUpgradeStatusResponseData,\n MigrationStatus,\n CascadeStatusEntry,\n RetryGroupUpgradeRequest,\n RetryGroupUpgradeResponseData,\n ReparentGroupRequest,\n ReparentGroupResponseData,\n DetachContextFromGroupRequest,\n CreateGroupInvitationRequest,\n CreateGroupInvitationResponseData,\n CreateRecursiveGroupInvitationResponseData,\n JoinGroupRequest,\n JoinGroupResponseData,\n TeeInfoResponseData,\n TeeAttestRequest,\n TeeAttestResponseData,\n TeeVerifyQuoteRequest,\n TeeVerifyQuoteResponseData,\n PerformIntentRequest,\n PerformIntentResponseData,\n AdmitJoinRequest,\n AdmitJoinResponseData,\n} from './admin-types.js';\n\n/**\n * Helper: server wraps most responses in `{ data: T }`.\n * This extracts `.data` so callers get the inner payload directly. Null-safe so an\n * empty 2xx body (parsed as null) yields undefined instead of throwing.\n */\nfunction unwrap<T>(response: { data: T }): T {\n return response?.data as T;\n}\n\n/**\n * Compare two version strings by SemVer 2.0 precedence, ascending: negative if\n * `a < b`, positive if `a > b`, `0` if equal. Build metadata (`+...`) is stripped\n * and ignored. The numeric `major.minor.patch` core is compared field-by-field\n * (numerically when both parse, so `1.10.0 > 1.9.0`; a missing field is `0`). A\n * version WITH a pre-release ranks below the same core without one, and\n * pre-release identifiers compare per spec: dot-separated, numeric identifiers\n * numerically, alphanumeric lexically by ASCII, numeric below alphanumeric, and a\n * shorter set of identifiers loses when all preceding fields are equal.\n */\nexport function compareSemver(a: string, b: string): number {\n const [coreA, preA] = splitVersion(a);\n const [coreB, preB] = splitVersion(b);\n\n const na = coreA.split('.');\n const nb = coreB.split('.');\n const n = Math.max(na.length, nb.length);\n for (let i = 0; i < n; i++) {\n const c = compareSemverId(na[i] ?? '0', nb[i] ?? '0');\n if (c !== 0) return c;\n }\n\n // A pre-release ranks below the same core version with no pre-release.\n if (preA === undefined && preB === undefined) return 0;\n if (preA === undefined) return 1;\n if (preB === undefined) return -1;\n\n const pa = preA.split('.');\n const pb = preB.split('.');\n const m = Math.max(pa.length, pb.length);\n for (let i = 0; i < m; i++) {\n if (i >= pa.length) return -1; // shorter set loses when all preceding equal\n if (i >= pb.length) return 1;\n const c = compareSemverId(pa[i], pb[i]);\n if (c !== 0) return c;\n }\n return 0;\n}\n\n/** Drop build metadata and split the pre-release tail: `1.2.3-rc.1+b` -> `['1.2.3', 'rc.1']`. */\nfunction splitVersion(v: string): [string, string | undefined] {\n const core = v.split('+', 1)[0];\n const dash = core.indexOf('-');\n return dash === -1 ? [core, undefined] : [core.slice(0, dash), core.slice(dash + 1)];\n}\n\n/**\n * Compare one identifier: numerically when both are all-digits, else lexically by\n * ASCII with a numeric identifier ranking below an alphanumeric one. Fallback: a\n * non-numeric core component (loose/malformed input) is treated as a string, so\n * comparison never throws.\n */\nfunction compareSemverId(a: string, b: string): number {\n const na = /^\\d+$/.test(a);\n const nb = /^\\d+$/.test(b);\n if (na && nb) {\n const d = Number(a) - Number(b);\n return d < 0 ? -1 : d > 0 ? 1 : 0;\n }\n if (na) return -1;\n if (nb) return 1;\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/**\n * Fetch a URL from the (foreign-origin) registry with a per-attempt timeout and\n * retry on transient failures. Deliberately NOT routed through the node\n * `HttpClient`: that client attaches the node's bearer token to every request,\n * which must never leak to the registry's origin. Each attempt times out after\n * ~10s; network errors and 5xx are retried (2 retries, short backoff via the\n * shared `withRetry`), while a 4xx is a definitive answer and is not retried.\n * `kind`/`context` shape the error message so failures stay debuggable in logs.\n */\nasync function fetchRegistry(url: string, kind: string, context: string): Promise<Response> {\n return withRetry(\n async () => {\n const resp = await fetch(url, { signal: AbortSignal.timeout(10000) });\n if (!resp.ok) {\n // Carry `status` so withRetry retries 5xx but leaves 4xx to throw.\n const err = new Error(\n `registry ${kind} fetch failed (${resp.status}) for ${context}`,\n ) as Error & { status: number };\n err.status = resp.status;\n throw err;\n }\n return resp;\n },\n { attempts: 3 },\n );\n}\n\nexport class AdminApiClient {\n constructor(private httpClient: HttpClient) {}\n\n // ---- Health and Status (public, no auth) ----\n\n async healthCheck(): Promise<HealthStatus> {\n return unwrap(await this.httpClient.get<{ data: HealthStatus }>('/admin-api/health'));\n }\n\n async isAuthed(): Promise<AdminAuthStatus> {\n return this.httpClient.get<AdminAuthStatus>('/admin-api/is-authed');\n }\n\n // ---- Application Management ----\n\n async installApplication(request: InstallApplicationRequest): Promise<InstallApplicationResponseData> {\n return unwrap(await this.httpClient.post<{ data: InstallApplicationResponseData }>('/admin-api/install-application', request));\n }\n\n /**\n * Resolve a `package@version` to its registry artifact URL and install it.\n * Node install is URL-based (no node-side package+version resolution), so this\n * fetches the bundle manifest from the registry, derives the `.mpk` artifact\n * URL, then calls {@link installApplication}. `registryUrl` is the registry\n * origin. This is the discrete \"download\" step an Updates flow pairs with a\n * subsequent `upgradeGroup`.\n */\n async installFromRegistry(\n registryUrl: string,\n packageName: string,\n version: string,\n ): Promise<InstallApplicationResponseData> {\n const base = new URL(registryUrl).origin;\n const manifestUrl = new URL(\n `/api/v2/bundles/${encodeURIComponent(packageName)}/${encodeURIComponent(version)}`,\n base,\n ).toString();\n const resp = await fetchRegistry(manifestUrl, 'manifest', `${packageName}@${version}`);\n const bundle = (await resp.json()) as RegistryBundleManifest;\n // Encode the path segments \u2014 the package/version come from a (best-effort\n // trusted) registry response, so guard against odd characters breaking or\n // traversing the artifact path. For normal ids/semvers this is a no-op.\n const pkg = encodeURIComponent(bundle.package);\n const ver = encodeURIComponent(bundle.appVersion);\n const artifactUrl = `${base}/artifacts/${pkg}/${ver}/${pkg}-${ver}.mpk`;\n return this.installApplication({\n url: artifactUrl,\n package: bundle.package,\n version: bundle.appVersion,\n metadata: [],\n });\n }\n\n /**\n * List a package's published versions from the registry, newest-first by\n * semver. Reads the registry's V2 bundle listing\n * (`GET {registry}/api/v2/bundles?package={package}`), taking each bundle's\n * `appVersion`. Registry-side data \u2014 distinct from the node's\n * installed-version list \u2014 and the source an Updates view compares against\n * the running `Context.applicationVersion` to detect \"a new version exists\".\n */\n async getRegistryVersions(registryUrl: string, packageName: string): Promise<string[]> {\n const url = new URL('/api/v2/bundles', new URL(registryUrl).origin);\n url.searchParams.set('package', packageName);\n const resp = await fetchRegistry(url.toString(), 'versions', packageName);\n const bundles = (await resp.json()) as RegistryBundleManifest[];\n return (Array.isArray(bundles) ? bundles : [])\n .map((b) => b.appVersion)\n .filter((v): v is string => typeof v === 'string')\n .sort((a, b) => compareSemver(b, a));\n }\n\n async installDevApplication(request: InstallDevApplicationRequest): Promise<InstallApplicationResponseData> {\n return unwrap(await this.httpClient.post<{ data: InstallApplicationResponseData }>('/admin-api/install-dev-application', request));\n }\n\n async uninstallApplication(appId: string): Promise<UninstallApplicationResponseData> {\n return unwrap(await this.httpClient.delete<{ data: UninstallApplicationResponseData }>(`/admin-api/applications/${appId}`));\n }\n\n async listApplications(): Promise<ListApplicationsResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListApplicationsResponseData }>('/admin-api/applications'));\n }\n\n async getApplication(appId: string): Promise<GetApplicationResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetApplicationResponseData }>(`/admin-api/applications/${appId}`));\n }\n\n /**\n * Installed-blob inventory for an application \u2014 one entry per locally installed\n * version. This is the *installed* inventory (source for a \"pick a version to\n * pin\" UI); the registry equivalent is `listPackageVersions`.\n */\n async listApplicationVersions(applicationId: string): Promise<ApplicationVersionEntry[]> {\n return unwrap(\n await this.httpClient.get<{ data: ApplicationVersionEntry[] }>(`/admin-api/applications/${applicationId}/versions`),\n );\n }\n\n /**\n * The application's embedded `wasm-abi/1` manifest. Omit `serviceName` for\n * single-service apps; core 400s if the ABI is absent or the name is ambiguous.\n */\n async getApplicationAbi(applicationId: string, serviceName?: string): Promise<GetApplicationAbiResponseData> {\n const query = serviceName ? `?service_name=${encodeURIComponent(serviceName)}` : '';\n return unwrap(\n await this.httpClient.get<{ data: GetApplicationAbiResponseData }>(\n `/admin-api/applications/${applicationId}/abi${query}`,\n ),\n );\n }\n\n // ---- Package Management ----\n\n async listPackages(): Promise<ListPackagesResponseData> {\n // Core returns this flat ({ packages: [...] }), not under `data`; tolerate both.\n const r = await this.httpClient.get<ListPackagesResponseData & { data?: ListPackagesResponseData }>(\n '/admin-api/packages',\n );\n return (r?.data ?? r) as ListPackagesResponseData;\n }\n\n async listPackageVersions(packageName: string): Promise<ListVersionsResponseData> {\n // Core returns this flat ({ versions: [...] }), not under `data`; tolerate both.\n const r = await this.httpClient.get<ListVersionsResponseData & { data?: ListVersionsResponseData }>(\n `/admin-api/packages/${encodeURIComponent(packageName)}/versions`,\n );\n return (r?.data ?? r) as ListVersionsResponseData;\n }\n\n async getLatestPackageVersion(packageName: string): Promise<GetLatestVersionResponseData> {\n return this.httpClient.get<GetLatestVersionResponseData>(\n `/admin-api/packages/${encodeURIComponent(packageName)}/latest`,\n );\n }\n\n // ---- Context Management ----\n\n async createContext(request: CreateContextRequest): Promise<CreateContextResponseData> {\n // Core requires `initializationParams` (no default); default it to an empty\n // byte array so callers that pass none don't get a 400.\n const body = { ...request, initializationParams: request.initializationParams ?? [] };\n return unwrap(await this.httpClient.post<{ data: CreateContextResponseData }>('/admin-api/contexts', body));\n }\n\n async deleteContext(contextId: string, request?: DeleteContextRequest): Promise<DeleteContextResponseData> {\n if (request) {\n return unwrap(\n await this.httpClient.request<{ data: DeleteContextResponseData }>(`/admin-api/contexts/${contextId}`, {\n method: 'DELETE',\n body: JSON.stringify(request),\n headers: { 'Content-Type': 'application/json' },\n }),\n );\n }\n return unwrap(await this.httpClient.delete<{ data: DeleteContextResponseData }>(`/admin-api/contexts/${contextId}`));\n }\n\n async getContexts(): Promise<GetContextsResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextsResponseData }>('/admin-api/contexts'));\n }\n\n async getContext(contextId: string): Promise<Context> {\n return unwrap(await this.httpClient.get<{ data: Context }>(`/admin-api/contexts/${contextId}`));\n }\n\n async getContextsForApplication(applicationId: string): Promise<GetContextsResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextsResponseData }>(`/admin-api/contexts/for-application/${applicationId}`));\n }\n\n // ---- Context Identity ----\n\n async generateContextIdentity(): Promise<GenerateContextIdentityResponseData> {\n return unwrap(await this.httpClient.post<{ data: GenerateContextIdentityResponseData }>('/admin-api/identity/context', {}));\n }\n\n async getContextIdentities(contextId: string): Promise<GetContextIdentitiesResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextIdentitiesResponseData }>(`/admin-api/contexts/${contextId}/identities`));\n }\n\n async getContextIdentitiesOwned(contextId: string): Promise<GetContextIdentitiesResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextIdentitiesResponseData }>(`/admin-api/contexts/${contextId}/identities-owned`));\n }\n\n // ---- Context join (group membership) ----\n\n async joinContext(contextId: string): Promise<JoinContextResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: JoinContextResponseData }>(`/admin-api/contexts/${contextId}/join`, {}),\n );\n }\n\n // ---- Context group / storage / sync ----\n\n async getContextGroup(contextId: string): Promise<ContextGroupResponseData> {\n return unwrap(await this.httpClient.get<{ data: ContextGroupResponseData }>(`/admin-api/contexts/${contextId}/group`));\n }\n\n async getContextStorage(contextId: string): Promise<ContextStorageResponseData> {\n return unwrap(await this.httpClient.get<{ data: ContextStorageResponseData }>(`/admin-api/contexts/${contextId}/storage`));\n }\n\n async syncContext(contextId?: string): Promise<void> {\n await this.httpClient.post(`/admin-api/contexts/sync/${contextId ?? ''}`, {});\n }\n\n /**\n * Kick off a full state re-pull for a context (operator recovery for a\n * stranded context). `force` re-pulls even when the node does not flag the\n * context as stranded.\n */\n async resyncContext(\n contextId: string,\n request: ResyncContextRequest = {},\n ): Promise<ResyncContextResponseData> {\n // Core's `ResyncContextApiResponse` is a flat payload (no inner `data`\n // field), so parse the body directly \u2014 do NOT `unwrap`, or `resyncStarted`\n // reads as undefined and the resync silently appears to never start.\n const r = await this.httpClient.post<ResyncContextResponseData | null>(\n `/admin-api/contexts/${contextId}/resync`,\n request,\n );\n // An empty 2xx body means the resync was accepted; synthesize the result so\n // callers always get a typed value instead of null.\n return r ?? { contextId, resyncStarted: true };\n }\n\n async inviteSpecializedNode(request: InviteSpecializedNodeRequest): Promise<InviteSpecializedNodeResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: InviteSpecializedNodeResponseData }>(\n '/admin-api/contexts/invite-specialized-node',\n request,\n ),\n );\n }\n\n async updateContextApplication(\n contextId: string,\n request: UpdateContextApplicationRequest,\n ): Promise<void> {\n await this.httpClient.post(`/admin-api/contexts/${contextId}/application`, request);\n }\n\n async getContextsWithExecutorsForApplication(applicationId: string): Promise<ContextsWithExecutorsResponseData> {\n // Core returns this flat as { contexts: [...] } (not a bare array under `data`).\n const r = await this.httpClient.get<\n | ContextsWithExecutorsResponseData\n | { contexts: ContextsWithExecutorsResponseData }\n | { data: ContextsWithExecutorsResponseData }\n >(`/admin-api/contexts/with-executors/for-application/${applicationId}`);\n if (Array.isArray(r)) return r;\n return (\n (r as { contexts?: ContextsWithExecutorsResponseData } | null)?.contexts ??\n (r as { data?: ContextsWithExecutorsResponseData } | null)?.data ??\n []\n );\n }\n\n // ---- Blob Management ----\n\n async uploadBlob(request: UploadBlobRequest): Promise<UploadBlobResponseData> {\n // Core streams the raw request body into blob storage (no JSON) and takes\n // its params from the query string (`hash`, `context_id` \u2014 snake_case).\n const params = new URLSearchParams();\n if (request.hash) params.set('hash', request.hash);\n if (request.contextId) params.set('context_id', request.contextId);\n const query = params.toString();\n const path = query ? `/admin-api/blobs?${query}` : '/admin-api/blobs';\n // request.data (Uint8Array view | ArrayBuffer | Blob) is a valid BodyInit and\n // is streamed verbatim \u2014 no JSON, no cast. fetch honors a Uint8Array view's\n // byteOffset/byteLength, so subarrays upload the correct region.\n // Core's BlobInfo is snake_case (`blob_id`); map to camelCase like deleteBlob.\n const res = unwrap(\n await this.httpClient.request<{ data: { blob_id: string; size: number } }>(path, {\n method: 'PUT',\n body: request.data,\n headers: { 'Content-Type': 'application/octet-stream' },\n }),\n );\n return { blobId: res.blob_id, size: res.size };\n }\n\n async deleteBlob(blobId: string): Promise<DeleteBlobResponseData> {\n // Core's `BlobDeleteResponse` is a flat, snake_case payload (`{ blob_id,\n // deleted }`) \u2014 the lone admin DTO without a camelCase rename and without an\n // inner `data` field. Parse directly (no `unwrap`) and map to camelCase.\n const body = await this.httpClient.delete<{ blob_id: string; deleted: boolean }>(\n `/admin-api/blobs/${blobId}`,\n );\n return { blobId: body.blob_id, deleted: body.deleted };\n }\n\n async listBlobs(): Promise<ListBlobsResponseData> {\n // Core's BlobInfo is snake_case (`blob_id`); map to camelCase.\n const res = unwrap(\n await this.httpClient.get<{ data: { blobs: Array<{ blob_id: string; size: number }> } }>(\n '/admin-api/blobs',\n ),\n );\n return { blobs: res.blobs.map((b) => ({ blobId: b.blob_id, size: b.size })) };\n }\n\n /**\n * Download a blob's raw bytes. `GET /admin-api/blobs/:id` streams the blob\n * content (e.g. `application/gzip`), NOT JSON \u2014 so fetch it as an ArrayBuffer.\n * Use {@link listBlobs} for `{ blobId, size }` metadata.\n */\n async getBlob(blobId: string): Promise<ArrayBuffer> {\n return this.httpClient.get<ArrayBuffer>(`/admin-api/blobs/${blobId}`, {\n parse: 'arrayBuffer',\n });\n }\n\n /**\n * Fetch a blob's metadata without downloading it. `HEAD /admin-api/blobs/:id`\n * returns the info in response headers (size via `content-length`, plus\n * `x-blob-id`/`x-blob-hash`/`x-blob-mime-type`).\n */\n async getBlobInfo(blobId: string): Promise<GetBlobInfoResponseData> {\n // HEAD throws (HttpError) on a non-2xx status, so we only reach here on success\n // \u2014 the x-blob-* headers are present. Guard size against a missing/non-numeric\n // content-length anyway (defaults to 0 rather than NaN).\n const { headers } = await this.httpClient.head(`/admin-api/blobs/${blobId}`);\n const size = Number(headers['content-length']);\n return {\n blobId: headers['x-blob-id'] ?? blobId,\n size: Number.isFinite(size) ? size : 0,\n hash: headers['x-blob-hash'],\n mimeType: headers['x-blob-mime-type'],\n };\n }\n\n // ---- Alias Management ----\n\n async createContextAlias(\n request: CreateContextAliasRequest,\n ): Promise<CreateAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateAliasResponseData }>(\n '/admin-api/alias/create/context',\n { alias: request.alias, contextId: request.contextId },\n ),\n );\n }\n\n async createApplicationAlias(\n request: CreateApplicationAliasRequest,\n ): Promise<CreateAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateAliasResponseData }>(\n '/admin-api/alias/create/application',\n { alias: request.alias, applicationId: request.applicationId },\n ),\n );\n }\n\n async lookupContextAlias(name: string): Promise<LookupAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: LookupAliasResponseData }>(\n `/admin-api/alias/lookup/context/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async lookupApplicationAlias(name: string): Promise<LookupAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: LookupAliasResponseData }>(\n `/admin-api/alias/lookup/application/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async deleteContextAlias(name: string): Promise<DeleteAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: DeleteAliasResponseData }>(\n `/admin-api/alias/delete/context/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async deleteApplicationAlias(name: string): Promise<DeleteAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: DeleteAliasResponseData }>(\n `/admin-api/alias/delete/application/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async listContextAliases(): Promise<ListAliasesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListAliasesResponseData }>('/admin-api/alias/list/context'));\n }\n\n async listApplicationAliases(): Promise<ListAliasesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListAliasesResponseData }>('/admin-api/alias/list/application'));\n }\n\n // ---- Namespace Management ----\n\n async listNamespaces(): Promise<ListNamespacesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListNamespacesResponseData }>('/admin-api/namespaces'));\n }\n\n async getNamespace(namespaceId: string): Promise<Namespace> {\n return unwrap(await this.httpClient.get<{ data: Namespace }>(`/admin-api/namespaces/${namespaceId}`));\n }\n\n /**\n * Who this node is \u2014 the account it writes as, the device it is, the key it\n * signs with, and the account root a second device pairs against.\n *\n * Takes no namespace, and that is the point: one root key is one account\n * everywhere, and a node signs with one key, so none of it varies by\n * namespace.\n */\n async getNodeIdentity(): Promise<NodeIdentity> {\n return unwrap(await this.httpClient.get<{ data: NodeIdentity }>('/admin-api/identity'));\n }\n\n /**\n * @deprecated Use {@link getNodeIdentity} instead. Every field this returns is\n * node-level, so the namespace was only ever decoration \u2014 it now delegates to\n * the node-level route and reshapes the answer.\n *\n * Three consequences of that delegation, all visible to a caller who relied on\n * the old route's behaviour:\n *\n * - **No participation gate.** The namespace route answered 404 when this node\n * had never joined the namespace; this answers whatever the node's identity\n * is, regardless. If you were using it to ask \"am I in this namespace?\", ask\n * {@link listNamespaces} instead \u2014 that is the question you were really\n * asking.\n * - **`namespaceId` is echoed verbatim.** The old route resolved a subgroup id\n * to its root namespace and returned that; passing a subgroup id here gives\n * the subgroup id back.\n * - **404 means something else.** Previously \"not my namespace\", now \"this node\n * holds no account root yet\".\n */\n async getNamespaceIdentity(namespaceId: string): Promise<NamespaceIdentity> {\n const node = await this.getNodeIdentity();\n return { namespaceId, publicKey: node.publicKey, account: node.accountId };\n }\n\n /**\n * Ask this node to run one method on a member's behalf, under a warrant that\n * member signed.\n *\n * The node executes and signs the envelope with its own key; the change is\n * attributed to the **author**. Both halves travel together, so every peer\n * re-checks that the member consented instead of trusting the relay.\n *\n * Three things have to be true first, and none is implied by the others:\n *\n * - the author's **account** is a member of the group owning the context \u2014\n * their device joins nothing and is in no group's binding rows, which is\n * exactly the case a device certificate covers;\n * - this node holds `CAN_AUTHOR_ON_BEHALF` on that group, which is implied by\n * neither membership nor admin;\n * - the warrant has not been spent. It is single-use: presenting a valid one\n * twice is refused, because the signature stays valid forever and replay is\n * not forgery.\n *\n * A refusal comes back as a `403` carrying the reason \u2014 \"an admin must grant\n * CAN_AUTHOR_ON_BEHALF to \u2026\", or that the nonce is already spent \u2014 so a caller\n * can tell which precondition failed rather than only that one did.\n *\n * Mint the warrant with {@link signWarrant}; see\n * {@link PerformIntentRequest.warrant}.\n */\n async performIntent(\n contextId: string,\n request: PerformIntentRequest,\n ): Promise<PerformIntentResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: PerformIntentResponseData }>(\n `/admin-api/contexts/${contextId}/intents`,\n request,\n ),\n );\n }\n\n async listNamespacesForApplication(applicationId: string): Promise<ListNamespacesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListNamespacesResponseData }>(`/admin-api/namespaces/for-application/${applicationId}`));\n }\n\n async createNamespace(request: CreateNamespaceRequest): Promise<CreateNamespaceResponseData> {\n // `upgradePolicy` is sent even though the request type no longer carries it.\n //\n // The concept was deleted server-side (calimero-network/core#3393), but only\n // on master: every RELEASED node still declares the field required and\n // rejects a body without it \u2014 `missing field 'upgradePolicy'`. A node that\n // has dropped it ignores the extra key, so sending it is the one shape that\n // works against both, and this SDK does not get to choose which node a\n // caller points it at.\n //\n // `LazyOnAccess` because it was the default and is the only behaviour that\n // survives the removal, so an old node given it does what a new one does.\n //\n // Remove once no supported release predates that change.\n return unwrap(\n await this.httpClient.post<{ data: CreateNamespaceResponseData }>('/admin-api/namespaces', {\n upgradePolicy: 'LazyOnAccess',\n ...request,\n }),\n );\n }\n\n async deleteNamespace(\n namespaceId: string,\n request?: DeleteNamespaceRequest,\n ): Promise<DeleteNamespaceResponseData> {\n // Core requires `Content-Type: application/json` on this DELETE even when the\n // body is empty, so always send the header and a (possibly empty) JSON body.\n return unwrap(\n await this.httpClient.request<{ data: DeleteNamespaceResponseData }>(`/admin-api/namespaces/${namespaceId}`, {\n method: 'DELETE',\n body: JSON.stringify(request ?? {}),\n headers: { 'Content-Type': 'application/json' },\n }),\n );\n }\n\n async createNamespaceInvitation(\n namespaceId: string,\n request?: CreateNamespaceInvitationRequest,\n ): Promise<CreateNamespaceInvitationResponseData | CreateRecursiveInvitationResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateNamespaceInvitationResponseData | CreateRecursiveInvitationResponseData }>(\n `/admin-api/namespaces/${namespaceId}/invite`,\n request ?? {},\n ),\n );\n }\n\n /**\n * Present a join this caller signed to a node the inviter named as an\n * admitter.\n *\n * For a member with no node. `joinNamespace` publishes the membership op from\n * the node making the call; this hands an already-signed op to somebody else's\n * node to publish. The distinction matters because a keyholder has nowhere to\n * publish from.\n *\n * The op must be signed by the **device key** in the credential it carries \u2014\n * every peer checks that when applying a join. So the admitter cannot author\n * this, only carry it: a hostile one can refuse, and nothing else. It cannot\n * admit a different account, change the group, or grant a role.\n *\n * @param namespaceId the namespace being joined, 64 hex\n * @param request the invitation and the hex-encoded signed op\n */\n async admitJoin(\n namespaceId: string,\n request: AdmitJoinRequest,\n ): Promise<AdmitJoinResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: AdmitJoinResponseData }>(\n `/admin-api/namespaces/${namespaceId}/admit`,\n request,\n { timeoutMs: 65000 },\n ),\n );\n }\n\n async joinNamespace(\n namespaceId: string,\n request: JoinNamespaceRequest,\n ): Promise<JoinNamespaceResponseData> {\n const data = unwrap(\n await this.httpClient.post<{ data: JoinNamespaceResponseData }>(\n `/admin-api/namespaces/${namespaceId}/join`,\n request,\n { timeoutMs: 65000 },\n ),\n );\n\n // core 0.11.0-rc.25 renamed this response's `groupId` to `namespaceId`\n // (core#3598). Bind whichever spelling the node actually sent rather than\n // picking one: the rename lands as `undefined` on the field the client\n // reads, and nothing errors \u2014 no 4xx, no thrown parse \u2014 so a client that\n // knows only one spelling fails much later and somewhere else. Normalising\n // here means one mero-js works against nodes either side of that release.\n if (data && data.namespaceId === undefined && data.groupId !== undefined) {\n return { ...data, namespaceId: data.groupId };\n }\n return data;\n }\n\n async createGroupInNamespace(\n namespaceId: string,\n request?: CreateGroupInNamespaceRequest,\n ): Promise<CreateGroupInNamespaceResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateGroupInNamespaceResponseData }>(\n `/admin-api/namespaces/${namespaceId}/groups`,\n request ?? {},\n ),\n );\n }\n\n async listNamespaceGroups(namespaceId: string): Promise<SubgroupEntry[]> {\n return unwrap(await this.httpClient.get<{ data: SubgroupEntry[] }>(`/admin-api/namespaces/${namespaceId}/groups`));\n }\n\n // ---- Group Management ----\n\n async getGroupInfo(groupId: string): Promise<GroupInfoResponseData> {\n return unwrap(await this.httpClient.get<{ data: GroupInfoResponseData }>(`/admin-api/groups/${groupId}`));\n }\n\n /** Thin wrapper over {@link getGroupInfo}: returns the group's `defaultCapabilities` bitmask. */\n async getDefaultCapabilities(groupId: string): Promise<number> {\n return (await this.getGroupInfo(groupId)).defaultCapabilities;\n }\n\n /** Thin wrapper over {@link getGroupInfo}: returns the group's `subgroupVisibility`. */\n async getSubgroupVisibility(groupId: string): Promise<string> {\n return (await this.getGroupInfo(groupId)).subgroupVisibility;\n }\n\n async deleteGroup(groupId: string, request?: DeleteGroupRequest): Promise<DeleteGroupResponseData> {\n // Core requires `Content-Type: application/json` on this DELETE even with an\n // empty body, so always send the header and a (possibly empty) JSON body.\n return unwrap(\n await this.httpClient.request<{ data: DeleteGroupResponseData }>(`/admin-api/groups/${groupId}`, {\n method: 'DELETE',\n body: JSON.stringify(request ?? {}),\n headers: { 'Content-Type': 'application/json' },\n }),\n );\n }\n\n async listGroupMembers(groupId: string): Promise<ListGroupMembersResponseData> {\n const response = await this.httpClient.get<ListGroupMembersResponseData>(\n `/admin-api/groups/${groupId}/members`,\n );\n // Validate the field we declare as non-optional in the type so a\n // contract-violating response (proxy error body, future API drift,\n // etc.) surfaces as a clear error rather than silently producing an\n // empty list. Empty groups still satisfy this \u2014 merod returns\n // `members: []`, not an omitted field.\n if (!Array.isArray(response?.members)) {\n // Sanitize before interpolation: groupId reaches us from caller code,\n // not parsed input, but defending the message keeps untrusted bytes\n // out of error logs and downstream UIs.\n const safeId = String(groupId).replace(/[\\r\\n\\t\\s]/g, '').slice(0, 64);\n throw new Error(\n `Invalid listGroupMembers response for group ${safeId}: missing or non-array \\`members\\` field`,\n );\n }\n return response;\n }\n\n async listGroupContexts(groupId: string): Promise<ListGroupContextsResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListGroupContextsResponseData }>(`/admin-api/groups/${groupId}/contexts`));\n }\n\n async addGroupMembers(groupId: string, request: AddGroupMembersRequest): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/members`, request);\n }\n\n async removeGroupMembers(groupId: string, request: RemoveGroupMembersRequest): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/members/remove`, request);\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async updateMemberRole(\n groupId: string,\n identity: string,\n request: UpdateMemberRoleRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/role`, request);\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async getMemberCapabilities(groupId: string, identity: string): Promise<MemberCapabilities> {\n return unwrap(\n await this.httpClient.get<{ data: MemberCapabilities }>(\n `/admin-api/groups/${groupId}/members/${identity}/capabilities`,\n ),\n );\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async setMemberCapabilities(\n groupId: string,\n identity: string,\n request: SetMemberCapabilitiesRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/capabilities`, request);\n }\n\n async setDefaultCapabilities(\n groupId: string,\n request: SetDefaultCapabilitiesRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/settings/default-capabilities`, request);\n }\n\n async setSubgroupVisibility(\n groupId: string,\n request: SetSubgroupVisibilityRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/settings/subgroup-visibility`, request);\n }\n\n async setTeeAdmissionPolicy(\n groupId: string,\n request: SetTeeAdmissionPolicyRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/settings/tee-admission-policy`, request);\n }\n\n async getTeeAdmissionPolicy(groupId: string): Promise<GetTeeAdmissionPolicyResponseData> {\n // Intersection (not union) so the type is unambiguous: `data` is optional, so\n // `?? response` cleanly falls back to a flat (un-enveloped) response.\n const response = await this.httpClient.get<\n GetTeeAdmissionPolicyResponseData & { data?: GetTeeAdmissionPolicyResponseData }\n >(`/admin-api/groups/${groupId}/settings/tee-admission-policy`);\n return response.data ?? response;\n }\n\n // ---- Group / member / context metadata ----\n\n async setGroupMetadata(groupId: string, request: SetGroupMetadataRequest): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/metadata`, request);\n }\n\n async getGroupMetadata(groupId: string): Promise<MetadataRecord | null> {\n // Core single-envelopes the record: `{ data: MetadataRecord | null }`.\n // \"No record yet\" is `{ data: null }` (or a bare null body on older nodes),\n // so optional-chain to a clean null. Returns the full record (name + data +\n // updatedAt/updatedBy), not just the data map.\n const response = await this.httpClient.get<GetMetadataResponseData | null>(\n `/admin-api/groups/${groupId}/metadata`,\n );\n return response?.data ?? null;\n }\n\n async setMemberMetadata(\n groupId: string,\n identity: string,\n request: SetMemberMetadataRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/metadata`, request);\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async getMemberMetadata(groupId: string, identity: string): Promise<MetadataRecord | null> {\n // Single-enveloped record; see getGroupMetadata.\n const response = await this.httpClient.get<GetMetadataResponseData | null>(\n `/admin-api/groups/${groupId}/members/${identity}/metadata`,\n );\n return response?.data ?? null;\n }\n\n async setContextMetadata(\n groupId: string,\n contextId: string,\n request: SetContextMetadataRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/contexts/${contextId}/metadata`, request);\n }\n\n async getContextMetadata(groupId: string, contextId: string): Promise<MetadataRecord | null> {\n // Single-enveloped record; see getGroupMetadata.\n const response = await this.httpClient.get<GetMetadataResponseData | null>(\n `/admin-api/groups/${groupId}/contexts/${contextId}/metadata`,\n );\n return response?.data ?? null;\n }\n\n async syncGroup(groupId: string, request?: SyncGroupRequest): Promise<SyncGroupResponseData> {\n return unwrap(await this.httpClient.post<{ data: SyncGroupResponseData }>(`/admin-api/groups/${groupId}/sync`, request ?? {}));\n }\n\n async upgradeGroup(groupId: string, request: UpgradeGroupRequest): Promise<UpgradeGroupResponseData> {\n return unwrap(await this.httpClient.post<{ data: UpgradeGroupResponseData }>(`/admin-api/groups/${groupId}/upgrade`, request));\n }\n\n async getGroupUpgradeStatus(groupId: string): Promise<GroupUpgradeStatusResponseData> {\n return unwrap(\n await this.httpClient.get<{ data: GroupUpgradeStatusResponseData }>(`/admin-api/groups/${groupId}/upgrade/status`),\n );\n }\n\n /**\n * The operator-facing \"have all peers migrated?\" rollup for a namespace.\n * The handler serializes the payload directly, so there is no `{ data }`\n * envelope to unwrap here (unlike most admin reads).\n */\n async getMigrationStatus(namespaceId: string): Promise<MigrationStatus> {\n const id = encodeURIComponent(namespaceId);\n return this.httpClient.get<MigrationStatus>(`/admin-api/groups/${id}/migration-status`);\n }\n\n /** Per-group cascade-migration snapshots for a namespace. */\n async getCascadeStatus(namespaceId: string): Promise<CascadeStatusEntry[]> {\n const id = encodeURIComponent(namespaceId);\n return unwrap(\n await this.httpClient.get<{ data: CascadeStatusEntry[] }>(`/admin-api/groups/${id}/cascade-status`),\n );\n }\n\n async retryGroupUpgrade(\n groupId: string,\n request?: RetryGroupUpgradeRequest,\n ): Promise<RetryGroupUpgradeResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: RetryGroupUpgradeResponseData }>(\n `/admin-api/groups/${groupId}/upgrade/retry`,\n request ?? {},\n ),\n );\n }\n\n /** Move `childGroupId` under `request.newParentId`. */\n async reparentGroup(\n childGroupId: string,\n request: ReparentGroupRequest,\n ): Promise<ReparentGroupResponseData> {\n // Core returns this flat ({ reparented }); tolerate the { data } envelope too.\n const r = await this.httpClient.post<\n ReparentGroupResponseData & { data?: ReparentGroupResponseData }\n >(`/admin-api/groups/${childGroupId}/reparent`, request);\n return (r?.data ?? r) as ReparentGroupResponseData;\n }\n\n async listSubgroups(groupId: string): Promise<SubgroupEntry[]> {\n const response = await this.httpClient.get<{ subgroups?: SubgroupEntry[]; data?: SubgroupEntry[] }>(\n `/admin-api/groups/${groupId}/subgroups`,\n );\n return response.subgroups ?? response.data ?? [];\n }\n\n async detachContextFromGroup(\n groupId: string,\n contextId: string,\n request?: DetachContextFromGroupRequest,\n ): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/contexts/${contextId}/remove`, request ?? {});\n }\n\n // ---- Group Invitation & Join ----\n\n async createGroupInvitation(\n groupId: string,\n request?: CreateGroupInvitationRequest,\n ): Promise<CreateGroupInvitationResponseData | CreateRecursiveGroupInvitationResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateGroupInvitationResponseData | CreateRecursiveGroupInvitationResponseData }>(\n `/admin-api/groups/${groupId}/invite`,\n request ?? {},\n ),\n );\n }\n\n async joinGroup(request: JoinGroupRequest): Promise<JoinGroupResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: JoinGroupResponseData }>('/admin-api/groups/join', request),\n );\n }\n\n async joinSubgroupInheritance(groupId: string): Promise<JoinSubgroupInheritanceResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: JoinSubgroupInheritanceResponseData }>(\n `/admin-api/groups/${groupId}/join-via-inheritance`,\n {},\n ),\n );\n }\n\n // ---- TEE ----\n\n async getTeeInfo(): Promise<TeeInfoResponseData> {\n return unwrap(await this.httpClient.get<{ data: TeeInfoResponseData }>('/admin-api/tee/info'));\n }\n\n async teeAttest(request: TeeAttestRequest): Promise<TeeAttestResponseData> {\n return unwrap(await this.httpClient.post<{ data: TeeAttestResponseData }>('/admin-api/tee/attest', request));\n }\n\n async teeVerifyQuote(request: TeeVerifyQuoteRequest): Promise<TeeVerifyQuoteResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: TeeVerifyQuoteResponseData }>('/admin-api/tee/verify-quote', request),\n );\n }\n\n // ---- Network ----\n\n async getPeersCount(): Promise<{ count: number }> {\n return this.httpClient.get<{ count: number }>('/admin-api/peers');\n }\n\n /** Node network status (GET /admin-api/network/status). */\n async getNetworkStatus(): Promise<unknown> {\n return this.httpClient.get<unknown>('/admin-api/network/status');\n }\n\n /** Node storage/usage stats (GET /admin-api/usage). */\n async getUsage(): Promise<unknown> {\n return this.httpClient.get<unknown>('/admin-api/usage');\n }\n\n /** Node TLS certificate, PEM text (GET /admin-api/certificate). */\n async getCertificate(): Promise<string> {\n return this.httpClient.get<string>('/admin-api/certificate', { parse: 'text' });\n }\n\n // ---- Group / context / namespace membership ----\n\n /** Create a standalone group (POST /admin-api/groups). */\n async createGroup(request: Record<string, unknown>): Promise<{ groupId: string }> {\n // `upgradePolicy` for the same reason as `createNamespace` above \u2014 these are\n // the only two requests a released node still requires it on, and it ignores\n // the extra key once the concept is gone. Spread after the caller's request\n // so an explicit value wins.\n return unwrap(\n await this.httpClient.post<{ data: { groupId: string } }>('/admin-api/groups', {\n upgradePolicy: 'LazyOnAccess',\n ...request,\n }),\n );\n }\n\n /** Leave a group (POST /admin-api/groups/:group_id/leave). */\n async leaveGroup(groupId: string, request?: Record<string, unknown>): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/leave`, request ?? {});\n }\n\n /** Leave a context (POST /admin-api/contexts/:context_id/leave). */\n async leaveContext(contextId: string, request?: Record<string, unknown>): Promise<void> {\n await this.httpClient.post(`/admin-api/contexts/${contextId}/leave`, request ?? {});\n }\n\n /** Leave a namespace (POST /admin-api/namespaces/:namespace_id/leave). */\n async leaveNamespace(namespaceId: string, request?: Record<string, unknown>): Promise<void> {\n await this.httpClient.post(`/admin-api/namespaces/${namespaceId}/leave`, request ?? {});\n }\n\n /** Issue a group ownership proof (POST /admin-api/groups/:group_id/issue-ownership-proof). */\n async issueOwnershipProof(groupId: string, request?: Record<string, unknown>): Promise<unknown> {\n return this.httpClient.post<unknown>(`/admin-api/groups/${groupId}/issue-ownership-proof`, request ?? {});\n }\n\n /** Issue a namespace ownership proof (POST /admin-api/groups/:group_id/issue-namespace-ownership-proof). */\n async issueNamespaceOwnershipProof(groupId: string, request?: Record<string, unknown>): Promise<unknown> {\n return this.httpClient.post<unknown>(\n `/admin-api/groups/${groupId}/issue-namespace-ownership-proof`,\n request ?? {},\n );\n }\n\n /**\n * Set a member's auto-follow flag (PUT\n * /admin-api/groups/:group_id/members/:identity/auto-follow).\n *\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async setMemberAutoFollow(\n groupId: string,\n identity: string,\n request: Record<string, unknown>,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/auto-follow`, request);\n }\n\n /** Abort a namespace migration (POST /admin-api/groups/:namespace_id/migration/abort). */\n async abortMigration(namespaceId: string, request?: Record<string, unknown>): Promise<unknown> {\n return this.httpClient.post<unknown>(\n `/admin-api/groups/${namespaceId}/migration/abort`,\n request ?? {},\n );\n }\n}\n", "import { AdminApiClient } from './admin-client.js';\nimport { AdminApiClientConfig } from './admin-types.js';\nimport {\n HttpClient,\n createBrowserHttpClient,\n createNodeHttpClient,\n createUniversalHttpClient,\n} from '../http-client/index.js';\n\n// Factory functions for creating Admin API clients\n\n/** Admin client over a browser HTTP transport (global `fetch`). */\nexport function createBrowserAdminApiClient(\n config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(createBrowserHttpClient(config));\n}\n\n/** Admin client over a Node HTTP transport (Node 18+ `fetch`). */\nexport function createNodeAdminApiClient(\n config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(createNodeHttpClient(config));\n}\n\n/** Admin client over whichever transport suits the current runtime. */\nexport function createAdminApiClient(\n config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(createUniversalHttpClient(config));\n}\n\n/**\n * Admin client over a caller-supplied HTTP client \u2014 use this to share one\n * transport (and its token handling) with the other API clients.\n */\nexport function createAdminApiClientFromHttpClient(\n httpClient: HttpClient,\n _config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(httpClient);\n}\n", "export interface AuthCallbackResult {\n accessToken: string;\n refreshToken: string;\n applicationId: string;\n contextId: string;\n contextIdentity: string;\n nodeUrl: string;\n}\n\nexport interface AuthLoginOptions {\n callbackUrl: string;\n packageName?: string;\n mode: string;\n permissions?: string[];\n registryUrl?: string;\n packageVersion?: string;\n}\n\n/**\n * Parse an auth callback URL hash fragment.\n * Returns null if access_token is missing.\n */\nexport function parseAuthCallback(url: string): AuthCallbackResult | null {\n try {\n const hashIndex = url.indexOf('#');\n if (hashIndex === -1) return null;\n\n const hash = url.substring(hashIndex + 1);\n const params = new URLSearchParams(hash);\n\n const accessToken = params.get('access_token');\n if (!accessToken) return null;\n\n return {\n accessToken,\n refreshToken: params.get('refresh_token') ?? '',\n applicationId: params.get('application_id') ?? '',\n contextId: params.get('context_id') ?? '',\n contextIdentity: params.get('context_identity') ?? '',\n nodeUrl: params.get('node_url') ?? '',\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Build the auth login URL for redirecting users to the node's auth page.\n */\nexport function buildAuthLoginUrl(nodeUrl: string, opts: AuthLoginOptions): string {\n const params = new URLSearchParams();\n params.set('callback-url', opts.callbackUrl);\n\n if (opts.permissions && opts.permissions.length > 0) {\n params.set('permissions', opts.permissions.join(','));\n }\n\n params.set('mode', opts.mode);\n\n if (opts.packageName) {\n params.set('package-name', opts.packageName);\n if (opts.packageVersion) {\n params.set('package-version', opts.packageVersion);\n }\n if (opts.registryUrl) {\n params.set('registry-url', opts.registryUrl);\n }\n }\n\n // Trim trailing slash from nodeUrl\n const base = nodeUrl.replace(/\\/+$/, '');\n return `${base}/auth/login?${params.toString()}`;\n}\n", "import type { HttpClient } from '../http-client/index.js';\n\n/** Result of the owner-driven `migrate_my_entries` convert (counts are u32). */\nexport interface MigrateMyEntriesSummary {\n converted: number;\n remaining: number;\n}\n\nexport interface ExecuteParams {\n contextId: string;\n method: string;\n argsJson?: Record<string, unknown>;\n /** @deprecated No longer used by the server. Ignored if provided. */\n executorPublicKey?: string;\n}\n\nexport class RpcError extends Error {\n code: number;\n type?: string;\n data?: unknown;\n\n constructor(code: number, message: string, data?: unknown, type?: string) {\n super(message);\n this.name = 'RpcError';\n this.code = code;\n this.data = data;\n this.type = type;\n }\n}\n\ninterface JsonRpcResponse {\n jsonrpc: string;\n id: number;\n result?: {\n output?: unknown;\n [key: string]: unknown;\n };\n error?: {\n // Standard JSON-RPC fields\n code?: number;\n message?: string;\n // Server-specific fields\n type?: string;\n data?: unknown;\n };\n}\n\n/**\n * POST a JSON-RPC call and unwrap `result`, converting an `error` payload into\n * an `RpcError`. The node returns `{ type, data }` (not always `{ code,\n * message }`), so this is the one place that normalization lives \u2014 every\n * JSON-RPC caller in this SDK shares it rather than re-deriving a bare\n * `Error(message)` and dropping the typed detail.\n */\nexport async function jsonRpcCall<T>(\n httpClient: HttpClient,\n method: string,\n params: unknown,\n): Promise<T> {\n const response = await httpClient.post<JsonRpcResponse>('/jsonrpc', {\n jsonrpc: '2.0',\n id: 1,\n method,\n params,\n });\n\n if (response.error) {\n const err = response.error;\n throw new RpcError(err.code ?? -1, err.message ?? err.type ?? 'RPC error', err.data, err.type);\n }\n\n return response.result as T;\n}\n\nexport class RpcClient {\n private httpClient: HttpClient;\n\n constructor(opts: { httpClient: HttpClient }) {\n this.httpClient = opts.httpClient;\n }\n\n async execute<T = unknown>(params: ExecuteParams): Promise<T> {\n const result = await jsonRpcCall<JsonRpcResponse['result']>(this.httpClient, 'execute', {\n contextId: params.contextId,\n method: params.method,\n argsJson: params.argsJson ?? {},\n });\n\n if (result && 'output' in result) {\n return result.output as T;\n }\n\n return result as T;\n }\n\n /**\n * One-tap owner-driven convert: re-signs the caller's identity-gated entries\n * to the current schema. The export converts all of the caller's\n * below-target entries in a single sweep, so this issues one call and returns\n * the resulting summary \u2014 it does not loop.\n */\n async migrateMyEntries(contextId: string): Promise<MigrateMyEntriesSummary> {\n return this.execute<MigrateMyEntriesSummary>({ contextId, method: 'migrate_my_entries' });\n }\n\n /** Read-only count of the caller's entries still below the target schema. */\n async countMyPending(contextId: string): Promise<number> {\n return this.execute<number>({ contextId, method: 'count_my_pending' });\n }\n}\n", "/** Parsed group-membership event (core's untagged `NodeEvent` group variant). */\nexport interface GroupMembershipEventData {\n groupId: string;\n type: 'MemberJoined' | 'MemberAdded' | 'MemberRemoved';\n data: {\n /** The member's ACCOUNT, hex-encoded 32 bytes (64 chars) - the principal the\n * governance rows name. Not a signing key: the field this replaced\n * carried one, and both are strings, so the rename is what makes a stale\n * consumer fail loudly instead of comparing accounts against keys forever. */\n memberAccount: string;\n /** Absent on `MemberRemoved`, and on a `MemberJoined` inherited from an Open\n * subgroup. Core's set is closed. */\n role?: 'Admin' | 'Member' | 'ReadOnly' | 'ReadOnlyTee';\n };\n}\n\n/**\n * A migration was accepted and its target ABI state version resolved.\n * `toStateVersion` is the `#[app::state(version = N)]` number, not the bundle\n * semver (`toVersion`).\n */\nexport interface MigrationStartedData {\n fromVersion: string;\n toVersion: string;\n toStateVersion: number;\n /** Contexts the EMITTING NODE enumerated for the migration. Node-local, never\n * the fleet cohort size that `MigrationProgressData.total` carries. */\n localContextsTotal: number;\n}\n\n/**\n * Fleet rollup counters, recomputed as peers' heartbeat facts change. Counters\n * only: the per-member detail behind them stays in the admin-gated\n * `getMigrationStatus` read.\n */\nexport interface MigrationProgressData {\n migrated: number;\n inProgress: number;\n unknown: number;\n failed: number;\n /** The pinned FLEET COHORT size, never a node-local context count like\n * `MigrationStartedData.localContextsTotal`. */\n total: number;\n}\n\n/**\n * One subgroup's local context swaps advanced on the emitting node.\n *\n * Admin-only: it names a descendant subgroup, which a plain namespace member\n * may not enumerate, so core withholds it from non-admin subscribers. A\n * non-admin never receiving this variant is correct behaviour, not a gap.\n */\nexport interface CascadeProgressData {\n /** Hex-encoded descendant subgroup id, never the namespace root the event is\n * keyed on. */\n subgroupId: string;\n localContextsSwapped: number;\n /** Contexts the emitting node holds for THIS SUBGROUP. Node-local and\n * per-subgroup; unrelated to both sibling totals. */\n localContextsTotal: number;\n}\n\n/** Every pinned-cohort member reported the target version. */\nexport interface MigrationCompletedData {\n toVersion: string;\n /** FLEET convergence, in seconds since the epoch: the same stamp\n * `MigrationStatus.fleetCompletedAt` returns. Not `GroupUpgradeStatus.completedAt`,\n * which is this node's own local swap completion. */\n completedAt: number;\n}\n\n/**\n * Parsed group-migration event (core's `GroupMigration` `NodeEvent` variant),\n * keyed on the namespace root a client subscribes with.\n *\n * `MigrationStarted`, `MigrationProgress` and `MigrationCompleted` reach every\n * subscribed member; `CascadeProgress` reaches namespace admins only.\n */\nexport type GroupMigrationEventData =\n | { groupId: string; type: 'MigrationStarted'; data: MigrationStartedData }\n | { groupId: string; type: 'MigrationProgress'; data: MigrationProgressData }\n | { groupId: string; type: 'CascadeProgress'; data: CascadeProgressData }\n | { groupId: string; type: 'MigrationCompleted'; data: MigrationCompletedData };\n\nconst MIGRATION_EVENT_TYPES: ReadonlySet<string> = new Set([\n 'MigrationStarted',\n 'MigrationProgress',\n 'CascadeProgress',\n 'MigrationCompleted',\n]);\n\n/** Narrows a raw `'event'` payload to the group-migration family by its tag. */\nexport function isGroupMigrationEvent(\n event: { type?: string },\n): event is GroupMigrationEventData {\n return event.type !== undefined && MIGRATION_EVENT_TYPES.has(event.type);\n}\n", "import type { GroupMembershipEventData, GroupMigrationEventData } from './group.js';\nimport { isGroupMigrationEvent } from './group.js';\nimport { AuthRevokedError, HTTPError } from '../http-client/index.js';\n\n/**\n * `x-auth-error` reasons that mean the whole token family is gone, mirroring\n * the request path in `web-client.ts`. Anything else \u2014 `token_expired` above\n * all \u2014 is recoverable by refreshing and reconnecting.\n */\nconst TERMINAL_AUTH_ERRORS = new Set(['token_reuse', 'token_revoked']);\n\nexport type { GroupMembershipEventData, GroupMigrationEventData };\n\nexport interface SseEventData {\n contextId: string;\n /** The context-event discriminator (core serializes it as a sibling of\n * `data`, e.g. `\"AppVersionChanged\"`). Undefined for events without a tag. */\n type?: string;\n data: unknown;\n}\n\n/** Parsed `AppVersionChanged` context event (bundle-version flip; skew #2). */\nexport interface AppVersionChangedEvent {\n contextId: string;\n fromVersion?: string;\n toVersion?: string;\n}\n\n/** Anything the `'event'` stream can deliver: context events plus the\n * group-keyed membership and migration families. */\ntype SseEvent = SseEventData | GroupMembershipEventData | GroupMigrationEventData;\ntype SseEventHandler = (event: SseEvent) => void;\ntype SseConnectHandler = (sessionId: string) => void;\ntype SseErrorHandler = (error: Error) => void;\n\ninterface SseListeners {\n connect: SseConnectHandler[];\n event: SseEventHandler[];\n error: SseErrorHandler[];\n}\n\nexport class SseClient {\n private baseUrl: string;\n private getAuthToken: () => Promise<string>;\n private reconnectDelayMs: number;\n private sessionId: string | null = null;\n private abortController: AbortController | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private subscribedContextIds: Set<string> = new Set();\n private subscribedGroupIds: Set<string> = new Set();\n private closed = false;\n private listeners: SseListeners = { connect: [], event: [], error: [] };\n\n constructor(opts: {\n baseUrl: string;\n getAuthToken: () => Promise<string>;\n reconnectDelayMs?: number;\n }) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, '');\n this.getAuthToken = opts.getAuthToken;\n this.reconnectDelayMs = opts.reconnectDelayMs ?? 3000;\n }\n\n on(event: 'connect', handler: SseConnectHandler): void;\n on(event: 'event', handler: SseEventHandler): void;\n on(event: 'error', handler: SseErrorHandler): void;\n on(event: string, handler: SseConnectHandler | SseEventHandler | SseErrorHandler): void {\n const key = event as keyof SseListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n if (!arr.includes(handler)) arr.push(handler);\n }\n }\n\n off(event: 'connect', handler: SseConnectHandler): void;\n off(event: 'event', handler: SseEventHandler): void;\n off(event: 'error', handler: SseErrorHandler): void;\n off(event: string, handler: SseConnectHandler | SseEventHandler | SseErrorHandler): void {\n const key = event as keyof SseListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n const idx = arr.indexOf(handler);\n if (idx !== -1) arr.splice(idx, 1);\n }\n }\n\n /**\n * Typed convenience over the generic `'event'` stream: invokes `handler` only\n * for `AppVersionChanged` context events, with the payload already parsed.\n * Returns an unsubscribe closure (so callers need not retain the listener).\n */\n onAppVersionChanged(handler: (e: AppVersionChangedEvent) => void): () => void {\n const listener: SseEventHandler = (ev) => {\n // Core flattens the tagged payload: the event carries `type` as a sibling\n // of `data`, and `data` is the `{ fromVersion?, toVersion? }` payload.\n if (ev.type !== 'AppVersionChanged') return;\n const d = ev.data as { fromVersion?: string; toVersion?: string } | undefined;\n handler({ contextId: ev.contextId, fromVersion: d?.fromVersion, toVersion: d?.toVersion });\n };\n this.on('event', listener);\n return () => this.off('event', listener);\n }\n\n /**\n * Typed convenience over the generic `'event'` stream: invokes `handler` only\n * for group-migration events, narrowed on `type` so `data` is the matching\n * payload. Returns an unsubscribe closure.\n *\n * A non-admin subscriber sees `MigrationStarted`, `MigrationProgress` and\n * `MigrationCompleted` but never `CascadeProgress`, which core delivers to\n * namespace admins only.\n */\n onMigrationEvent(handler: (e: GroupMigrationEventData) => void): () => void {\n const listener: SseEventHandler = (ev) => {\n if (isGroupMigrationEvent(ev)) handler(ev);\n };\n this.on('event', listener);\n return () => this.off('event', listener);\n }\n\n private emit(event: 'connect', sessionId: string): void;\n private emit(event: 'event', data: SseEvent): void;\n private emit(event: 'error', error: Error): void;\n private emit(event: string, arg?: string | SseEvent | Error): void {\n const key = event as keyof SseListeners;\n if (key in this.listeners) {\n for (const handler of this.listeners[key]) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (handler as any)(arg);\n } catch {\n // Swallow handler errors\n }\n }\n }\n }\n\n async connect(): Promise<void> {\n // Already connected \u2014 don't reconnect\n if (this.abortController && !this.closed) {\n return;\n }\n this.closed = false;\n this.abortController = new AbortController();\n\n try {\n const token = await this.getAuthToken();\n const url = `${this.baseUrl}/sse`;\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Accept': 'text/event-stream',\n },\n signal: this.abortController.signal,\n });\n\n if (!response.ok) {\n // Throw the same typed errors the request path throws. A bare\n // `Error(\"SSE connection failed: 401\")` forced callers to string-match\n // the status and guess what it meant, and the honest guess \u2014 treat any\n // 401 as fatal \u2014 logs the user out on a routine reconnect after the\n // access token ages out, discarding a refresh token that was still\n // good. The distinction is in the header; surface it.\n const authError = response.headers.get('x-auth-error');\n const bodyText = await response.text().catch(() => undefined);\n\n if (\n response.status === 401 &&\n authError &&\n TERMINAL_AUTH_ERRORS.has(authError)\n ) {\n throw new AuthRevokedError(\n authError,\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n }\n\n throw new HTTPError(\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n }\n\n if (!response.body) {\n throw new Error('SSE response has no body');\n }\n\n this.readStream(response.body).catch((err) => {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n this.scheduleReconnect();\n });\n } catch (err) {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n this.scheduleReconnect();\n }\n }\n\n private async readStream(body: ReadableStream<Uint8Array>): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split('\\n');\n // Keep the last partial line in the buffer\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data:')) {\n const jsonStr = line.slice(5).trim();\n if (jsonStr) {\n this.handleMessage(jsonStr);\n }\n }\n }\n }\n // Flush remaining bytes from the decoder\n buffer += decoder.decode();\n if (buffer.startsWith('data:')) {\n const jsonStr = buffer.slice(5).trim();\n if (jsonStr) {\n this.handleMessage(jsonStr);\n }\n }\n } catch (err) {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n }\n\n // Stream ended, reconnect\n if (!this.closed) {\n this.scheduleReconnect();\n }\n }\n\n private handleMessage(jsonStr: string): void {\n try {\n const msg = JSON.parse(jsonStr);\n\n // Connection message\n if (msg.type === 'connect' && msg.session_id) {\n this.sessionId = msg.session_id;\n this.emit('connect', msg.session_id);\n // Re-subscribe after reconnect\n if (this.subscribedContextIds.size > 0 || this.subscribedGroupIds.size > 0) {\n this.sendSubscription('subscribe', {\n contextIds: [...this.subscribedContextIds],\n groupIds: [...this.subscribedGroupIds],\n });\n }\n return;\n }\n\n if (!msg.result) return;\n\n let eventData = msg.result.data;\n // Decode byte-array data if needed\n if (Array.isArray(eventData)) {\n try {\n const bytes = new Uint8Array(eventData);\n const text = new TextDecoder().decode(bytes);\n eventData = JSON.parse(text);\n } catch {\n // Keep raw data\n }\n }\n\n // Context event message\n if (msg.result.contextId) {\n this.emit('event', {\n contextId: msg.result.contextId,\n // Forward the event tag (sibling of `data` in core's flattened\n // payload) so typed helpers like `onAppVersionChanged` can discriminate.\n type: msg.result.type,\n data: eventData,\n });\n return;\n }\n\n // Group-keyed event message (untagged NodeEvent's membership and\n // migration variants; the `type` tag tells them apart).\n if (msg.result.groupId) {\n this.emit('event', {\n groupId: msg.result.groupId,\n type: msg.result.type,\n data: eventData,\n });\n }\n } catch {\n // Invalid JSON, ignore\n }\n }\n\n async subscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): Promise<void> {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n const newContextIds = (opts.contextIds ?? []).filter(id => !this.subscribedContextIds.has(id));\n const newGroupIds = (opts.groupIds ?? []).filter(id => !this.subscribedGroupIds.has(id));\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.add(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.add(id);\n }\n if ((newContextIds.length > 0 || newGroupIds.length > 0) && this.sessionId) {\n await this.sendSubscription('subscribe', { contextIds: newContextIds, groupIds: newGroupIds });\n }\n }\n\n async unsubscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): Promise<void> {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n const hadContextIds = (opts.contextIds ?? []).filter(id => this.subscribedContextIds.has(id));\n const hadGroupIds = (opts.groupIds ?? []).filter(id => this.subscribedGroupIds.has(id));\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.delete(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.delete(id);\n }\n if ((hadContextIds.length > 0 || hadGroupIds.length > 0) && this.sessionId) {\n await this.sendSubscription('unsubscribe', { contextIds: hadContextIds, groupIds: hadGroupIds });\n }\n }\n\n private async sendSubscription(\n method: 'subscribe' | 'unsubscribe',\n ids: { contextIds?: string[]; groupIds?: string[] },\n ): Promise<void> {\n try {\n const token = await this.getAuthToken();\n const params: { contextIds?: string[]; groupIds?: string[] } = {};\n if (ids.contextIds && ids.contextIds.length > 0) params.contextIds = ids.contextIds;\n if (ids.groupIds && ids.groupIds.length > 0) params.groupIds = ids.groupIds;\n const response = await fetch(`${this.baseUrl}/sse/subscription`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n id: this.sessionId,\n method,\n params,\n }),\n });\n if (!response.ok) {\n this.emit('error', new Error(`SSE ${method} failed: ${response.status}`));\n }\n } catch (err) {\n this.emit('error', err instanceof Error ? err : new Error(`SSE ${method} failed`));\n }\n }\n\n private forceReconnect(): void {\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n this.sessionId = null;\n this.connect();\n }\n\n private scheduleReconnect(): void {\n if (this.closed) return;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.forceReconnect();\n }, this.reconnectDelayMs);\n }\n\n close(): void {\n this.closed = true;\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.sessionId = null;\n this.subscribedContextIds.clear();\n this.subscribedGroupIds.clear();\n }\n}\n", "import type { GroupMembershipEventData, GroupMigrationEventData } from './group.js';\n\nexport type { GroupMembershipEventData, GroupMigrationEventData };\n\nexport interface WsEventData {\n contextId: string;\n /** The context-event discriminator (core serializes it as a sibling of\n * `data`, e.g. `\"AppVersionChanged\"`). Undefined for events without a tag. */\n type?: string;\n data: unknown;\n}\n\n/** Anything the `'event'` stream can deliver: context events plus the\n * group-keyed membership and migration families. */\ntype WsEvent = WsEventData | GroupMembershipEventData | GroupMigrationEventData;\ntype WsEventHandler = (event: WsEvent) => void;\ntype WsConnectHandler = () => void;\ntype WsErrorHandler = (error: Error) => void;\n\ninterface WsListeners {\n connect: WsConnectHandler[];\n event: WsEventHandler[];\n error: WsErrorHandler[];\n}\n\n/**\n * @experimental WebSocket event client. The SSE client (`SseClient`) is the\n * recommended transport for production \u2014 use `MeroJs.events` instead of `MeroJs.ws`.\n */\nexport class WsClient {\n private baseUrl: string;\n private getAuthToken: () => Promise<string>;\n private ws: WebSocket | null = null;\n private closed = false;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private subscribedContextIds: Set<string> = new Set();\n private subscribedGroupIds: Set<string> = new Set();\n private listeners: WsListeners = { connect: [], event: [], error: [] };\n\n private static readonly MAX_BACKOFF_MS = 30000;\n\n constructor(opts: {\n baseUrl: string;\n getAuthToken: () => Promise<string>;\n }) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, '');\n this.getAuthToken = opts.getAuthToken;\n }\n\n on(event: 'connect', handler: WsConnectHandler): void;\n on(event: 'event', handler: WsEventHandler): void;\n on(event: 'error', handler: WsErrorHandler): void;\n on(event: string, handler: WsConnectHandler | WsEventHandler | WsErrorHandler): void {\n const key = event as keyof WsListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n if (!arr.includes(handler)) arr.push(handler);\n }\n }\n\n off(event: 'connect', handler: WsConnectHandler): void;\n off(event: 'event', handler: WsEventHandler): void;\n off(event: 'error', handler: WsErrorHandler): void;\n off(event: string, handler: WsConnectHandler | WsEventHandler | WsErrorHandler): void {\n const key = event as keyof WsListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n const idx = arr.indexOf(handler);\n if (idx !== -1) arr.splice(idx, 1);\n }\n }\n\n private emit(event: 'connect'): void;\n private emit(event: 'event', data: WsEvent): void;\n private emit(event: 'error', error: Error): void;\n private emit(event: string, arg?: WsEvent | Error): void {\n const key = event as keyof WsListeners;\n if (key in this.listeners) {\n for (const handler of this.listeners[key]) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (handler as any)(arg);\n } catch {\n // Swallow handler errors\n }\n }\n }\n }\n\n async connect(): Promise<void> {\n if (this.ws && (this.ws.readyState === 0 /* CONNECTING */ || this.ws.readyState === 1 /* OPEN */)) {\n return;\n }\n this.closed = false;\n\n try {\n const token = await this.getAuthToken();\n if (!token) {\n throw new Error('No authentication token available for WebSocket connection');\n }\n // Browser WebSocket API can't set headers, use query param\n const wsUrl = this.baseUrl.replace(/^http/, 'ws');\n this.ws = new WebSocket(`${wsUrl}/ws?token=${encodeURIComponent(token)}`);\n\n this.ws.onopen = () => {\n this.reconnectAttempt = 0;\n this.emit('connect');\n this.resubscribeAfterReconnect();\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onerror = () => {\n this.emit('error', new Error('WebSocket error'));\n };\n\n this.ws.onclose = () => {\n if (!this.closed) {\n this.scheduleReconnect();\n }\n };\n } catch (err) {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n this.scheduleReconnect();\n }\n }\n\n private handleMessage(raw: string | ArrayBuffer | Blob): void {\n if (typeof raw !== 'string') return;\n\n try {\n const msg = JSON.parse(raw);\n\n if (!msg.result) return;\n\n let eventData = msg.result.data;\n if (Array.isArray(eventData)) {\n try {\n const bytes = new Uint8Array(eventData);\n const text = new TextDecoder().decode(bytes);\n eventData = JSON.parse(text);\n } catch {\n // Keep raw data\n }\n }\n\n if (msg.result.contextId) {\n this.emit('event', {\n contextId: msg.result.contextId,\n // Forward the event tag (sibling of `data` in core's flattened\n // payload) so consumers can discriminate, matching `SseClient`.\n type: msg.result.type,\n data: eventData,\n });\n return;\n }\n\n // Group-keyed event message (untagged NodeEvent's membership and\n // migration variants; the `type` tag tells them apart).\n if (msg.result.groupId) {\n this.emit('event', {\n groupId: msg.result.groupId,\n type: msg.result.type,\n data: eventData,\n });\n }\n } catch {\n // Invalid JSON, ignore\n }\n }\n\n subscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): void {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.add(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.add(id);\n }\n\n if (this.ws && this.ws.readyState === 1 /* OPEN */) {\n this.sendMessage({\n id: null,\n method: 'subscribe',\n params: this.buildSubscriptionParams(opts.contextIds ?? [], opts.groupIds ?? []),\n });\n }\n }\n\n unsubscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): void {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.delete(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.delete(id);\n }\n\n if (this.ws && this.ws.readyState === 1 /* OPEN */) {\n this.sendMessage({\n id: null,\n method: 'unsubscribe',\n params: this.buildSubscriptionParams(opts.contextIds ?? [], opts.groupIds ?? []),\n });\n }\n }\n\n private resubscribeAfterReconnect(): void {\n if (this.subscribedContextIds.size === 0 && this.subscribedGroupIds.size === 0) return;\n this.sendMessage({\n id: null,\n method: 'subscribe',\n params: this.buildSubscriptionParams([...this.subscribedContextIds], [...this.subscribedGroupIds]),\n });\n }\n\n private buildSubscriptionParams(\n contextIds: string[],\n groupIds: string[],\n ): { contextIds?: string[]; groupIds?: string[] } {\n const params: { contextIds?: string[]; groupIds?: string[] } = {};\n if (contextIds.length > 0) params.contextIds = contextIds;\n if (groupIds.length > 0) params.groupIds = groupIds;\n return params;\n }\n\n private sendMessage(msg: unknown): void {\n if (this.ws && this.ws.readyState === 1 /* OPEN */) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private scheduleReconnect(): void {\n if (this.closed) return;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n const delay = Math.min(\n 1000 * Math.pow(2, this.reconnectAttempt),\n WsClient.MAX_BACKOFF_MS,\n );\n this.reconnectAttempt++;\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n\n close(): void {\n this.closed = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.ws) {\n this.ws.onclose = null;\n this.ws.close();\n this.ws = null;\n }\n this.subscribedContextIds.clear();\n this.subscribedGroupIds.clear();\n }\n}\n", "import type { Codec } from './types.js';\n\n/** Default codec: JSON text as a byte array. The wire carries `state` as\n * `number[]`, not a string, so this encodes to bytes rather than to text. */\nexport function jsonCodec<T>(): Codec<T> {\n return {\n encode(value: T): number[] {\n return Array.from(new TextEncoder().encode(JSON.stringify(value)));\n },\n decode(bytes: number[]): T {\n return JSON.parse(new TextDecoder().decode(new Uint8Array(bytes))) as T;\n },\n };\n}\n", "import type { HttpClient } from '../http-client/index.js';\nimport type { SseClient } from '../events/index.js';\nimport { jsonRpcCall } from '../rpc/index.js';\nimport { jsonCodec } from './codec.js';\nimport type { Codec, EphemeralEntry } from './types.js';\n\nexport { jsonCodec };\nexport type { Codec, EphemeralEntry };\n\n/**\n * Ephemeral presence: transient, encrypted, never-persisted state (cursors,\n * typing, presence) that gossips between nodes without a WASM run or DAG\n * growth.\n *\n * The write/read asymmetry is the model, not an oversight. `set` takes no\n * author: you can only ever write your OWN slot, and the node resolves the\n * author server-side from its owned context identity \u2014 which is also why a\n * client cannot publish as somebody else. `subscribe` returns everyone's\n * slots, so each carries its `author`. The store is N independent\n * single-writer registers keyed by author; there is no merge across authors.\n *\n * There is a single read path: `subscribe`. On subscribing to a context, the\n * node replays that context's current presence to this connection as\n * ordinary `Ephemeral` events (carrying `ageMs`), before any live deltas\n * (which carry no `ageMs`). There is no separate snapshot RPC.\n */\nexport class EphemeralClient {\n private httpClient: HttpClient;\n private sse: SseClient;\n\n constructor(opts: { httpClient: HttpClient; sse: SseClient }) {\n this.httpClient = opts.httpClient;\n this.sse = opts.sse;\n }\n\n /**\n * Publish your own presence slice, replacing it wholesale.\n *\n * Rejects with an `RpcError` (not a bare `Error`), so a typed failure such as\n * an oversized slice keeps its `type` and `data` \u2014 e.g. `SliceTooLarge` with\n * the offending size \u2014 and is `instanceof RpcError` like every other RPC in\n * this SDK.\n */\n async set<T>(contextId: string, state: T, codec: Codec<T> = jsonCodec<T>()): Promise<void> {\n await jsonRpcCall<Record<string, never>>(this.httpClient, 'set_ephemeral', {\n contextId,\n state: codec.encode(state),\n });\n }\n\n /**\n * Observe presence changes for a context.\n *\n * This adds NO transport \u2014 it is a typed filter over the existing SSE event\n * stream, which already carries `{ contextId, type, data }`. On subscribing,\n * the node replays that context's current presence to this connection as\n * ordinary `Ephemeral` events before any live deltas; a replayed entry\n * carries `ageMs`, a live delta does not (never synthesized as `0` \u2014 absent\n * and zero mean different things). Returns an unsubscribe function.\n */\n subscribe<T>(\n contextId: string,\n handler: (entry: EphemeralEntry<T>) => void,\n codec: Codec<T> = jsonCodec<T>(),\n ): () => void {\n const listener = (event: unknown): void => {\n const e = event as { contextId?: string; type?: string; data?: unknown };\n if (e.type !== 'Ephemeral' || e.contextId !== contextId) return;\n\n const data = e.data as\n | { author?: string; state?: number[]; removed?: boolean; ageMs?: number }\n | undefined;\n if (!data?.author) return;\n\n // `removed` is omitted on an upsert, so normalize to a boolean here and\n // spare every caller the truthiness rule.\n const removed = Boolean(data.removed);\n const entry: EphemeralEntry<T> = {\n author: data.author,\n state: removed || data.state === undefined ? undefined : codec.decode(data.state),\n removed,\n };\n // `ageMs` is present only on a replayed seed entry; pass it through as-is\n // rather than defaulting a live delta to 0.\n if (data.ageMs !== undefined) entry.ageMs = data.ageMs;\n handler(entry);\n };\n\n this.sse.on('event', listener);\n // Errors surface via the SSE client's own 'error' event; nothing more to\n // do with them here.\n void this.sse.connect().catch(() => undefined);\n void this.sse.subscribe([contextId]).catch(() => undefined);\n\n return () => {\n this.sse.off('event', listener);\n };\n }\n}\n", "import { createBrowserHttpClient } from './http-client/index.js';\nimport { createAuthApiClientFromHttpClient } from './auth-api/index.js';\nimport { createAdminApiClientFromHttpClient } from './admin-api/index.js';\nimport type { AuthApiClient } from './auth-api/index.js';\nimport type { AdminApiClient } from './admin-api/index.js';\nimport type { HttpClient } from './http-client/index.js';\nimport type { TokenStore } from './token-store/index.js';\nimport { parseAuthCallback, buildAuthLoginUrl } from './auth/index.js';\nimport type { AuthCallbackResult, AuthLoginOptions } from './auth/index.js';\nimport { RpcClient } from './rpc/index.js';\nimport { SseClient } from './events/sse.js';\nimport { WsClient } from './events/ws.js';\nimport { EphemeralClient } from './ephemeral/index.js';\n\nexport interface MeroJsConfig {\n /** Base URL for the Calimero node */\n baseUrl: string;\n /** Initial credentials for authentication */\n credentials?: {\n username: string;\n password: string;\n };\n /** Custom HTTP client timeout in milliseconds */\n timeoutMs?: number;\n /** Request credentials mode for fetch (omit, same-origin, include) */\n requestCredentials?: RequestCredentials;\n /** Optional token store for persistence */\n tokenStore?: TokenStore;\n /**\n * Called when the node reports that the credential family is gone\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal: the tokens have\n * already been cleared by the time this runs and nothing is retried, so use it\n * to send the user back through login. Errors thrown here are swallowed \u2014\n * never let a UI failure mask the auth error.\n */\n onAuthRevoked?: () => Promise<void> | void;\n}\n\nexport interface TokenData {\n access_token: string;\n refresh_token: string;\n expires_at: number;\n}\n\n/** Name of the Web Lock that serializes token refresh across tabs / webviews. */\nconst REFRESH_LOCK_NAME = 'mero-js:token-refresh';\n\n/** Minimal structural view of the Web Locks API (not available in every runtime). */\ninterface LockManagerLike {\n request<T>(name: string, callback: () => Promise<T>): Promise<T>;\n}\n\n/** Returns `navigator.locks` when the runtime supports the Web Locks API. */\nfunction getLockManager(): LockManagerLike | null {\n const nav = (globalThis as unknown as { navigator?: { locks?: LockManagerLike } }).navigator;\n const locks = nav?.locks;\n return locks && typeof locks.request === 'function' ? locks : null;\n}\n\n/** Try to extract `exp` (seconds) from a JWT, return ms timestamp or fallback. */\nfunction expiresAtFromJwt(token: string, fallbackMs: number): number {\n try {\n const parts = token.split('.');\n if (parts.length === 3) {\n // JWT uses base64url encoding: replace -/_ with +// and add padding\n let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n while (b64.length % 4) b64 += '=';\n const payload = JSON.parse(atob(b64));\n if (typeof payload.exp === 'number') {\n return payload.exp * 1000;\n }\n }\n } catch {\n // not a JWT or can't parse\n }\n return fallbackMs;\n}\n\n/**\n * Main MeroJs SDK class that manages all API clients and authentication\n */\nexport class MeroJs {\n private config: MeroJsConfig;\n private httpClient: HttpClient;\n private authClient: AuthApiClient;\n private adminClient: AdminApiClient;\n private tokenData: TokenData | null = null;\n private refreshPromise: Promise<TokenData> | null = null;\n private tokenStore: TokenStore | null;\n private rpcClient: RpcClient | null = null;\n private sseClient: SseClient | null = null;\n private wsClient: WsClient | null = null;\n private wsWarned = false;\n private ephemeralClient?: EphemeralClient;\n\n constructor(config: MeroJsConfig) {\n this.config = {\n timeoutMs: 10000,\n ...config,\n };\n\n this.tokenStore = config.tokenStore ?? null;\n\n // Restore tokens from store if available\n if (this.tokenStore) {\n this.tokenData = this.tokenStore.getTokens();\n }\n\n // Create HTTP client with token management\n // For Tauri, explicitly set credentials to 'omit' to avoid network errors\n const isTauri = typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window;\n this.httpClient = createBrowserHttpClient({\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n refreshToken: async () => {\n const refreshed = await this.performTokenRefresh();\n return refreshed.access_token;\n },\n onTokenRefresh: async (newToken: string) => {\n if (this.tokenData) {\n this.tokenData.access_token = newToken;\n this.tokenStore?.setTokens(this.tokenData);\n }\n },\n onAuthRevoked: async () => {\n // The refresh-token family is gone (a single-use refresh token was\n // replayed, or the token was revoked). Nothing left to refresh with \u2014\n // drop the bundle so the app can force a re-login, then let the app react.\n this.clearToken();\n try {\n await this.config.onAuthRevoked?.();\n } catch {\n // A failing app callback must not mask the auth error.\n }\n },\n timeoutMs: this.config.timeoutMs,\n credentials: this.config.requestCredentials ?? (isTauri ? 'omit' : undefined),\n });\n\n // Create API clients\n this.authClient = createAuthApiClientFromHttpClient(this.httpClient, {\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n timeoutMs: this.config.timeoutMs,\n });\n\n this.adminClient = createAdminApiClientFromHttpClient(this.httpClient, {\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n timeoutMs: this.config.timeoutMs,\n });\n }\n\n /**\n * Get the Auth API client\n */\n get auth(): AuthApiClient {\n return this.authClient;\n }\n\n /**\n * Get the Admin API client\n */\n get admin(): AdminApiClient {\n return this.adminClient;\n }\n\n /**\n * Get the RPC client (lazy initialized)\n */\n get rpc(): RpcClient {\n if (!this.rpcClient) {\n this.rpcClient = new RpcClient({ httpClient: this.httpClient });\n }\n return this.rpcClient;\n }\n\n /**\n * Get the SSE event client (lazy initialized)\n */\n get events(): SseClient {\n if (!this.sseClient) {\n this.sseClient = new SseClient({\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n });\n }\n return this.sseClient;\n }\n\n /**\n * Get the ephemeral-presence client (lazy initialized).\n *\n * Shares this instance's SSE client, so `subscribe` reuses the one event\n * stream rather than opening a second connection.\n */\n get ephemeral(): EphemeralClient {\n if (!this.ephemeralClient) {\n this.ephemeralClient = new EphemeralClient({\n httpClient: this.httpClient,\n sse: this.events,\n });\n }\n return this.ephemeralClient;\n }\n\n /**\n * Get the WebSocket event client (lazy initialized).\n * @experimental Use `events` (SSE) for production. WsClient is experimental.\n */\n get ws(): WsClient {\n if (!this.wsWarned) {\n this.wsWarned = true;\n console.warn('[mero-js] WsClient is experimental. Use mero.events (SSE) for production.');\n }\n if (!this.wsClient) {\n this.wsClient = new WsClient({\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n });\n }\n return this.wsClient;\n }\n\n /**\n * Authenticate with the provided credentials\n * This will create the root key on first use\n */\n async authenticate(credentials?: {\n username: string;\n password: string;\n }): Promise<TokenData> {\n const creds = credentials || this.config.credentials;\n if (!creds) {\n throw new Error('No credentials provided for authentication');\n }\n\n try {\n const requestBody = {\n auth_method: 'user_password',\n public_key: creds.username,\n client_name: 'mero-js-sdk',\n permissions: ['admin'],\n timestamp: Math.floor(Date.now() / 1000),\n provider_data: {\n username: creds.username,\n password: creds.password,\n },\n };\n\n const response = await this.authClient.generateTokens(requestBody);\n\n const accessToken = response.data.access_token;\n this.tokenData = {\n access_token: accessToken,\n refresh_token: response.data.refresh_token,\n expires_at: expiresAtFromJwt(accessToken, Date.now() + 3600_000),\n };\n\n this.tokenStore?.setTokens(this.tokenData);\n\n return this.tokenData;\n } catch (error) {\n throw new Error(\n `Authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Get a valid token. Returns the current token as-is.\n * The server rejects refresh attempts while the access token is still valid,\n * so we never proactively refresh. Instead, the WebHttpClient handles 401\n * responses reactively via the refreshToken transport hook.\n */\n private async getValidToken(): Promise<TokenData | null> {\n return this.tokenData;\n }\n\n /**\n * Refresh the access token. Single-flight: every caller (including the HTTP\n * transport's 401 hook) goes through here.\n *\n * Refresh tokens are single-use (calimero-network/core#3083): each refresh\n * consumes the presented token and returns a new one, and replaying a consumed\n * token makes the server revoke the whole family. A refresh must therefore\n * happen exactly once per rotation, which needs three layers:\n * - an in-process promise, so concurrent 401s in this instance share one call;\n * - a Web Lock (when available), so other tabs/webviews don't refresh at the\n * same time on the same stored token;\n * - a re-read of the token store inside the lock, so a bundle that another\n * instance already rotated is adopted instead of replaying a stale token.\n */\n private async performTokenRefresh(): Promise<TokenData> {\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n // The access token that triggered this refresh. If the store holds a different\n // one by the time we get the lock, someone else already rotated for us.\n const triggeringAccessToken = this.tokenData?.access_token;\n\n const promise = this.withRefreshLock(() =>\n this.performTokenRefreshLocked(triggeringAccessToken),\n );\n this.refreshPromise = promise;\n\n try {\n return await promise;\n } finally {\n if (this.refreshPromise === promise) {\n this.refreshPromise = null;\n }\n }\n }\n\n /** Run `fn` under the cross-tab refresh lock, or directly if Web Locks are unavailable. */\n private withRefreshLock<T>(fn: () => Promise<T>): Promise<T> {\n const locks = getLockManager();\n return locks ? locks.request(REFRESH_LOCK_NAME, fn) : fn();\n }\n\n /**\n * Perform the actual token refresh. Runs with the refresh lock held.\n */\n private async performTokenRefreshLocked(\n triggeringAccessToken?: string,\n ): Promise<TokenData> {\n // Another instance/tab may have rotated the bundle while we were queued behind\n // the lock \u2014 the store, not our in-memory copy, is the source of truth.\n const stored = this.tokenStore?.getTokens() ?? null;\n if (stored?.refresh_token) {\n this.tokenData = stored;\n\n if (triggeringAccessToken && stored.access_token !== triggeringAccessToken) {\n // Someone else already refreshed. Reuse their bundle rather than replaying\n // our (now consumed) refresh token, which would revoke the family.\n return stored;\n }\n }\n\n if (!this.tokenData?.refresh_token) {\n throw new Error('No refresh token available');\n }\n\n try {\n const response = await this.authClient.refreshToken({\n access_token: this.tokenData.access_token,\n refresh_token: this.tokenData.refresh_token,\n });\n\n const accessToken = response.data.access_token;\n this.tokenData = {\n access_token: accessToken,\n // The refresh token is rotated on every refresh \u2014 persist the new one or\n // the next refresh replays a consumed token.\n refresh_token: response.data.refresh_token,\n expires_at: expiresAtFromJwt(accessToken, Date.now() + 3600_000),\n };\n\n this.tokenStore?.setTokens(this.tokenData);\n\n return this.tokenData;\n } catch (error) {\n // Don't clear tokens on refresh failure \u2014 the access token may still be\n // valid (server rejects refresh while access token hasn't expired yet).\n // A genuinely dead family arrives as `x-auth-error: token_reuse` and is\n // handled by the onAuthRevoked transport hook. Let the caller handle this.\n throw new Error(\n `Token refresh failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Clear the current token\n */\n public clearToken(): void {\n this.refreshPromise = null;\n this.tokenData = null;\n this.tokenStore?.clear();\n }\n\n /**\n * Check if the SDK is authenticated\n */\n public isAuthenticated(): boolean {\n return this.tokenData !== null;\n }\n\n /**\n * Set token data directly (e.g., from auth callback).\n * If `expires_at` is missing or 0, attempts to parse the JWT exp claim,\n * falling back to 1 hour from now.\n */\n public setTokenData(data: TokenData): void {\n const expiresAt = data.expires_at || expiresAtFromJwt(data.access_token, Date.now() + 3600_000);\n this.tokenData = { ...data, expires_at: expiresAt };\n this.tokenStore?.setTokens(this.tokenData);\n }\n\n /**\n * Get the current token data (for debugging)\n */\n public getTokenData(): TokenData | null {\n return this.tokenData;\n }\n\n /**\n * Close all event connections and clean up resources\n */\n public close(): void {\n this.sseClient?.close();\n this.wsClient?.close();\n }\n\n /**\n * Parse an auth callback URL hash fragment (static utility)\n */\n static parseAuthCallback(url: string): AuthCallbackResult | null {\n return parseAuthCallback(url);\n }\n\n /**\n * Build an auth login URL (static utility)\n */\n static buildAuthLoginUrl(nodeUrl: string, opts: AuthLoginOptions): string {\n return buildAuthLoginUrl(nodeUrl, opts);\n }\n}\n\n/**\n * Create a new MeroJs SDK instance\n */\nexport function createMeroJs(config: MeroJsConfig): MeroJs {\n return new MeroJs(config);\n}\n", "import type { TokenData } from '../mero-js.js';\n\nexport interface TokenStore {\n getTokens(): TokenData | null;\n setTokens(data: TokenData): void;\n clear(): void;\n}\n\nexport class MemoryTokenStore implements TokenStore {\n private tokens: TokenData | null = null;\n\n getTokens(): TokenData | null {\n return this.tokens;\n }\n\n setTokens(data: TokenData): void {\n this.tokens = data;\n }\n\n clear(): void {\n this.tokens = null;\n }\n}\n\nconst STORAGE_KEY = 'mero-tokens';\n\nexport class LocalStorageTokenStore implements TokenStore {\n private readonly key: string;\n\n constructor(key: string = STORAGE_KEY) {\n this.key = key;\n }\n\n getTokens(): TokenData | null {\n try {\n if (typeof localStorage === 'undefined') return null;\n const raw = localStorage.getItem(this.key);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (parsed && parsed.access_token && parsed.refresh_token) {\n return {\n access_token: parsed.access_token,\n refresh_token: parsed.refresh_token,\n expires_at: typeof parsed.expires_at === 'number' ? parsed.expires_at : Date.now() + 3600_000,\n };\n }\n return null;\n } catch {\n return null;\n }\n }\n\n setTokens(data: TokenData): void {\n try {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.key, JSON.stringify(data));\n } catch {\n // Storage unavailable\n }\n }\n\n clear(): void {\n try {\n if (typeof localStorage === 'undefined') return;\n localStorage.removeItem(this.key);\n } catch {\n // Storage unavailable\n }\n }\n}\n", "export interface CloudClientConfig {\n cloudBaseUrl?: string;\n}\n\nexport interface EnableHAOptions {\n groupId: string;\n contextId: string;\n redirectUrl?: string;\n}\n\nexport interface DisableHAOptions {\n groupId: string;\n contextId: string;\n redirectUrl?: string;\n}\n\nexport class CloudClient {\n private baseUrl: string;\n\n constructor(config: CloudClientConfig = {}) {\n this.baseUrl = (config.cloudBaseUrl || 'https://cloud.calimero.network').replace(/\\/+$/, '');\n }\n\n enableHA(options: EnableHAOptions): void {\n const params = new URLSearchParams({\n group_id: options.groupId,\n context_id: options.contextId,\n });\n if (options.redirectUrl) {\n params.set('redirect_url', options.redirectUrl);\n }\n window.open(`${this.baseUrl}/enable-ha?${params.toString()}`);\n }\n\n disableHA(options: DisableHAOptions): void {\n const params = new URLSearchParams({\n group_id: options.groupId,\n context_id: options.contextId,\n });\n if (options.redirectUrl) {\n params.set('redirect_url', options.redirectUrl);\n }\n window.open(`${this.baseUrl}/disable-ha?${params.toString()}`);\n }\n}\n", "/**\n * Byte-level primitives shared by everything in this package that signs.\n *\n * Extracted from `warrant/warrant.ts` when the device-cert signer arrived and\n * needed the same `domainHash`, hex handling and ed25519 import. Keeping one\n * copy is the point: these have to stay byte-identical with core, and two\n * copies drifting apart is exactly the failure the byte-parity e2e exists to\n * catch. Internal \u2014 not exported from the package root.\n */\n\nconst PKCS8_ED25519_PREFIX = new Uint8Array([\n 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04,\n 0x22, 0x04, 0x20,\n]);\n\n/** Little-endian u32, for borsh fixed-width fields and epoch counters. */\nexport function u32le(value: number): Uint8Array {\n const out = new Uint8Array(4);\n new DataView(out.buffer).setUint32(0, value, true);\n return out;\n}\n\nexport function hex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport function fromHex(value: string, label: string, expectedBytes: number): Uint8Array {\n const clean = value.trim();\n if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {\n throw new Error(\n `${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`,\n );\n }\n // Indexed rather than `match(/../g)!`: the length is already validated above,\n // so the assertion would only be telling the compiler what the guard proved,\n // and this needs no assertion at all.\n const bytes = new Uint8Array(expectedBytes);\n for (let i = 0; i < expectedBytes; i += 1) {\n bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\nexport function u64le(value: number | bigint): Uint8Array {\n const out = new Uint8Array(8);\n new DataView(out.buffer).setBigUint64(0, BigInt(value), true);\n return out;\n}\n\nexport function concat(...parts: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n\n/**\n * core's `domain_hash`: SHA-256 over the length-prefixed domain, then each\n * length-prefixed part. The lengths are what stop two different field splits from\n * hashing alike.\n */\nexport async function domainHash(\n domain: Uint8Array,\n parts: Uint8Array[],\n): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [u64le(domain.length), domain];\n for (const part of parts) {\n chunks.push(u64le(part.length), part);\n }\n return new Uint8Array(\n await crypto.subtle.digest('SHA-256', concat(...chunks)),\n );\n}\n\nexport async function importSigningKey(secretHex: string): Promise<CryptoKey> {\n const seed = fromHex(secretHex, 'deviceSecret', 32);\n const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);\n try {\n return await crypto.subtle.importKey(\n 'pkcs8',\n pkcs8,\n { name: 'Ed25519' },\n false,\n ['sign'],\n );\n } catch (cause) {\n // The original message is folded in rather than passed as `cause`: this\n // package targets ES2020, where `Error` has no `cause` option.\n const detail = cause instanceof Error ? `: ${cause.message}` : '';\n throw new Error(\n 'this runtime has no WebCrypto Ed25519, so a warrant cannot be signed ' +\n 'here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it; ' +\n 'otherwise mint the warrant with `merod account warrant`' +\n detail,\n );\n }\n}\n\n/**\n * The public half of an ed25519 seed.\n *\n * Derived rather than taken as an argument, for the reason core does the same: a\n * caller able to name a key it does not hold could produce a warrant it cannot\n * sign, and the field would stop meaning \"who authorised this\".\n */\nexport async function derivePublicKey(secretHex: string): Promise<Uint8Array> {\n const seed = fromHex(secretHex, 'deviceSecret', 32);\n const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);\n const key = await crypto.subtle.importKey(\n 'pkcs8',\n pkcs8,\n { name: 'Ed25519' },\n true,\n ['sign'],\n );\n const jwk = await crypto.subtle.exportKey('jwk', key);\n const raw = (jwk as JsonWebKey & { x: string }).x;\n return Uint8Array.from(atob(raw.replace(/-/g, '+').replace(/_/g, '/')), (c) =>\n c.charCodeAt(0),\n );\n}\n", "/**\n * Mint a warrant: the author's consent for one relay to run one intent, once.\n *\n * This exists because the case delegated authorship is *for* is an account that\n * holds no node \u2014 a browser tab, a Node service, a bot. Every one of those is a\n * JS runtime, and until now the only thing that could mint a warrant was `merod`,\n * so \"a member with no node\" in practice meant \"a member with a node it is not\n * allowed to use for anything else\".\n *\n * **No dependencies, and that is not incidental.** The three primitives are all\n * built in: `crypto.subtle.digest('SHA-256')` for the hash, `crypto.subtle`\n * Ed25519 for the signature, and `DataView.setBigUint64` for the two u64s. The\n * warrant's every field is fixed-width, so its encoding is concatenation \u2014 there\n * is no borsh here because none is needed.\n *\n * **The byte contract is pinned in core**, at\n * `crates/account/src/tests/warrant_wire_fixture.rs`. The domain strings below\n * are `pub(crate)` there, so nothing in that repository forces anyone to notice\n * this file depends on them \u2014 which is exactly why the fixture lives on that side\n * and this module's test asserts the same vectors. A drift would otherwise leave\n * this producing well-formed warrants whose signatures verify nowhere, surfacing\n * at a relay as a 403: an authorization refusal, nowhere near the cause.\n */\n\nimport {\n concat,\n derivePublicKey,\n domainHash,\n fromHex,\n hex,\n importSigningKey,\n u64le,\n} from '../crypto/internal.js';\n\nconst SIGN_DOMAIN = new TextEncoder().encode('calimero.warrant.v1');\nconst INTENT_DOMAIN = new TextEncoder().encode('calimero.warrant.intent.v1');\n\n/** Ed25519 PKCS#8 prefix, so a raw 32-byte seed can be imported by WebCrypto. */\n/** What a warrant authorises. */\nexport interface WarrantInput {\n /**\n * The context, hex \u2014 the same string every other method here takes.\n *\n * Hex like everything else on this interface. It was base58 while the node\n * spelled `ContextId` and `PublicKey` that way and `AccountId` and `DeviceId`\n * in hex; that split is gone, so this module no longer needs a rule per field\n * and no longer needs a base58 decoder to enforce one.\n */\n context: string;\n /** The author's account, hex \u2014 whose consent this is. */\n authorAccount: string;\n /** The relay authorised to act, hex. An account, not a key. */\n executor: string;\n /** The method the relay may run. */\n method: string;\n /** Its arguments, as the JSON the guest will receive. */\n argsJson: unknown;\n /**\n * Monotonic per author **device**.\n *\n * Per device rather than per account because two devices of one account are\n * independent replicas: they cannot coordinate on a counter, so an\n * account-scoped sequence would have them refusing each other's warrants.\n */\n nonce: number | bigint;\n /** Unix seconds after which the relay must refuse it. */\n notAfter: number | bigint;\n /**\n * The author device's ed25519 signing secret, hex (32 bytes).\n *\n * Never sent anywhere. It signs locally and only the signature travels, which\n * is the whole reason a warrant can be minted by something holding no node.\n */\n deviceSecret: string;\n}\n\n\n\n\n\n\n\n/**\n * The commitment a warrant carries in place of the intent itself.\n *\n * Its own domain, distinct from the signing one, so a value computed for one\n * purpose cannot be presented for the other.\n */\nexport async function intentHash(\n method: string,\n argsJson: unknown,\n): Promise<Uint8Array> {\n const args = new TextEncoder().encode(JSON.stringify(argsJson));\n return domainHash(INTENT_DOMAIN, [new TextEncoder().encode(method), args]);\n}\n\n\n/**\n * Sign a warrant and return it hex-encoded, ready for `performIntent`.\n *\n * The 240 bytes are the canonical form: the signature covers exactly them, which\n * is why this returns the encoding rather than an object. A caller that rebuilt\n * the fields from JSON would have a second spelling able to disagree with what\n * was signed.\n */\nexport async function signWarrant(input: WarrantInput): Promise<string> {\n const context = fromHex(input.context, 'context', 32);\n const authorAccount = fromHex(input.authorAccount, 'authorAccount', 32);\n const executor = fromHex(input.executor, 'executor', 32);\n\n const key = await importSigningKey(input.deviceSecret);\n const publicKey = await derivePublicKey(input.deviceSecret);\n\n const commitment = await intentHash(input.method, input.argsJson);\n const nonce = u64le(input.nonce);\n const notAfter = u64le(input.notAfter);\n\n const preimage = await domainHash(SIGN_DOMAIN, [\n context,\n authorAccount,\n publicKey,\n executor,\n commitment,\n nonce,\n notAfter,\n ]);\n\n const signature = new Uint8Array(\n await crypto.subtle.sign({ name: 'Ed25519' }, key, preimage),\n );\n\n return hex(\n concat(\n context,\n authorAccount,\n publicKey,\n executor,\n commitment,\n nonce,\n notAfter,\n signature,\n ),\n );\n}\n\n", "/**\n * Minting and certifying a device offline, with a key that never reaches a node.\n *\n * This is the second half of the keyholder story. `signWarrant` lets an account\n * with no node *write*; this lets one exist in the first place \u2014 an account root\n * certifies a device, and the resulting credential is what a joiner presents.\n *\n * As with the warrant signer, the risk is that this reproduces core's encoding\n * and has to keep doing so. The answer is the same: a golden vector here, and an\n * e2e that diffs this output against `merod account sign-cert` byte for byte.\n *\n * Everything below is derived from core:\n *\n * - `DeviceCert::signing_payload` \u2014 `crates/account/src/device.rs`\n * - `DeviceId::mint` \u2014 `crates/primitives/src/identity.rs`\n * - `AccountProof` / `AccountGenesis` borsh layout \u2014 `crates/account/src/{signed,account}.rs`\n */\nimport {\n concat,\n derivePublicKey,\n domainHash,\n fromHex,\n hex,\n importSigningKey,\n u32le,\n} from '../crypto/internal.js';\n\nconst CERT_DOMAIN = new TextEncoder().encode('calimero.device.cert.v1');\nconst ACCOUNT_ID_DOMAIN = new TextEncoder().encode('calimero.account.genesis.v1');\nconst DEVICE_ID_DOMAIN = new TextEncoder().encode('calimero.device.id.v1');\n\n/** `AccountGenesis::version`, which the credential's borsh encoding leads with. */\n/**\n * Core's `ACCOUNT_GENESIS_VERSION`. It is part of the `AccountId` preimage, so\n * this value decides which account a root key names \u2014 a mismatch does not fail\n * as a version error at the edge, it silently derives a different account and\n * core refuses the credential as unverifiable.\n *\n * `2` since the genesis dropped its per-namespace nonce. This was `1`, which\n * produced credentials current core rejects outright; the shape was already v2,\n * only the tag was stale.\n */\nconst ACCOUNT_GENESIS_VERSION = 2;\n\n/** What a root certifies about one device. */\nexport interface DeviceCertInput {\n /** The account root's signing secret, 64 hex. Signs the certificate. */\n rootSecret: string;\n /** The device being certified, 64 hex \u2014 see {@link mintDeviceId}. */\n device: string;\n /** The key that device signs with, 64 hex. */\n signPublicKey: string;\n /** The key the group key is delivered to, 64 hex (X25519). */\n kemPublicKey: string;\n /**\n * Must strictly exceed any epoch already folded for this device.\n *\n * The projection refuses a link that does not advance it, so a re-issued\n * certificate reusing an epoch is inert rather than a rollback.\n */\n deviceEpoch: number;\n}\n\n/**\n * Mint a device id: `H(DEVICE_ID_DOMAIN, account \u2016 nonce)`.\n *\n * Derived from the account and a fresh nonce rather than from the device's keys,\n * so rotating a keypair keeps the replica identity \u2014 and with it the counter\n * slots and HLC lineage \u2014 intact.\n */\nexport async function mintDeviceId(\n account: string,\n nonce: Uint8Array,\n): Promise<string> {\n if (nonce.length !== 16) {\n throw new Error(`nonce must be 16 bytes, got ${nonce.length}`);\n }\n const accountBytes = fromHex(account, 'account', 32);\n return hex(await domainHash(DEVICE_ID_DOMAIN, [accountBytes, nonce]));\n}\n\n/**\n * The 32 bytes a root signs to certify a device.\n *\n * Both keys are covered, so neither the signing key nor the delivery key can be\n * substituted into a certificate that otherwise verifies \u2014 which is what stops a\n * relay carrying someone's credential from making itself the reader.\n */\nexport async function deviceCertPayload(input: {\n account: string;\n device: string;\n signPublicKey: string;\n kemPublicKey: string;\n keyEpoch: number;\n deviceEpoch: number;\n}): Promise<Uint8Array> {\n return domainHash(CERT_DOMAIN, [\n fromHex(input.account, 'account', 32),\n fromHex(input.device, 'device', 32),\n fromHex(input.signPublicKey, 'signPublicKey', 32),\n fromHex(input.kemPublicKey, 'kemPublicKey', 32),\n u32le(input.keyEpoch),\n u32le(input.deviceEpoch),\n ]);\n}\n\n/**\n * Borsh-encode an `AccountProof<DeviceCert>` \u2014 what core calls a\n * `JoinAccountCredential`.\n *\n * Extracted so the device-cert path and the namespace-op signer encode this from\n * one implementation. Two copies of a borsh layout drift silently: the encoding\n * is only checked by a peer rejecting a signature, which points at the signature\n * rather than at whichever copy went stale.\n *\n * Layout is `AccountProof { genesis, chain, statement }`:\n * `AccountGenesis` (version u8 + root pk 32) + `chain` (empty Vec, u32 len) +\n * `DeviceCert` (account 32 + device 32 + sign pk 32 + kem pk 32 + key_epoch u32\n * + device_epoch u32 + signature 64) = 237 bytes with an empty chain.\n */\nexport function accountProofBytes(input: {\n rootPublicKey: Uint8Array;\n account: string;\n device: string;\n signPublicKey: string;\n kemPublicKey: string;\n keyEpoch: number;\n deviceEpoch: number;\n signature: Uint8Array;\n}): Uint8Array {\n return concat(\n new Uint8Array([ACCOUNT_GENESIS_VERSION]),\n input.rootPublicKey,\n u32le(0),\n fromHex(input.account, 'account', 32),\n fromHex(input.device, 'device', 32),\n fromHex(input.signPublicKey, 'signPublicKey', 32),\n fromHex(input.kemPublicKey, 'kemPublicKey', 32),\n u32le(input.keyEpoch),\n u32le(input.deviceEpoch),\n input.signature,\n );\n}\n\n/**\n * Certify a device, returning the hex credential `merod account sign-cert`\n * prints \u2014 a borsh-encoded `AccountProof<DeviceCert>`.\n *\n * The layout, field for field, is core's:\n *\n * ```\n * AccountProof { genesis: AccountGenesis, chain: Vec<RootKeyHandoff>, statement: DeviceCert }\n * AccountGenesis { version: u8, root_sign_pk: [u8; 32] }\n * chain \u2192 u32-LE count, then that many handoffs\n * DeviceCert { account, device, sign_pk, kem_pk: [u8; 32] x4,\n * key_epoch: u32, device_epoch: u32, signature: [u8; 64] }\n * ```\n *\n * Borsh for plain fixed-width data is concatenation; the only variable part is\n * the chain's length prefix. `chain` is empty here for the same reason it is in\n * `sign-cert`: a root that has never been handed off signs directly, and a\n * handoff chain is only needed once it has.\n *\n * `keyEpoch` is 0 for the same reason \u2014 it names the root epoch that signed, and\n * an un-rotated root is at 0. Re-signing after a handoff is a separate flow that\n * needs the chain, so this deliberately does not take it as an argument rather\n * than accepting a value it would then have to ignore.\n */\nexport async function signDeviceCert(input: DeviceCertInput): Promise<string> {\n const rootPublicKey = await derivePublicKey(input.rootSecret);\n const account = hex(\n await domainHash(ACCOUNT_ID_DOMAIN, [\n concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey),\n ]),\n );\n\n const keyEpoch = 0;\n const payload = await deviceCertPayload({\n account,\n device: input.device,\n signPublicKey: input.signPublicKey,\n kemPublicKey: input.kemPublicKey,\n keyEpoch,\n deviceEpoch: input.deviceEpoch,\n });\n\n const key = await importSigningKey(input.rootSecret);\n const signature = new Uint8Array(\n await crypto.subtle.sign('Ed25519', key, payload),\n );\n\n const credential = accountProofBytes({\n rootPublicKey,\n account,\n device: input.device,\n signPublicKey: input.signPublicKey,\n kemPublicKey: input.kemPublicKey,\n keyEpoch,\n deviceEpoch: input.deviceEpoch,\n signature,\n });\n\n return hex(credential);\n}\n\n/** The account this root owns \u2014 the content address of its genesis. */\nexport async function accountForRoot(rootSecret: string): Promise<string> {\n const rootPublicKey = await derivePublicKey(rootSecret);\n return hex(\n await domainHash(ACCOUNT_ID_DOMAIN, [\n concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey),\n ]),\n );\n}\n", "/**\n * Sign a namespace governance op from the SDK \u2014 specifically the membership op a\n * keyholder needs to join without running a node.\n *\n * `admitJoin` carries an already-signed op to a node the inviter named as an\n * admitter. Producing that op is the piece a keyholder could not do before: the\n * op must be signed by the device key in the credential it carries, because every\n * peer checks `signer == credential.statement.sign_pk` when applying a join. An\n * admitter can relay it and can never author it.\n *\n * The encoding is borsh, hand-written to match core's structs. Correctness is not\n * asserted against bytes recorded here \u2014 a layout transcribed by eye is exactly\n * how a golden ends up confidently wrong. It is asserted by a node accepting the\n * op, which is what the e2e does.\n */\nimport type { SignedGroupOpenInvitation } from '../admin-api/admin-types.js';\nimport {\n concat,\n derivePublicKey,\n fromHex,\n hex,\n importSigningKey,\n u32le,\n u64le,\n} from '../crypto/internal.js';\n\n/** Core's `SIGNED_NAMESPACE_OP_SCHEMA_VERSION`. A node refuses any other value. */\nexport const SIGNED_NAMESPACE_OP_SCHEMA_VERSION = 7;\n\n/** Domain prefixed to the signable bytes; core's `NAMESPACE_GOVERNANCE_SIGN_DOMAIN`. */\nconst NAMESPACE_SIGN_DOMAIN = new TextEncoder().encode('calimero.namespace.v1');\n\n/** `NamespaceOp::Root` is the first variant. */\nconst NAMESPACE_OP_ROOT = 0;\n\n/**\n * `RootOp` discriminants, in declaration order. Only the two join variants are\n * emitted here; the rest are listed so the numbering is checkable against core\n * rather than inferred from the two in use.\n */\nconst ROOT_OP = {\n GroupCreated: 0,\n GroupReparented: 1,\n GroupDeleted: 2,\n AdminChanged: 3,\n PolicyUpdated: 4,\n MemberJoined: 5,\n KeyDelivery: 6,\n MemberJoinedOpen: 7,\n MemberJoinedAt: 8,\n NamespaceCreated: 9,\n MemberJoinedViaTeeAttestation: 10,\n} as const;\n\n/** A required `[u8; 32]`, as JSON carries it: 32 byte values. */\nfunction bytes32(value: readonly number[], label: string): Uint8Array {\n if (value.length !== 32) {\n throw new Error(`${label} must be 32 bytes, got ${value.length}`);\n }\n return new Uint8Array(value);\n}\n\n/**\n * Borsh `Option<[u8; 32]>` from the byte array JSON carries it as.\n *\n * `[u8; 32]` crosses JSON as 32 numbers, not as hex \u2014 the hex spelling belongs to\n * `AccountId`, which has its own representation. Encoding one of these from a hex\n * string would silently produce the wrong 32 bytes.\n */\nfunction optionalBytes32(\n value: readonly number[] | null | undefined,\n label: string,\n): Uint8Array {\n if (value === null || value === undefined) {\n return new Uint8Array([0]);\n }\n if (value.length !== 32) {\n throw new Error(`${label} must be 32 bytes, got ${value.length}`);\n }\n return concat(new Uint8Array([1]), new Uint8Array(value));\n}\n\n/** Borsh `String`: u32 length then UTF-8 bytes. */\nfunction borshString(value: string): Uint8Array {\n const bytes = new TextEncoder().encode(value);\n return concat(u32le(bytes.length), bytes);\n}\n\n\n/**\n * Borsh-encode a `SignedGroupOpenInvitation`.\n *\n * Re-encoded rather than passed through, because it has to go inside the op that\n * gets signed. That makes this function version-locked to core: a field added to\n * the invitation and omitted here produces an op whose inner invitation no longer\n * matches the inviter's signature over it. That exact drift, in client-py, broke\n * 93 scenarios \u2014 the failure surfaces as `invalid invitation signature` and points\n * nowhere near the encoder.\n */\nexport function encodeSignedInvitation(signed: SignedGroupOpenInvitation): Uint8Array {\n const body = signed.invitation;\n const admitters = body.admitters ?? [];\n const admitterAddrs = signed.admitter_addrs ?? [];\n\n return concat(\n // GroupInvitationFromAdmin.\n //\n // `SignerId` and `ContextGroupId` cross JSON as 32 numbers; `AccountId`\n // crosses as hex. Same width, different spelling, and reading either the\n // wrong way yields 32 bytes that encode cleanly and verify as nothing.\n bytes32(body.inviter_identity, 'inviter_identity'),\n bytes32(body.group_id, 'group_id'),\n u64le(body.expiration_timestamp),\n bytes32(body.secret_salt, 'secret_salt'),\n new Uint8Array([body.invited_role]),\n u32le(admitters.length),\n ...admitters.map((a, i) => fromHex(a, `admitters[${i}]`, 32)),\n // ...then the enclosing SignedGroupOpenInvitation, in declaration order.\n // `inviter_account` sits between the signature and the addresses; putting it\n // anywhere else still encodes 32 bytes and still verifies as nothing.\n borshString(signed.inviter_signature),\n signed.inviter_account\n ? concat(new Uint8Array([1]), fromHex(signed.inviter_account, 'inviter_account', 32))\n : new Uint8Array([0]),\n // A `Vec<String>`, so each entry is a bare borsh string. This carried an\n // enum until core dropped the URL variant, and an enum writes a\n // discriminant byte ahead of each entry \u2014 encoding one here now would shift\n // every following byte and fail as `invalid invitation signature`, pointing\n // nowhere near this line.\n u32le(admitterAddrs.length),\n ...admitterAddrs.map(borshString),\n optionalBytes32(signed.application_id, 'application_id'),\n // Borsh order follows core's field order, where this is `bytecode_id`; the\n // JSON key is `app_key`, a rename covering both directions that core pins in\n // a test. Encoding by the Rust name would read `undefined` and emit a None\n // where the inviter signed a Some.\n optionalBytes32(signed.app_key, 'app_key'),\n );\n}\n\nexport interface SignMemberJoinInput {\n /** The namespace being joined, 64 hex. */\n readonly namespaceId: string;\n /** The account joining, 64 hex \u2014 the subject of the credential. */\n readonly member: string;\n /** The invitation, as the admin API returned it. */\n readonly invitation: SignedGroupOpenInvitation;\n /**\n * The joiner's `AccountProof<DeviceCert>`, hex \u2014 from `signDeviceCert`.\n *\n * Its `sign_pk` must be the public key of `deviceSecret`; a peer checks that\n * when applying the join and refuses otherwise.\n */\n readonly credential: string;\n /** The device signing secret, 64 hex. Must match the credential's `sign_pk`. */\n readonly deviceSecret: string;\n /**\n * Heads this op is written against. Empty means \"signed against an empty head\"\n * \u2014 which is NOT the same as genesis, and a node with a non-empty head will\n * reject it as stale rather than treat it as a first op.\n */\n readonly parentOpHashes?: readonly string[];\n /** Anti-replay nonce; a node keeps a window per signer. */\n readonly nonce: number | bigint;\n /**\n * When the join happened, unix seconds. Defaults to now.\n *\n * Carried only by `MemberJoinedAt`, which is the variant used whenever the\n * invitation expires \u2014 and since core clamps every invitation to\n * `MAX_INVITATION_VALIDITY_SECS`, that is every invitation. The variant is\n * inferred from the invitation rather than selected by a flag: an expiring\n * invitation joined with plain `MemberJoined` is refused at apply with\n * \"expiration is set but joined_at is absent\", which is not a mistake worth\n * leaving available.\n */\n readonly joinedAt?: number | bigint;\n}\n\n/**\n * Sign a `MemberJoined` (or `MemberJoinedAt`) namespace op and return it\n * borsh-encoded and hex \u2014 the `signedOp` that `admitJoin` takes.\n */\nexport async function signMemberJoinOp(input: SignMemberJoinInput): Promise<string> {\n const parents = input.parentOpHashes ?? [];\n const credential = fromHex(input.credential, 'credential', input.credential.length / 2);\n\n // An invitation that expires must be claimed with `MemberJoinedAt`, which\n // carries `joined_at` between the invitation and the credential. Choosing the\n // variant from the invitation keeps the two in step: the discriminant and the\n // presence of that field are one decision, and splitting them produces bytes\n // that decode into the wrong shape rather than failing to decode.\n const expires = BigInt(input.invitation.invitation.expiration_timestamp ?? 0) !== 0n;\n const joinedAt =\n input.joinedAt ?? BigInt(Math.floor(Date.now() / 1000));\n\n const rootOp = expires\n ? concat(\n new Uint8Array([ROOT_OP.MemberJoinedAt]),\n fromHex(input.member, 'member', 32),\n encodeSignedInvitation(input.invitation),\n u64le(joinedAt),\n credential,\n )\n : concat(\n new Uint8Array([ROOT_OP.MemberJoined]),\n fromHex(input.member, 'member', 32),\n encodeSignedInvitation(input.invitation),\n credential,\n );\n\n const op = concat(new Uint8Array([NAMESPACE_OP_ROOT]), rootOp);\n\n const key = await importSigningKey(input.deviceSecret);\n const signer = await derivePublicKey(input.deviceSecret);\n\n const signable = concat(\n new Uint8Array([SIGNED_NAMESPACE_OP_SCHEMA_VERSION]),\n fromHex(input.namespaceId, 'namespaceId', 32),\n u32le(parents.length),\n ...parents.map((p, i) => fromHex(p, `parentOpHashes[${i}]`, 32)),\n signer,\n u64le(input.nonce),\n op,\n );\n\n const signature = new Uint8Array(\n await crypto.subtle.sign('Ed25519', key, concat(NAMESPACE_SIGN_DOMAIN, signable)),\n );\n\n // The signed struct repeats the signable fields, then the signature. The domain\n // is a signing prefix only and is never part of the encoded op.\n return hex(concat(signable, signature));\n}\n", "// Member capability bitmask constants \u2014 mirrors core's `MemberCapabilities`\n// (crates/context/config/src/lib.rs). The value stored per-member is a u32\n// bitmask. Core currently assigns bits 0..=8; bits 9 and above are unassigned\n// and may be claimed by future core versions, so an application MUST NOT\n// assume any particular bit is safe for its own use unless core documents it\n// as reserved for applications.\n\n/**\n * Capability bits as defined by core's `MemberCapabilities`.\n *\n * The per-member value is a u32 bitmask. Core currently assigns bits 0..=8\n * (the entries below); bits 9 and above are unassigned \u2014 do not repurpose\n * them for application data, as a future core release may claim them.\n */\nexport const CAPABILITIES = {\n CAN_CREATE_CONTEXT: 1 << 0,\n CAN_INVITE_MEMBERS: 1 << 1,\n CAN_JOIN_OPEN_SUBGROUPS: 1 << 2,\n MANAGE_MEMBERS: 1 << 3,\n MANAGE_APPLICATION: 1 << 4,\n CAN_CREATE_SUBGROUP: 1 << 5,\n CAN_DELETE_SUBGROUP: 1 << 6,\n CAN_MANAGE_VISIBILITY: 1 << 7,\n CAN_MANAGE_METADATA: 1 << 8,\n} as const;\n\nexport type CapabilityName = keyof typeof CAPABILITIES;\nexport type CapabilityBit = (typeof CAPABILITIES)[CapabilityName];\n\n/**\n * Returns true if `mask` has every bit of `cap` set. Both operands are\n * coerced to unsigned 32-bit (`>>> 0`) before comparing so a high bit such\n * as `1 << 31` doesn't fall foul of `&` yielding a signed result.\n */\nexport function hasCap(mask: number, cap: number): boolean {\n const capU32 = cap >>> 0;\n return ((mask & capU32) >>> 0) === capU32;\n}\n\n/** Returns `mask` with every bit of `cap` set (u32-normalized). */\nexport function withCap(mask: number, cap: number): number {\n return (mask | cap) >>> 0;\n}\n\n/** Returns `mask` with every bit of `cap` cleared (u32-normalized). */\nexport function withoutCap(mask: number, cap: number): number {\n return (mask & ~cap) >>> 0;\n}\n", "/**\n * Local-node discovery.\n *\n * Calimero dev/desktop nodes expose a public, unauthenticated health endpoint\n * at `GET {nodeUrl}/admin-api/health` that returns `{ \"data\": { \"status\":\n * \"alive\" } }`. The most common local layouts run on a small, well-known set of\n * ports, so instead of forcing the user to type a URL we probe those ports and\n * offer whatever is actually running.\n */\n\n/**\n * Default ports probed when discovering local nodes. Covers the two-node dev\n * stacks used across the Calimero apps (RPC + alt ports for node1 / node2).\n */\nexport const DEFAULT_LOCAL_NODE_PORTS = [2428, 2429, 2528, 2529] as const;\n\n/** Host used to build local candidate URLs. */\nconst LOCAL_HOST = 'localhost';\n\n/** Per-probe timeout. A reachable local node answers almost instantly; a\n * closed port rejects fast, but a firewalled/black-holed one can hang, so we\n * cap each probe. */\nconst DEFAULT_PROBE_TIMEOUT_MS = 2000;\n\nexport interface DiscoverLocalNodesOptions {\n /** Ports to probe. Defaults to {@link DEFAULT_LOCAL_NODE_PORTS}. */\n ports?: readonly number[];\n /** Per-probe timeout in ms. Defaults to 2000. */\n timeoutMs?: number;\n /** Abort the whole discovery (e.g. when the modal closes). */\n signal?: AbortSignal;\n}\n\n/** Build the canonical base URL for a local node on the given port. */\nexport function localNodeUrl(port: number): string {\n return `http://${LOCAL_HOST}:${port}`;\n}\n\n/**\n * Resolve an API `path` against a node `baseUrl`. Ensures the base ends with a\n * slash first, so a base that carries a path prefix (e.g. a `NODE_PATH_PREFIX`\n * deployment like `http://host/node1`) keeps that segment instead of having it\n * stripped by relative URL resolution.\n */\nexport function nodeEndpoint(baseUrl: string, path: string): string {\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n return new URL(path, base).toString();\n}\n\n/**\n * Probe a single node's health endpoint. Resolves `true` only when the node\n * answers with a 2xx and (when the body is JSON) reports a non-dead status.\n * Any network error, timeout, or non-ok response resolves `false` \u2014 never\n * throws (except on an external abort, which is swallowed as `false`).\n */\nexport async function probeNodeHealth(\n baseUrl: string,\n options: { timeoutMs?: number; signal?: AbortSignal } = {},\n): Promise<boolean> {\n const { timeoutMs = DEFAULT_PROBE_TIMEOUT_MS, signal } = options;\n\n // Already cancelled before we start \u2014 don't fetch, and don't register a\n // timer or listener that would then need cleanup.\n if (signal?.aborted) return false;\n\n // Per-probe timeout, also linked to the caller's abort signal so closing the\n // modal cancels every in-flight probe. Bind the signal to a local so the\n // cleanup below stays symmetric with registration without re-narrowing.\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n const abortSignal = signal;\n if (abortSignal) abortSignal.addEventListener('abort', onAbort, { once: true });\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const url = nodeEndpoint(baseUrl, 'admin-api/health');\n const res = await fetch(url, {\n method: 'GET',\n signal: controller.signal,\n });\n\n if (!res.ok) return false;\n\n // Health body is `{ data: { status: \"alive\" } }`, but tolerate plain\n // `{ status }` and non-JSON 2xx responses. A *missing* status is treated as\n // alive (the 2xx is enough); a status that is present but not \"alive\"\n // (including an explicit `null`) is treated as unhealthy.\n try {\n const body = (await res.json()) as\n | { data?: { status?: string | null }; status?: string | null }\n | undefined;\n const status =\n body?.data?.status !== undefined ? body?.data?.status : body?.status;\n if (status === undefined) return true;\n return typeof status === 'string' && status.toLowerCase() === 'alive';\n } catch {\n return true;\n }\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n if (abortSignal) abortSignal.removeEventListener('abort', onAbort);\n }\n}\n\n/**\n * Probe the configured local ports in parallel and return the base URLs that\n * responded as healthy, in the same order as the `ports` argument (which\n * defaults to ascending). Returns an empty array when nothing local is running.\n */\nexport async function discoverLocalNodes(\n options: DiscoverLocalNodesOptions = {},\n): Promise<string[]> {\n const { ports = DEFAULT_LOCAL_NODE_PORTS, timeoutMs, signal } = options;\n\n const results = await Promise.all(\n ports.map(async (port) => {\n const url = localNodeUrl(port);\n const ok = await probeNodeHealth(url, { timeoutMs, signal });\n return ok ? url : null;\n }),\n );\n\n return results.filter((url): url is string => url !== null);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// Mero.js - Pure JavaScript SDK for Calimero\n// This will contain the pure JavaScript SDK without React dependencies\n\n// Main SDK class\nexport { MeroJs, createMeroJs } from './mero-js.js';\nexport type { MeroJsConfig, TokenData } from './mero-js.js';\n\n// HTTP client module (Web Standards based)\nexport * from './http-client/index.js';\n\n// Auth API client\nexport * from './auth-api/index.js';\n\n// Admin API client\nexport * from './admin-api/index.js';\n\n// Auth utilities\nexport { parseAuthCallback, buildAuthLoginUrl } from './auth/index.js';\nexport type { AuthCallbackResult, AuthLoginOptions } from './auth/index.js';\n\n// Token store\nexport { MemoryTokenStore, LocalStorageTokenStore } from './token-store/index.js';\nexport type { TokenStore } from './token-store/index.js';\n\n// RPC client\nexport { RpcClient, RpcError } from './rpc/index.js';\nexport type { MigrateMyEntriesSummary } from './rpc/index.js';\nexport type { ExecuteParams } from './rpc/index.js';\n\n// Events (SSE / WebSocket)\nexport { SseClient, WsClient } from './events/index.js';\nexport type {\n SseEventData,\n WsEventData,\n AppVersionChangedEvent,\n GroupMembershipEventData,\n GroupMigrationEventData,\n MigrationStartedData,\n MigrationProgressData,\n CascadeProgressData,\n MigrationCompletedData,\n} from './events/index.js';\n\n// Ephemeral presence (cursors / typing / online)\nexport { EphemeralClient, jsonCodec } from './ephemeral/index.js';\nexport type { Codec, EphemeralEntry } from './ephemeral/index.js';\n\n// Cloud client (enable-HA, disable-HA)\nexport * from './cloud/index.js';\n\n// Warrant signing \u2014 mint the author's consent for a relay to run one intent\nexport { signWarrant, intentHash } from './warrant/index.js';\nexport {\n signDeviceCert,\n mintDeviceId,\n deviceCertPayload,\n accountForRoot,\n} from './device-cert/index.js';\nexport type { DeviceCertInput } from './device-cert/index.js';\nexport {\n signMemberJoinOp,\n encodeSignedInvitation,\n SIGNED_NAMESPACE_OP_SCHEMA_VERSION,\n} from './namespace-op/index.js';\nexport type { SignMemberJoinInput } from './namespace-op/index.js';\nexport type { WarrantInput } from './warrant/index.js';\n\n// Member capability bitmask constants & helpers\nexport * from './capabilities.js';\n\n// Utilities\nexport {\n DEFAULT_LOCAL_NODE_PORTS,\n localNodeUrl,\n nodeEndpoint,\n probeNodeHealth,\n discoverLocalNodes,\n} from './nodeDiscovery.js';\nexport type { DiscoverLocalNodesOptions } from './nodeDiscovery.js';\n", "// Utility for combining multiple AbortSignals\nexport function combineSignals(\n signals: Array<AbortSignal | undefined>,\n): AbortSignal | undefined {\n const list = signals.filter(Boolean) as AbortSignal[];\n if (list.length === 0) return undefined;\n\n // Prefer native any(), but fall back if unavailable or it throws\n const AbortSignalAny = AbortSignal as {\n any?: (signals: AbortSignal[]) => AbortSignal;\n };\n if (typeof AbortSignalAny.any === 'function') {\n try {\n return AbortSignalAny.any(list);\n } catch {\n // Fall through to manual implementation\n }\n }\n\n const controller = new AbortController();\n const onAbort = (evt: Event) => {\n controller.abort((evt.target as AbortSignal).reason);\n for (const s of list) s.removeEventListener('abort', onAbort);\n };\n\n for (const s of list) {\n if (s.aborted) return AbortSignal.abort(s.reason);\n s.addEventListener('abort', onAbort, { once: true });\n }\n\n return controller.signal;\n}\n\n// Helper to create a timeout signal\nexport function createTimeoutSignal(timeoutMs: number): AbortSignal {\n // Use AbortSignal.timeout if available (Node 18.17+, modern browsers)\n if (typeof AbortSignal.timeout === 'function') {\n return AbortSignal.timeout(timeoutMs);\n }\n\n // Fallback for older environments\n const controller = new AbortController();\n setTimeout(() => {\n controller.abort(new DOMException('Timeout', 'TimeoutError'));\n }, timeoutMs);\n\n return controller.signal;\n}\n", "// ErrorResponse import removed as it's not used\nimport {\n HttpClient,\n Transport,\n RequestOptions,\n ResponseParser,\n} from './http-types.js';\nimport { combineSignals, createTimeoutSignal } from './signal-utils.js';\n\n/**\n * `x-auth-error` reasons that mean the whole token family is gone.\n *\n * Refresh tokens are single-use (calimero-network/core#3083): presenting a\n * consumed refresh token is treated as token theft and the server revokes the\n * family. Refreshing or retrying afterwards is pointless \u2014 the only way out is\n * a fresh login.\n */\nconst TERMINAL_AUTH_ERRORS = new Set(['token_reuse', 'token_revoked']);\n\n/**\n * Pull the node's explanation out of an error body. Core answers every handled\n * failure with `{\"error\": \"<message>\"}` (`ApiError::into_response`); the nested\n * `{\"error\": {\"message\": ...}}` form is what proxies in front of a node emit.\n * Returns undefined for a non-JSON, empty, or envelope-less body.\n */\nfunction extractErrorMessage(bodyText?: string): string | undefined {\n if (!bodyText) return undefined;\n try {\n const error = (JSON.parse(bodyText) as { error?: unknown })?.error;\n if (typeof error === 'string' && error.trim() !== '') return error;\n const nested = (error as { message?: unknown } | null)?.message;\n if (typeof nested === 'string' && nested.trim() !== '') return nested;\n } catch {\n // Not JSON \u2014 the status line is all we can honestly report.\n }\n return undefined;\n}\n\n// Custom error class for HTTP errors\nexport class HTTPError extends Error {\n name = 'HTTPError';\n\n constructor(\n public status: number,\n public statusText: string,\n public url: string,\n public headers: Headers,\n public bodyText?: string, // cap at ~64KB\n ) {\n const explanation = extractErrorMessage(bodyText);\n super(\n explanation\n ? `HTTP ${status} ${statusText}: ${explanation}`\n : `HTTP ${status} ${statusText}`,\n );\n }\n\n toJSON(): {\n status: number;\n statusText: string;\n url: string;\n headers: Record<string, string>;\n bodyText?: string;\n } {\n return {\n status: this.status,\n statusText: this.statusText,\n url: this.url,\n headers: headersToRecord(this.headers),\n bodyText: this.bodyText,\n };\n }\n}\n\n/**\n * Terminal authentication error: the refresh-token family was revoked (single-use\n * refresh token replayed, or the token was explicitly revoked). Never retried and\n * never refreshed \u2014 apps should catch this and force a re-login.\n *\n * Extends {@link HTTPError} so existing `instanceof HTTPError` handling keeps working.\n */\nexport class AuthRevokedError extends HTTPError {\n name = 'AuthRevokedError';\n\n constructor(\n /** Value of the `x-auth-error` header, e.g. `token_reuse` or `token_revoked`. */\n public reason: string,\n status: number,\n statusText: string,\n url: string,\n headers: Headers,\n bodyText?: string,\n ) {\n super(status, statusText, url, headers, bodyText);\n this.message = `Authentication revoked (${reason}): HTTP ${status} ${statusText}`;\n }\n}\n\n// Helper function to convert Headers to Record\nfunction headersToRecord(headers: Headers): Record<string, string> {\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key] = value;\n });\n return record;\n}\n\n// Web Standards HTTP client implementation\nexport class WebHttpClient implements HttpClient {\n // Cache for concurrent refresh token calls to prevent race conditions\n private refreshTokenPromise: Promise<string> | null = null;\n // Cache for concurrent onTokenRefresh calls to prevent duplicate callbacks\n private onTokenRefreshPromise: Promise<void> | null = null;\n \n constructor(private transport: Transport) {}\n\n async get<T>(path: string, init?: RequestOptions): Promise<T> {\n return this.request<T>(path, { ...init, method: 'GET' });\n }\n\n async post<T>(\n path: string,\n body?: unknown,\n init?: RequestOptions,\n ): Promise<T> {\n return this.request<T>(path, {\n ...init,\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n headers: {\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n }\n\n async put<T>(\n path: string,\n body?: unknown,\n init?: RequestOptions,\n ): Promise<T> {\n return this.request<T>(path, {\n ...init,\n method: 'PUT',\n body: body ? JSON.stringify(body) : undefined,\n headers: {\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n }\n\n async delete<T>(path: string, init?: RequestOptions): Promise<T> {\n return this.request<T>(path, { ...init, method: 'DELETE' });\n }\n\n async patch<T>(\n path: string,\n body?: unknown,\n init?: RequestOptions,\n ): Promise<T> {\n return this.request<T>(path, {\n ...init,\n method: 'PATCH',\n body: body ? JSON.stringify(body) : undefined,\n headers: {\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n }\n\n async head(\n path: string,\n init?: RequestOptions,\n ): Promise<{ headers: Record<string, string>; status: number }> {\n const response = await this.makeRequest<Response>(path, {\n ...init,\n method: 'HEAD',\n parse: 'response',\n });\n return {\n headers: headersToRecord(response.headers),\n status: response.status,\n };\n }\n\n async request<T>(path: string, init?: RequestOptions): Promise<T> {\n return this.makeRequest<T>(path, init);\n }\n\n private async makeRequest<T>(\n path: string,\n init?: RequestOptions,\n retryCount = 0,\n requestStartTime?: number,\n ): Promise<T> {\n // Maximum retry attempts to prevent infinite loops\n const MAX_RETRY_ATTEMPTS = 1;\n const url = this.buildUrl(path);\n \n // Track request start time for timeout calculation (only on first attempt)\n // Use per-request start time to avoid corruption from concurrent requests\n const startTime = requestStartTime ?? Date.now();\n // Note: Tauri proxy script now handles AbortSignal, so we can use full RequestInit\n // Removed Tauri-specific minimal path - proxy script handles AbortSignal properly\n const signal = this.createAbortSignal(init);\n const headers = await this.buildHeaders(init?.headers);\n let headersObj: Record<string, string>;\n if (headers instanceof Headers) {\n headersObj = {};\n headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n } else {\n headersObj = headers;\n }\n \n const requestInit: RequestInit = {\n method: init?.method || 'GET',\n headers: headersObj,\n };\n \n // Check if body is a stream (ReadableStream) that can't be reused\n // Note: Blob is reusable, so it's not included here\n const isStreamBody = init?.body instanceof ReadableStream ||\n (typeof init?.body === 'object' && init?.body !== null && 'getReader' in init.body && !(init.body instanceof Blob));\n \n if (init?.body !== undefined && !isStreamBody) {\n requestInit.body = init.body;\n } else if (init?.body !== undefined && isStreamBody && retryCount === 0) {\n // Only include stream body on first attempt - can't retry with streams\n requestInit.body = init.body;\n }\n \n // For retries, calculate remaining timeout to prevent timeout reset\n // Track elapsed time and use remaining timeout for retry\n // Note: This is calculated before the request, so it doesn't include token refresh time\n // The actual remaining timeout check happens after token refresh completes\n let retrySignal: AbortSignal | undefined;\n if (retryCount > 0 && requestStartTime !== undefined) {\n const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;\n if (timeoutMs) {\n // Calculate elapsed time (will be recalculated after token refresh if needed)\n const elapsed = Date.now() - startTime;\n const remaining = Math.max(0, timeoutMs - elapsed);\n // Create signal with remaining timeout, preserving user's signal\n retrySignal = this.createAbortSignal({ ...init, timeoutMs: remaining });\n } else {\n // No timeout, just preserve user's signal\n retrySignal = this.createAbortSignal(init);\n }\n } else {\n retrySignal = signal;\n }\n \n if (retrySignal) {\n requestInit.signal = retrySignal;\n }\n \n if (this.transport.credentials !== undefined) {\n requestInit.credentials = this.transport.credentials;\n }\n \n if (init?.mode !== undefined) {\n requestInit.mode = init.mode;\n }\n if (init?.cache !== undefined) {\n requestInit.cache = init.cache;\n }\n if (init?.redirect !== undefined) {\n requestInit.redirect = init.redirect;\n }\n if (init?.referrer !== undefined) {\n requestInit.referrer = init.referrer;\n }\n if (init?.referrerPolicy !== undefined) {\n requestInit.referrerPolicy = init.referrerPolicy;\n }\n if (init?.integrity !== undefined) {\n requestInit.integrity = init.integrity;\n }\n if (init?.keepalive !== undefined) {\n requestInit.keepalive = init.keepalive;\n }\n\n try {\n const response = await this.transport.fetch(url, requestInit);\n\n if (!response.ok) {\n const bodyText = await this.getBodyText(response);\n const httpError = new HTTPError(\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n\n // Handle a revoked token family (single-use refresh token replayed, or an\n // explicitly revoked token). This is terminal: refreshing would only burn\n // another token and retrying would 401 again, so clear the tokens via the\n // onAuthRevoked hook and surface a distinguishable error.\n const authError = response.headers.get('x-auth-error');\n if (\n (response.status === 401 || response.status === 403) &&\n authError &&\n TERMINAL_AUTH_ERRORS.has(authError)\n ) {\n // Any in-flight refresh is based on a now-dead family \u2014 drop the caches.\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n\n if (this.transport.onAuthRevoked) {\n try {\n await this.transport.onAuthRevoked();\n } catch {\n // Never mask the auth error with a cleanup failure.\n }\n }\n\n throw new AuthRevokedError(\n authError,\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n }\n\n // Handle 401 with token_expired - attempt automatic token refresh\n const userAborted = init?.signal?.aborted === true;\n if (\n response.status === 401 &&\n this.transport.refreshToken &&\n authError === 'token_expired' &&\n retryCount < MAX_RETRY_ATTEMPTS &&\n !isStreamBody &&\n !userAborted\n ) {\n try {\n // Use cached refresh promise if one is in progress (prevents race conditions)\n let refreshPromise = this.refreshTokenPromise;\n if (!refreshPromise) {\n refreshPromise = this.transport.refreshToken();\n this.refreshTokenPromise = refreshPromise;\n }\n \n // Attempt to refresh the token\n const newToken = await refreshPromise;\n \n // Validate token - must be non-empty\n if (!newToken || newToken.trim() === '') {\n // Clear caches on error\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n throw new Error('Refresh token returned empty token');\n }\n \n // onTokenRefresh is required when refreshToken is provided\n // Without it, the new token cannot be stored and getAuthToken() will return the old token\n if (!this.transport.onTokenRefresh) {\n // Clear caches on error\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n throw new Error(\n 'onTokenRefresh callback is required when refreshToken is provided. ' +\n 'The callback must update the token storage so getAuthToken() returns the new token.'\n );\n }\n \n // Use cached onTokenRefresh promise if one is in progress (prevents duplicate callbacks)\n // This ensures onTokenRefresh is only called once per token refresh, even with concurrent requests\n let onTokenRefreshPromise = this.onTokenRefreshPromise;\n if (!onTokenRefreshPromise) {\n onTokenRefreshPromise = this.transport.onTokenRefresh(newToken);\n this.onTokenRefreshPromise = onTokenRefreshPromise;\n }\n \n // Update token via callback (only called once per refresh, even with concurrent requests)\n // Errors from onTokenRefresh callback should be preserved (don't mask as 401)\n // This helps developers debug token storage issues\n await onTokenRefreshPromise;\n \n // Clear caches after both refresh and callback complete\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n \n // Check if timeout has expired during token refresh\n // If so, throw the original 401 error instead of retrying with 0ms timeout\n // This prevents timeout/abort errors that obscure the root cause (expired token)\n const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;\n if (timeoutMs && requestStartTime !== undefined) {\n const elapsed = Date.now() - startTime;\n const remaining = timeoutMs - elapsed;\n if (remaining <= 0) {\n // Timeout expired during token refresh - throw original 401 error\n // This is better than retrying with 0ms timeout which would cause confusing timeout errors\n throw httpError;\n }\n }\n \n // Retry the request with the new token (increment retry count)\n // Preserve user's abort signal and start time in retry\n return this.makeRequest<T>(path, init, retryCount + 1, startTime);\n } catch (refreshError) {\n // Clear caches on error\n this.refreshTokenPromise = null;\n this.onTokenRefreshPromise = null;\n // Configuration errors (missing onTokenRefresh) should be thrown as-is\n if (refreshError instanceof Error && refreshError.message.includes('onTokenRefresh')) {\n throw refreshError;\n }\n // Errors from onTokenRefresh callback are already thrown above, so if we get here,\n // it's either a refreshToken() failure or empty token - throw original 401\n // This matches the PR description: \"If refresh fails, throws the original 401 error\"\n throw httpError;\n }\n }\n\n throw httpError;\n }\n\n return this.parseResponse<T>(response, init?.parse);\n } catch (error) {\n if (error instanceof HTTPError) {\n throw error;\n }\n // Preserve configuration errors (like missing onTokenRefresh)\n if (error instanceof Error && error.message.includes('onTokenRefresh')) {\n throw error;\n }\n throw new HTTPError(\n 0,\n 'Network Error',\n url,\n new Headers(),\n error instanceof Error ? error.message : 'Unknown error',\n );\n }\n }\n\n private buildUrl(path: string): string {\n // Handle absolute URLs\n if (path.startsWith('http://') || path.startsWith('https://')) {\n return path;\n }\n\n // Handle baseUrl with path\n const baseUrl = this.transport.baseUrl;\n if (path.startsWith('/')) {\n // If path starts with /, combine with baseUrl\n const base = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n return `${base}${path}`;\n } else {\n // If path doesn't start with /, append to baseUrl\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n return `${base}${path}`;\n }\n }\n\n private createAbortSignal(init?: RequestOptions): AbortSignal | undefined {\n const signals: AbortSignal[] = [];\n\n if (this.transport.defaultAbortSignal) {\n signals.push(this.transport.defaultAbortSignal);\n }\n\n if (init?.signal) {\n signals.push(init.signal);\n }\n\n const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;\n if (timeoutMs) {\n signals.push(createTimeoutSignal(timeoutMs));\n }\n\n return signals.length > 0 ? combineSignals(signals) : undefined;\n }\n\n private async buildHeaders(\n initHeaders?: HeadersInit,\n ): Promise<Record<string, string>> {\n const headers: Record<string, string> = {\n ...this.transport.defaultHeaders,\n };\n\n // Add auth token if available and not empty\n if (this.transport.getAuthToken) {\n try {\n const token = await this.transport.getAuthToken();\n if (token && token.trim() !== '') {\n headers.Authorization = `Bearer ${token}`;\n }\n } catch (error) {\n // Ignore auth token errors\n }\n }\n\n // Add init headers\n if (initHeaders) {\n if (initHeaders instanceof Headers) {\n initHeaders.forEach((value, key) => {\n headers[key] = value;\n });\n } else if (Array.isArray(initHeaders)) {\n initHeaders.forEach(([key, value]) => {\n headers[key] = value;\n });\n } else {\n Object.assign(headers, initHeaders);\n }\n }\n\n return headers;\n }\n\n private async parseResponse<T>(\n response: Response,\n parse?: ResponseParser,\n ): Promise<T> {\n switch (parse) {\n case 'text':\n return (await response.text()) as T;\n case 'blob':\n return (await response.blob()) as T;\n case 'arrayBuffer':\n return (await response.arrayBuffer()) as T;\n case 'response':\n return response as T;\n case 'json':\n default: {\n // Tolerate empty 2xx bodies (e.g. 204 No Content from delete/resync):\n // `response.json()` throws on '', so read text and return null when empty.\n const text = await response.text();\n if (!text) return null as T;\n try {\n return JSON.parse(text) as T;\n } catch {\n // Non-JSON body on a 2xx (e.g. an HTML error page) \u2014 surface a clear\n // error with a snippet instead of a bare SyntaxError.\n throw new Error(\n `Expected a JSON response (status ${response.status}) but body was not JSON: ${text.slice(0, 200)}`,\n );\n }\n }\n }\n }\n\n private async getBodyText(response: Response): Promise<string> {\n try {\n const text = await response.text();\n return text.length > 65536 ? text.slice(0, 65536) + '...' : text;\n } catch {\n return '';\n }\n }\n}\n", "import { WebHttpClient } from './web-client.js';\nimport { Transport, HttpClient } from './http-types.js';\n\n// Factory function to create HTTP client with sensible defaults\nexport function createHttpClient(transport: Transport): HttpClient {\n return new WebHttpClient(transport);\n}\n\n// Factory function for browser environments\nexport function createBrowserHttpClient(options: {\n baseUrl: string;\n getAuthToken?: () => Promise<string | undefined>;\n onTokenRefresh?: (newToken: string) => Promise<void>;\n /**\n * Callback to refresh the access token when a 401 error with 'token_expired' is detected.\n * Should return the new access token, or throw an error if refresh fails.\n * If provided, the client will automatically retry the request after a successful refresh.\n */\n refreshToken?: () => Promise<string>;\n /**\n * Callback invoked when the server reports a revoked token family\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal \u2014 the request is\n * never retried; clear stored tokens and force a re-login.\n */\n onAuthRevoked?: () => Promise<void> | void;\n defaultHeaders?: Record<string, string>;\n timeoutMs?: number;\n credentials?: RequestCredentials;\n defaultAbortSignal?: AbortSignal;\n}): HttpClient {\n const transport: Transport = {\n // Wrap fetch in arrow function to prevent \"Illegal invocation\" error\n // This preserves the correct 'this' context when fetch is called\n fetch: (url: RequestInfo | URL, init?: RequestInit) => globalThis.fetch(url, init),\n baseUrl: options.baseUrl,\n getAuthToken: options.getAuthToken,\n onTokenRefresh: options.onTokenRefresh,\n refreshToken: options.refreshToken,\n onAuthRevoked: options.onAuthRevoked,\n defaultHeaders: options.defaultHeaders,\n timeoutMs: options.timeoutMs,\n credentials: options.credentials, // No default credentials\n defaultAbortSignal: options.defaultAbortSignal,\n };\n\n return createHttpClient(transport);\n}\n\n// Factory function for Node.js environments\nexport function createNodeHttpClient(options: {\n baseUrl: string;\n fetch?: typeof fetch; // Allow injection of undici.fetch or other fetch implementations\n getAuthToken?: () => Promise<string | undefined>;\n onTokenRefresh?: (newToken: string) => Promise<void>;\n /**\n * Callback to refresh the access token when a 401 error with 'token_expired' is detected.\n * Should return the new access token, or throw an error if refresh fails.\n * If provided, the client will automatically retry the request after a successful refresh.\n */\n refreshToken?: () => Promise<string>;\n /**\n * Callback invoked when the server reports a revoked token family\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal \u2014 the request is\n * never retried; clear stored tokens and force a re-login.\n */\n onAuthRevoked?: () => Promise<void> | void;\n defaultHeaders?: Record<string, string>;\n timeoutMs?: number;\n credentials?: RequestCredentials;\n defaultAbortSignal?: AbortSignal;\n}): HttpClient {\n // Use provided fetch or try to use global fetch (Node 18+)\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n if (!fetchImpl) {\n throw new Error(\n 'No fetch implementation available. Please provide a fetch implementation ' +\n '(e.g., undici.fetch) or use Node.js 18+ which has native fetch support.',\n );\n }\n\n // Check if we're using the default globalThis.fetch to preserve context\n // When fetchImpl is globalThis.fetch, we must call it directly, not through a variable\n // Custom fetch implementations (like undici.fetch) can be called through the variable\n const isDefaultFetch = fetchImpl === globalThis.fetch;\n\n const transport: Transport = {\n // Wrap fetch in arrow function to prevent \"Illegal invocation\" error\n // For globalThis.fetch, call it directly to preserve 'this' context\n // For custom implementations, calling through the variable is safe\n fetch: isDefaultFetch\n ? (url: RequestInfo | URL, init?: RequestInit) => globalThis.fetch(url, init)\n : (url: RequestInfo | URL, init?: RequestInit) => fetchImpl(url, init),\n baseUrl: options.baseUrl,\n getAuthToken: options.getAuthToken,\n onTokenRefresh: options.onTokenRefresh,\n refreshToken: options.refreshToken,\n onAuthRevoked: options.onAuthRevoked,\n defaultHeaders: options.defaultHeaders,\n timeoutMs: options.timeoutMs,\n credentials: options.credentials, // Node.js doesn't have default credentials\n defaultAbortSignal: options.defaultAbortSignal,\n };\n\n return createHttpClient(transport);\n}\n\n// Universal factory that works in both environments\nexport function createUniversalHttpClient(options: {\n baseUrl: string;\n fetch?: typeof fetch;\n getAuthToken?: () => Promise<string | undefined>;\n onTokenRefresh?: (newToken: string) => Promise<void>;\n /**\n * Callback to refresh the access token when a 401 error with 'token_expired' is detected.\n * Should return the new access token, or throw an error if refresh fails.\n * If provided, the client will automatically retry the request after a successful refresh.\n */\n refreshToken?: () => Promise<string>;\n /**\n * Callback invoked when the server reports a revoked token family\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal \u2014 the request is\n * never retried; clear stored tokens and force a re-login.\n */\n onAuthRevoked?: () => Promise<void> | void;\n defaultHeaders?: Record<string, string>;\n timeoutMs?: number;\n credentials?: RequestCredentials;\n defaultAbortSignal?: AbortSignal;\n}): HttpClient {\n // Try to detect environment and use appropriate factory\n if (typeof window !== 'undefined') {\n // Browser environment\n return createBrowserHttpClient(options);\n } else {\n // Node.js environment\n return createNodeHttpClient(options);\n }\n}\n", "// Retry helper for HTTP requests\nexport interface RetryOptions {\n attempts?: number;\n}\n\n// Error types for retry logic\ninterface ErrorWithName extends Error {\n name: string;\n}\n\ninterface ErrorWithStatus extends Error {\n status: number;\n}\n\ninterface ErrorWithHeaders extends Error {\n headers?: Headers;\n}\n\n// Default retry condition - retry on network errors and 5xx status codes\nfunction defaultRetryCondition(error: Error, attempt: number): boolean {\n // Don't retry on the last attempt\n if (attempt <= 0) return false;\n\n // Distinguish timeout vs. user abort:\n // - Timeout: name === 'TimeoutError' (per spec/platforms)\n // - User abort: name === 'AbortError'\n const errorWithName = error as ErrorWithName;\n const name = errorWithName?.name;\n if (name === 'TimeoutError') return true;\n if (name === 'AbortError') return false;\n\n // HTTP 5xx and 429 (including HTTPError from web-client)\n const errorWithStatus = error as ErrorWithStatus;\n if (\n 'status' in errorWithStatus &&\n typeof errorWithStatus.status === 'number'\n ) {\n const status = errorWithStatus.status;\n return status >= 500 || status === 429;\n }\n // Network TypeError (DNS/reset) is reasonably retryable\n if (name === 'TypeError') return true;\n\n return false;\n}\n\n// Calculate delay with exponential backoff and jitter\nfunction calculateDelay(attempt: number): number {\n const baseDelayMs = 250; // Base 250ms as per spec\n const delay = baseDelayMs * Math.pow(2, attempt - 1);\n\n // Add \u00B120% jitter to reduce stampedes\n const jitter = (Math.random() - 0.5) * 0.4 * delay;\n return Math.max(0, delay + jitter);\n}\n\n// Retry helper function with new signature\nexport async function withRetry<T>(\n fn: (attempt: number) => Promise<T>,\n options: RetryOptions = {},\n): Promise<T> {\n const { attempts = 3 } = options;\n\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= attempts; attempt++) {\n try {\n return await fn(attempt);\n } catch (error) {\n lastError = error as Error;\n\n // Check if we should retry (this handles the last attempt check)\n if (!defaultRetryCondition(lastError, attempts - attempt)) {\n throw lastError;\n }\n\n // Calculate delay\n let delayMs = calculateDelay(attempt);\n\n // Check for Retry-After header if it's an HTTP error\n const errorWithHeaders = lastError as ErrorWithHeaders;\n const hdrs = errorWithHeaders.headers;\n const retryAfter = hdrs?.get?.('Retry-After');\n if (retryAfter) {\n // If it's a number, treat as seconds\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n delayMs = Math.max(delayMs, seconds * 1000);\n } else {\n // If it's a date, calculate the difference\n const date = new Date(retryAfter);\n if (!isNaN(date.getTime())) {\n const waitTime = Math.max(0, date.getTime() - Date.now());\n // Cap wait at 60s per attempt as per spec\n delayMs = Math.max(delayMs, Math.min(waitTime, 60000));\n }\n }\n }\n\n // Wait before retrying\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n throw lastError || new Error('Retry failed without error');\n}\n\n// Helper to create a retry-enabled HTTP client method\nexport function createRetryableMethod<T extends unknown[], R>(\n method: (...args: T) => Promise<R>,\n retryOptions: RetryOptions = {},\n) {\n return async (...args: T): Promise<R> => {\n return withRetry(() => method(...args), retryOptions);\n };\n}\n", "import { HttpClient } from '../http-client/index.js';\nimport {\n // Common types\n ApiResponse,\n // Health and Status\n HealthResponse,\n IdentityResponse,\n ProvidersResponse,\n // Authentication\n TokenRequest,\n TokenResponse,\n RefreshTokenRequest,\n // Mock Token (testing)\n MockTokenRequest,\n // Token Management\n RevokeTokenRequest,\n RevokeTokenResponse,\n // Key Management\n CreateKeyRequest,\n CreateKeyResponse,\n DeleteKeyResponse,\n RootKey,\n // Client Management\n ClientKey,\n GenerateClientKeyRequest,\n DeleteClientResponse,\n // Permissions\n PermissionResponse,\n UpdateKeyPermissionsRequest,\n} from './auth-types.js';\n\nexport class AuthApiClient {\n constructor(private httpClient: HttpClient) {}\n\n // Health and Status Endpoints\n async getHealth(): Promise<HealthResponse> {\n const response =\n await this.httpClient.get<ApiResponse<HealthResponse>>('/auth/health');\n if (!response.data) {\n throw new Error('Health response data is null');\n }\n return response.data;\n }\n\n async getIdentity(): Promise<IdentityResponse> {\n const response =\n await this.httpClient.get<ApiResponse<IdentityResponse>>(\n '/admin/identity',\n );\n if (!response.data) {\n throw new Error('Identity response data is null');\n }\n return response.data;\n }\n\n async getProviders(): Promise<ProvidersResponse> {\n const response =\n await this.httpClient.get<ApiResponse<ProvidersResponse>>(\n '/auth/providers',\n );\n if (!response.data) {\n throw new Error('Providers response data is null');\n }\n return response.data;\n }\n\n // Authentication Endpoints\n async getLoginPage(): Promise<string> {\n return this.httpClient.get<string>('/auth/login', { parse: 'text' });\n }\n\n async generateTokens(request: TokenRequest): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/auth/token', request);\n }\n\n async refreshToken(request: RefreshTokenRequest): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/auth/refresh', request);\n }\n\n async generateMockTokens(request: MockTokenRequest): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/auth/mock-token', request);\n }\n\n async validateToken(token: string): Promise<{\n valid: boolean;\n headers: Record<string, string>;\n status: number;\n }> {\n try {\n const response = await this.validateTokenGet(token);\n return {\n valid: response.status === 200,\n headers: response.headers,\n status: response.status,\n };\n } catch (error) {\n return {\n valid: false,\n headers: {},\n status: 401,\n };\n }\n }\n\n async validateTokenGet(\n token: string,\n ): Promise<{ status: number; headers: Record<string, string> }> {\n const response = await this.httpClient.head('/auth/validate', {\n headers: { Authorization: `Bearer ${token}` },\n });\n return {\n status: response.status,\n headers: response.headers,\n };\n }\n\n // Token Management Endpoints\n // NOTE: node auth status lives on AdminApiClient.isAuthed() (/admin-api/is-authed);\n // there is no /auth/is-authed on the auth service.\n async revokeTokens(\n request: RevokeTokenRequest,\n ): Promise<RevokeTokenResponse> {\n const response = await this.httpClient.post<ApiResponse<RevokeTokenResponse>>(\n '/admin/revoke',\n request,\n );\n if (!response.data) {\n throw new Error('Revoke tokens response data is null');\n }\n return response.data;\n }\n\n // Key Management Endpoints\n async listRootKeys(): Promise<RootKey[]> {\n const response =\n await this.httpClient.get<ApiResponse<RootKey[]>>('/admin/keys');\n if (!response.data) {\n throw new Error('Root keys response data is null');\n }\n return response.data;\n }\n\n async createRootKey(request: CreateKeyRequest): Promise<CreateKeyResponse> {\n const response = await this.httpClient.post<ApiResponse<CreateKeyResponse>>(\n '/admin/keys',\n request,\n );\n if (!response.data) {\n throw new Error('Create root key response data is null');\n }\n return response.data;\n }\n\n async deleteRootKey(keyId: string): Promise<DeleteKeyResponse> {\n return this.httpClient.delete<DeleteKeyResponse>(`/admin/keys/${keyId}`);\n }\n\n // Client Management Endpoints\n async listClientKeys(): Promise<ClientKey[]> {\n const response = await this.httpClient.get<ApiResponse<ClientKey[]>>(\n '/admin/keys/clients',\n );\n if (!response.data) {\n throw new Error('Client keys response data is null');\n }\n return response.data;\n }\n\n async generateClientKey(\n request: GenerateClientKeyRequest,\n ): Promise<TokenResponse> {\n return this.httpClient.post<TokenResponse>('/admin/client-key', request);\n }\n\n async deleteClientKey(\n keyId: string,\n clientId: string,\n ): Promise<DeleteClientResponse> {\n return this.httpClient.delete<DeleteClientResponse>(\n `/admin/keys/${keyId}/clients/${clientId}`,\n );\n }\n\n // Permission Management Endpoints\n async getKeyPermissions(keyId: string): Promise<PermissionResponse> {\n return this.httpClient.get<PermissionResponse>(\n `/admin/keys/${keyId}/permissions`,\n );\n }\n\n async updateKeyPermissions(\n keyId: string,\n changes: UpdateKeyPermissionsRequest,\n ): Promise<PermissionResponse> {\n // Core expects an { add, remove } delta, not a { permissions } replacement.\n return this.httpClient.put<PermissionResponse>(\n `/admin/keys/${keyId}/permissions`,\n { add: changes.add, remove: changes.remove },\n );\n }\n}\n", "import { AuthApiClient } from './auth-client.js';\nimport { AuthApiClientConfig } from './auth-types.js';\nimport { HttpClient } from '../http-client/index.js';\n\n// Mock HTTP client for testing\nclass MockHttpClient implements HttpClient {\n async get<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async post<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async put<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async delete<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async patch<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async head(): Promise<{ headers: Record<string, string>; status: number }> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n async request<T>(): Promise<T> {\n throw new Error(\n 'HTTP client not implemented - use createAuthApiClientFromHttpClient with a real HTTP client',\n );\n }\n}\n\n// Factory functions for creating Auth API clients\nexport function createBrowserAuthApiClient(\n _config: AuthApiClientConfig,\n): AuthApiClient {\n const httpClient = new MockHttpClient();\n return new AuthApiClient(httpClient);\n}\n\nexport function createNodeAuthApiClient(\n _config: AuthApiClientConfig,\n): AuthApiClient {\n const httpClient = new MockHttpClient();\n return new AuthApiClient(httpClient);\n}\n\nexport function createAuthApiClient(\n _config: AuthApiClientConfig,\n): AuthApiClient {\n const httpClient = new MockHttpClient();\n return new AuthApiClient(httpClient);\n}\n\nexport function createAuthApiClientFromHttpClient(\n httpClient: HttpClient,\n _config: AuthApiClientConfig,\n): AuthApiClient {\n return new AuthApiClient(httpClient);\n}\n", "import { HttpClient, withRetry } from '../http-client/index.js';\nimport type {\n HealthStatus,\n AdminAuthStatus,\n InstallApplicationRequest,\n InstallApplicationResponseData,\n InstallDevApplicationRequest,\n UninstallApplicationResponseData,\n ListApplicationsResponseData,\n GetApplicationResponseData,\n ApplicationVersionEntry,\n GetApplicationAbiResponseData,\n GetLatestVersionResponseData,\n ListPackagesResponseData,\n ListVersionsResponseData,\n RegistryBundleManifest,\n CreateContextRequest,\n CreateContextResponseData,\n DeleteContextRequest,\n DeleteContextResponseData,\n GetContextsResponseData,\n Context,\n GenerateContextIdentityResponseData,\n GetContextIdentitiesResponseData,\n JoinContextResponseData,\n JoinSubgroupInheritanceResponseData,\n ContextGroupResponseData,\n ContextStorageResponseData,\n InviteSpecializedNodeRequest,\n InviteSpecializedNodeResponseData,\n UpdateContextApplicationRequest,\n ResyncContextRequest,\n ResyncContextResponseData,\n ContextsWithExecutorsResponseData,\n UploadBlobRequest,\n UploadBlobResponseData,\n DeleteBlobResponseData,\n ListBlobsResponseData,\n GetBlobInfoResponseData,\n CreateContextAliasRequest,\n CreateApplicationAliasRequest,\n CreateAliasResponseData,\n LookupAliasResponseData,\n DeleteAliasResponseData,\n ListAliasesResponseData,\n ListNamespacesResponseData,\n CreateNamespaceRequest,\n CreateNamespaceResponseData,\n DeleteNamespaceRequest,\n DeleteNamespaceResponseData,\n CreateNamespaceInvitationRequest,\n CreateNamespaceInvitationResponseData,\n CreateRecursiveInvitationResponseData,\n JoinNamespaceRequest,\n JoinNamespaceResponseData,\n CreateGroupInNamespaceRequest,\n CreateGroupInNamespaceResponseData,\n SubgroupEntry,\n Namespace,\n NamespaceIdentity,\n NodeIdentity,\n GroupInfoResponseData,\n DeleteGroupRequest,\n DeleteGroupResponseData,\n ListGroupMembersResponseData,\n ListGroupContextsResponseData,\n AddGroupMembersRequest,\n RemoveGroupMembersRequest,\n UpdateMemberRoleRequest,\n MemberCapabilities,\n SetMemberCapabilitiesRequest,\n SetDefaultCapabilitiesRequest,\n SetSubgroupVisibilityRequest,\n SetTeeAdmissionPolicyRequest,\n GetTeeAdmissionPolicyResponseData,\n SetGroupMetadataRequest,\n SetMemberMetadataRequest,\n SetContextMetadataRequest,\n MetadataRecord,\n GetMetadataResponseData,\n SyncGroupRequest,\n SyncGroupResponseData,\n UpgradeGroupRequest,\n UpgradeGroupResponseData,\n GroupUpgradeStatusResponseData,\n MigrationStatus,\n CascadeStatusEntry,\n RetryGroupUpgradeRequest,\n RetryGroupUpgradeResponseData,\n ReparentGroupRequest,\n ReparentGroupResponseData,\n DetachContextFromGroupRequest,\n CreateGroupInvitationRequest,\n CreateGroupInvitationResponseData,\n CreateRecursiveGroupInvitationResponseData,\n JoinGroupRequest,\n JoinGroupResponseData,\n TeeInfoResponseData,\n TeeAttestRequest,\n TeeAttestResponseData,\n TeeVerifyQuoteRequest,\n TeeVerifyQuoteResponseData,\n PerformIntentRequest,\n PerformIntentResponseData,\n AdmitJoinRequest,\n AdmitJoinResponseData,\n} from './admin-types.js';\n\n/**\n * Helper: server wraps most responses in `{ data: T }`.\n * This extracts `.data` so callers get the inner payload directly. Null-safe so an\n * empty 2xx body (parsed as null) yields undefined instead of throwing.\n */\nfunction unwrap<T>(response: { data: T }): T {\n return response?.data as T;\n}\n\n/**\n * Compare two version strings by SemVer 2.0 precedence, ascending: negative if\n * `a < b`, positive if `a > b`, `0` if equal. Build metadata (`+...`) is stripped\n * and ignored. The numeric `major.minor.patch` core is compared field-by-field\n * (numerically when both parse, so `1.10.0 > 1.9.0`; a missing field is `0`). A\n * version WITH a pre-release ranks below the same core without one, and\n * pre-release identifiers compare per spec: dot-separated, numeric identifiers\n * numerically, alphanumeric lexically by ASCII, numeric below alphanumeric, and a\n * shorter set of identifiers loses when all preceding fields are equal.\n */\nexport function compareSemver(a: string, b: string): number {\n const [coreA, preA] = splitVersion(a);\n const [coreB, preB] = splitVersion(b);\n\n const na = coreA.split('.');\n const nb = coreB.split('.');\n const n = Math.max(na.length, nb.length);\n for (let i = 0; i < n; i++) {\n const c = compareSemverId(na[i] ?? '0', nb[i] ?? '0');\n if (c !== 0) return c;\n }\n\n // A pre-release ranks below the same core version with no pre-release.\n if (preA === undefined && preB === undefined) return 0;\n if (preA === undefined) return 1;\n if (preB === undefined) return -1;\n\n const pa = preA.split('.');\n const pb = preB.split('.');\n const m = Math.max(pa.length, pb.length);\n for (let i = 0; i < m; i++) {\n if (i >= pa.length) return -1; // shorter set loses when all preceding equal\n if (i >= pb.length) return 1;\n const c = compareSemverId(pa[i], pb[i]);\n if (c !== 0) return c;\n }\n return 0;\n}\n\n/** Drop build metadata and split the pre-release tail: `1.2.3-rc.1+b` -> `['1.2.3', 'rc.1']`. */\nfunction splitVersion(v: string): [string, string | undefined] {\n const core = v.split('+', 1)[0];\n const dash = core.indexOf('-');\n return dash === -1 ? [core, undefined] : [core.slice(0, dash), core.slice(dash + 1)];\n}\n\n/**\n * Compare one identifier: numerically when both are all-digits, else lexically by\n * ASCII with a numeric identifier ranking below an alphanumeric one. Fallback: a\n * non-numeric core component (loose/malformed input) is treated as a string, so\n * comparison never throws.\n */\nfunction compareSemverId(a: string, b: string): number {\n const na = /^\\d+$/.test(a);\n const nb = /^\\d+$/.test(b);\n if (na && nb) {\n const d = Number(a) - Number(b);\n return d < 0 ? -1 : d > 0 ? 1 : 0;\n }\n if (na) return -1;\n if (nb) return 1;\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/**\n * Fetch a URL from the (foreign-origin) registry with a per-attempt timeout and\n * retry on transient failures. Deliberately NOT routed through the node\n * `HttpClient`: that client attaches the node's bearer token to every request,\n * which must never leak to the registry's origin. Each attempt times out after\n * ~10s; network errors and 5xx are retried (2 retries, short backoff via the\n * shared `withRetry`), while a 4xx is a definitive answer and is not retried.\n * `kind`/`context` shape the error message so failures stay debuggable in logs.\n */\nasync function fetchRegistry(url: string, kind: string, context: string): Promise<Response> {\n return withRetry(\n async () => {\n const resp = await fetch(url, { signal: AbortSignal.timeout(10000) });\n if (!resp.ok) {\n // Carry `status` so withRetry retries 5xx but leaves 4xx to throw.\n const err = new Error(\n `registry ${kind} fetch failed (${resp.status}) for ${context}`,\n ) as Error & { status: number };\n err.status = resp.status;\n throw err;\n }\n return resp;\n },\n { attempts: 3 },\n );\n}\n\nexport class AdminApiClient {\n constructor(private httpClient: HttpClient) {}\n\n // ---- Health and Status (public, no auth) ----\n\n async healthCheck(): Promise<HealthStatus> {\n return unwrap(await this.httpClient.get<{ data: HealthStatus }>('/admin-api/health'));\n }\n\n async isAuthed(): Promise<AdminAuthStatus> {\n return this.httpClient.get<AdminAuthStatus>('/admin-api/is-authed');\n }\n\n // ---- Application Management ----\n\n /**\n * Install a published application by its `package@version` coordinates. The\n * node resolves and fetches them from its own configured `[registry]`, so no\n * URL is passed and none is accepted. A 502 means the node's source has\n * nothing published at those coordinates. This is the discrete \"download\"\n * step an Updates flow pairs with a subsequent `upgradeGroup`.\n */\n async installApplication(request: InstallApplicationRequest): Promise<InstallApplicationResponseData> {\n return unwrap(await this.httpClient.post<{ data: InstallApplicationResponseData }>('/admin-api/install-application', request));\n }\n\n /**\n * List a package's published versions from the registry, newest-first by\n * semver. Reads the registry's V2 bundle listing\n * (`GET {registry}/api/v2/bundles?package={package}`), taking each bundle's\n * `appVersion`. Registry-side data \u2014 distinct from the node's\n * installed-version list \u2014 and the source an Updates view compares against\n * the running `Context.applicationVersion` to detect \"a new version exists\".\n */\n async getRegistryVersions(registryUrl: string, packageName: string): Promise<string[]> {\n const url = new URL('/api/v2/bundles', new URL(registryUrl).origin);\n url.searchParams.set('package', packageName);\n const resp = await fetchRegistry(url.toString(), 'versions', packageName);\n const bundles = (await resp.json()) as RegistryBundleManifest[];\n return (Array.isArray(bundles) ? bundles : [])\n .map((b) => b.appVersion)\n .filter((v): v is string => typeof v === 'string')\n .sort((a, b) => compareSemver(b, a));\n }\n\n async installDevApplication(request: InstallDevApplicationRequest): Promise<InstallApplicationResponseData> {\n return unwrap(await this.httpClient.post<{ data: InstallApplicationResponseData }>('/admin-api/install-dev-application', request));\n }\n\n async uninstallApplication(appId: string): Promise<UninstallApplicationResponseData> {\n return unwrap(await this.httpClient.delete<{ data: UninstallApplicationResponseData }>(`/admin-api/applications/${appId}`));\n }\n\n async listApplications(): Promise<ListApplicationsResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListApplicationsResponseData }>('/admin-api/applications'));\n }\n\n async getApplication(appId: string): Promise<GetApplicationResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetApplicationResponseData }>(`/admin-api/applications/${appId}`));\n }\n\n /**\n * Installed-blob inventory for an application \u2014 one entry per locally installed\n * version. This is the *installed* inventory (source for a \"pick a version to\n * pin\" UI); the registry equivalent is `listPackageVersions`.\n */\n async listApplicationVersions(applicationId: string): Promise<ApplicationVersionEntry[]> {\n return unwrap(\n await this.httpClient.get<{ data: ApplicationVersionEntry[] }>(`/admin-api/applications/${applicationId}/versions`),\n );\n }\n\n /**\n * The application's embedded `wasm-abi/1` manifest. Omit `serviceName` for\n * single-service apps; core 400s if the ABI is absent or the name is ambiguous.\n */\n async getApplicationAbi(applicationId: string, serviceName?: string): Promise<GetApplicationAbiResponseData> {\n const query = serviceName ? `?service_name=${encodeURIComponent(serviceName)}` : '';\n return unwrap(\n await this.httpClient.get<{ data: GetApplicationAbiResponseData }>(\n `/admin-api/applications/${applicationId}/abi${query}`,\n ),\n );\n }\n\n // ---- Package Management ----\n\n async listPackages(): Promise<ListPackagesResponseData> {\n // Core returns this flat ({ packages: [...] }), not under `data`; tolerate both.\n const r = await this.httpClient.get<ListPackagesResponseData & { data?: ListPackagesResponseData }>(\n '/admin-api/packages',\n );\n return (r?.data ?? r) as ListPackagesResponseData;\n }\n\n async listPackageVersions(packageName: string): Promise<ListVersionsResponseData> {\n // Core returns this flat ({ versions: [...] }), not under `data`; tolerate both.\n const r = await this.httpClient.get<ListVersionsResponseData & { data?: ListVersionsResponseData }>(\n `/admin-api/packages/${encodeURIComponent(packageName)}/versions`,\n );\n return (r?.data ?? r) as ListVersionsResponseData;\n }\n\n async getLatestPackageVersion(packageName: string): Promise<GetLatestVersionResponseData> {\n return this.httpClient.get<GetLatestVersionResponseData>(\n `/admin-api/packages/${encodeURIComponent(packageName)}/latest`,\n );\n }\n\n // ---- Context Management ----\n\n async createContext(request: CreateContextRequest): Promise<CreateContextResponseData> {\n // Core requires `initializationParams` (no default); default it to an empty\n // byte array so callers that pass none don't get a 400.\n const body = { ...request, initializationParams: request.initializationParams ?? [] };\n return unwrap(await this.httpClient.post<{ data: CreateContextResponseData }>('/admin-api/contexts', body));\n }\n\n async deleteContext(contextId: string, request?: DeleteContextRequest): Promise<DeleteContextResponseData> {\n if (request) {\n return unwrap(\n await this.httpClient.request<{ data: DeleteContextResponseData }>(`/admin-api/contexts/${contextId}`, {\n method: 'DELETE',\n body: JSON.stringify(request),\n headers: { 'Content-Type': 'application/json' },\n }),\n );\n }\n return unwrap(await this.httpClient.delete<{ data: DeleteContextResponseData }>(`/admin-api/contexts/${contextId}`));\n }\n\n async getContexts(): Promise<GetContextsResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextsResponseData }>('/admin-api/contexts'));\n }\n\n async getContext(contextId: string): Promise<Context> {\n return unwrap(await this.httpClient.get<{ data: Context }>(`/admin-api/contexts/${contextId}`));\n }\n\n async getContextsForApplication(applicationId: string): Promise<GetContextsResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextsResponseData }>(`/admin-api/contexts/for-application/${applicationId}`));\n }\n\n // ---- Context Identity ----\n\n async generateContextIdentity(): Promise<GenerateContextIdentityResponseData> {\n return unwrap(await this.httpClient.post<{ data: GenerateContextIdentityResponseData }>('/admin-api/identity/context', {}));\n }\n\n async getContextIdentities(contextId: string): Promise<GetContextIdentitiesResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextIdentitiesResponseData }>(`/admin-api/contexts/${contextId}/identities`));\n }\n\n async getContextIdentitiesOwned(contextId: string): Promise<GetContextIdentitiesResponseData> {\n return unwrap(await this.httpClient.get<{ data: GetContextIdentitiesResponseData }>(`/admin-api/contexts/${contextId}/identities-owned`));\n }\n\n // ---- Context join (group membership) ----\n\n async joinContext(contextId: string): Promise<JoinContextResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: JoinContextResponseData }>(`/admin-api/contexts/${contextId}/join`, {}),\n );\n }\n\n // ---- Context group / storage / sync ----\n\n async getContextGroup(contextId: string): Promise<ContextGroupResponseData> {\n return unwrap(await this.httpClient.get<{ data: ContextGroupResponseData }>(`/admin-api/contexts/${contextId}/group`));\n }\n\n async getContextStorage(contextId: string): Promise<ContextStorageResponseData> {\n return unwrap(await this.httpClient.get<{ data: ContextStorageResponseData }>(`/admin-api/contexts/${contextId}/storage`));\n }\n\n async syncContext(contextId?: string): Promise<void> {\n await this.httpClient.post(`/admin-api/contexts/sync/${contextId ?? ''}`, {});\n }\n\n /**\n * Kick off a full state re-pull for a context (operator recovery for a\n * stranded context). `force` re-pulls even when the node does not flag the\n * context as stranded.\n */\n async resyncContext(\n contextId: string,\n request: ResyncContextRequest = {},\n ): Promise<ResyncContextResponseData> {\n // Core's `ResyncContextApiResponse` is a flat payload (no inner `data`\n // field), so parse the body directly \u2014 do NOT `unwrap`, or `resyncStarted`\n // reads as undefined and the resync silently appears to never start.\n const r = await this.httpClient.post<ResyncContextResponseData | null>(\n `/admin-api/contexts/${contextId}/resync`,\n request,\n );\n // An empty 2xx body means the resync was accepted; synthesize the result so\n // callers always get a typed value instead of null.\n return r ?? { contextId, resyncStarted: true };\n }\n\n async inviteSpecializedNode(request: InviteSpecializedNodeRequest): Promise<InviteSpecializedNodeResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: InviteSpecializedNodeResponseData }>(\n '/admin-api/contexts/invite-specialized-node',\n request,\n ),\n );\n }\n\n async updateContextApplication(\n contextId: string,\n request: UpdateContextApplicationRequest,\n ): Promise<void> {\n await this.httpClient.post(`/admin-api/contexts/${contextId}/application`, request);\n }\n\n async getContextsWithExecutorsForApplication(applicationId: string): Promise<ContextsWithExecutorsResponseData> {\n // Core returns this flat as { contexts: [...] } (not a bare array under `data`).\n const r = await this.httpClient.get<\n | ContextsWithExecutorsResponseData\n | { contexts: ContextsWithExecutorsResponseData }\n | { data: ContextsWithExecutorsResponseData }\n >(`/admin-api/contexts/with-executors/for-application/${applicationId}`);\n if (Array.isArray(r)) return r;\n return (\n (r as { contexts?: ContextsWithExecutorsResponseData } | null)?.contexts ??\n (r as { data?: ContextsWithExecutorsResponseData } | null)?.data ??\n []\n );\n }\n\n // ---- Blob Management ----\n\n async uploadBlob(request: UploadBlobRequest): Promise<UploadBlobResponseData> {\n // Core streams the raw request body into blob storage (no JSON) and takes\n // its params from the query string (`hash`, `context_id` \u2014 snake_case).\n const params = new URLSearchParams();\n if (request.hash) params.set('hash', request.hash);\n if (request.contextId) params.set('context_id', request.contextId);\n const query = params.toString();\n const path = query ? `/admin-api/blobs?${query}` : '/admin-api/blobs';\n // request.data (Uint8Array view | ArrayBuffer | Blob) is a valid BodyInit and\n // is streamed verbatim \u2014 no JSON, no cast. fetch honors a Uint8Array view's\n // byteOffset/byteLength, so subarrays upload the correct region.\n // Core's BlobInfo is snake_case (`blob_id`); map to camelCase like deleteBlob.\n const res = unwrap(\n await this.httpClient.request<{ data: { blob_id: string; size: number } }>(path, {\n method: 'PUT',\n body: request.data,\n headers: { 'Content-Type': 'application/octet-stream' },\n }),\n );\n return { blobId: res.blob_id, size: res.size };\n }\n\n async deleteBlob(blobId: string): Promise<DeleteBlobResponseData> {\n // Core's `BlobDeleteResponse` is a flat, snake_case payload (`{ blob_id,\n // deleted }`) \u2014 the lone admin DTO without a camelCase rename and without an\n // inner `data` field. Parse directly (no `unwrap`) and map to camelCase.\n const body = await this.httpClient.delete<{ blob_id: string; deleted: boolean }>(\n `/admin-api/blobs/${blobId}`,\n );\n return { blobId: body.blob_id, deleted: body.deleted };\n }\n\n async listBlobs(): Promise<ListBlobsResponseData> {\n // Core's BlobInfo is snake_case (`blob_id`); map to camelCase.\n const res = unwrap(\n await this.httpClient.get<{ data: { blobs: Array<{ blob_id: string; size: number }> } }>(\n '/admin-api/blobs',\n ),\n );\n return { blobs: res.blobs.map((b) => ({ blobId: b.blob_id, size: b.size })) };\n }\n\n /**\n * Download a blob's raw bytes. `GET /admin-api/blobs/:id` streams the blob\n * content (e.g. `application/gzip`), NOT JSON \u2014 so fetch it as an ArrayBuffer.\n * Use {@link listBlobs} for `{ blobId, size }` metadata.\n */\n async getBlob(blobId: string): Promise<ArrayBuffer> {\n return this.httpClient.get<ArrayBuffer>(`/admin-api/blobs/${blobId}`, {\n parse: 'arrayBuffer',\n });\n }\n\n /**\n * Fetch a blob's metadata without downloading it. `HEAD /admin-api/blobs/:id`\n * returns the info in response headers (size via `content-length`, plus\n * `x-blob-id`/`x-blob-hash`/`x-blob-mime-type`).\n */\n async getBlobInfo(blobId: string): Promise<GetBlobInfoResponseData> {\n // HEAD throws (HttpError) on a non-2xx status, so we only reach here on success\n // \u2014 the x-blob-* headers are present. Guard size against a missing/non-numeric\n // content-length anyway (defaults to 0 rather than NaN).\n const { headers } = await this.httpClient.head(`/admin-api/blobs/${blobId}`);\n const size = Number(headers['content-length']);\n return {\n blobId: headers['x-blob-id'] ?? blobId,\n size: Number.isFinite(size) ? size : 0,\n hash: headers['x-blob-hash'],\n mimeType: headers['x-blob-mime-type'],\n };\n }\n\n // ---- Alias Management ----\n\n async createContextAlias(\n request: CreateContextAliasRequest,\n ): Promise<CreateAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateAliasResponseData }>(\n '/admin-api/alias/create/context',\n { alias: request.alias, contextId: request.contextId },\n ),\n );\n }\n\n async createApplicationAlias(\n request: CreateApplicationAliasRequest,\n ): Promise<CreateAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateAliasResponseData }>(\n '/admin-api/alias/create/application',\n { alias: request.alias, applicationId: request.applicationId },\n ),\n );\n }\n\n async lookupContextAlias(name: string): Promise<LookupAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: LookupAliasResponseData }>(\n `/admin-api/alias/lookup/context/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async lookupApplicationAlias(name: string): Promise<LookupAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: LookupAliasResponseData }>(\n `/admin-api/alias/lookup/application/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async deleteContextAlias(name: string): Promise<DeleteAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: DeleteAliasResponseData }>(\n `/admin-api/alias/delete/context/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async deleteApplicationAlias(name: string): Promise<DeleteAliasResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: DeleteAliasResponseData }>(\n `/admin-api/alias/delete/application/${encodeURIComponent(name)}`,\n {},\n ),\n );\n }\n\n async listContextAliases(): Promise<ListAliasesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListAliasesResponseData }>('/admin-api/alias/list/context'));\n }\n\n async listApplicationAliases(): Promise<ListAliasesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListAliasesResponseData }>('/admin-api/alias/list/application'));\n }\n\n // ---- Namespace Management ----\n\n async listNamespaces(): Promise<ListNamespacesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListNamespacesResponseData }>('/admin-api/namespaces'));\n }\n\n async getNamespace(namespaceId: string): Promise<Namespace> {\n return unwrap(await this.httpClient.get<{ data: Namespace }>(`/admin-api/namespaces/${namespaceId}`));\n }\n\n /**\n * Who this node is \u2014 the account it writes as, the device it is, the key it\n * signs with, and the account root a second device pairs against.\n *\n * Takes no namespace, and that is the point: one root key is one account\n * everywhere, and a node signs with one key, so none of it varies by\n * namespace.\n */\n async getNodeIdentity(): Promise<NodeIdentity> {\n return unwrap(await this.httpClient.get<{ data: NodeIdentity }>('/admin-api/identity'));\n }\n\n /**\n * @deprecated Use {@link getNodeIdentity} instead. Every field this returns is\n * node-level, so the namespace was only ever decoration \u2014 it now delegates to\n * the node-level route and reshapes the answer.\n *\n * Three consequences of that delegation, all visible to a caller who relied on\n * the old route's behaviour:\n *\n * - **No participation gate.** The namespace route answered 404 when this node\n * had never joined the namespace; this answers whatever the node's identity\n * is, regardless. If you were using it to ask \"am I in this namespace?\", ask\n * {@link listNamespaces} instead \u2014 that is the question you were really\n * asking.\n * - **`namespaceId` is echoed verbatim.** The old route resolved a subgroup id\n * to its root namespace and returned that; passing a subgroup id here gives\n * the subgroup id back.\n * - **404 means something else.** Previously \"not my namespace\", now \"this node\n * holds no account root yet\".\n */\n async getNamespaceIdentity(namespaceId: string): Promise<NamespaceIdentity> {\n const node = await this.getNodeIdentity();\n return { namespaceId, publicKey: node.publicKey, account: node.accountId };\n }\n\n /**\n * Ask this node to run one method on a member's behalf, under a warrant that\n * member signed.\n *\n * The node executes and signs the envelope with its own key; the change is\n * attributed to the **author**. Both halves travel together, so every peer\n * re-checks that the member consented instead of trusting the relay.\n *\n * Three things have to be true first, and none is implied by the others:\n *\n * - the author's **account** is a member of the group owning the context \u2014\n * their device joins nothing and is in no group's binding rows, which is\n * exactly the case a device certificate covers;\n * - this node holds `CAN_AUTHOR_ON_BEHALF` on that group, which is implied by\n * neither membership nor admin;\n * - the warrant has not been spent. It is single-use: presenting a valid one\n * twice is refused, because the signature stays valid forever and replay is\n * not forgery.\n *\n * A refusal comes back as a `403` carrying the reason \u2014 \"an admin must grant\n * CAN_AUTHOR_ON_BEHALF to \u2026\", or that the nonce is already spent \u2014 so a caller\n * can tell which precondition failed rather than only that one did.\n *\n * Mint the warrant with {@link signWarrant}; see\n * {@link PerformIntentRequest.warrant}.\n */\n async performIntent(\n contextId: string,\n request: PerformIntentRequest,\n ): Promise<PerformIntentResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: PerformIntentResponseData }>(\n `/admin-api/contexts/${contextId}/intents`,\n request,\n ),\n );\n }\n\n async listNamespacesForApplication(applicationId: string): Promise<ListNamespacesResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListNamespacesResponseData }>(`/admin-api/namespaces/for-application/${applicationId}`));\n }\n\n async createNamespace(request: CreateNamespaceRequest): Promise<CreateNamespaceResponseData> {\n // `upgradePolicy` is sent even though the request type no longer carries it.\n //\n // The concept was deleted server-side (calimero-network/core#3393), but only\n // on master: every RELEASED node still declares the field required and\n // rejects a body without it \u2014 `missing field 'upgradePolicy'`. A node that\n // has dropped it ignores the extra key, so sending it is the one shape that\n // works against both, and this SDK does not get to choose which node a\n // caller points it at.\n //\n // `LazyOnAccess` because it was the default and is the only behaviour that\n // survives the removal, so an old node given it does what a new one does.\n //\n // Remove once no supported release predates that change.\n return unwrap(\n await this.httpClient.post<{ data: CreateNamespaceResponseData }>('/admin-api/namespaces', {\n upgradePolicy: 'LazyOnAccess',\n ...request,\n }),\n );\n }\n\n async deleteNamespace(\n namespaceId: string,\n request?: DeleteNamespaceRequest,\n ): Promise<DeleteNamespaceResponseData> {\n // Core requires `Content-Type: application/json` on this DELETE even when the\n // body is empty, so always send the header and a (possibly empty) JSON body.\n return unwrap(\n await this.httpClient.request<{ data: DeleteNamespaceResponseData }>(`/admin-api/namespaces/${namespaceId}`, {\n method: 'DELETE',\n body: JSON.stringify(request ?? {}),\n headers: { 'Content-Type': 'application/json' },\n }),\n );\n }\n\n async createNamespaceInvitation(\n namespaceId: string,\n request?: CreateNamespaceInvitationRequest,\n ): Promise<CreateNamespaceInvitationResponseData | CreateRecursiveInvitationResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateNamespaceInvitationResponseData | CreateRecursiveInvitationResponseData }>(\n `/admin-api/namespaces/${namespaceId}/invite`,\n request ?? {},\n ),\n );\n }\n\n /**\n * Present a join this caller signed to a node the inviter named as an\n * admitter.\n *\n * For a member with no node. `joinNamespace` publishes the membership op from\n * the node making the call; this hands an already-signed op to somebody else's\n * node to publish. The distinction matters because a keyholder has nowhere to\n * publish from.\n *\n * The op must be signed by the **device key** in the credential it carries \u2014\n * every peer checks that when applying a join. So the admitter cannot author\n * this, only carry it: a hostile one can refuse, and nothing else. It cannot\n * admit a different account, change the group, or grant a role.\n *\n * @param namespaceId the namespace being joined, 64 hex\n * @param request the invitation and the hex-encoded signed op\n */\n async admitJoin(\n namespaceId: string,\n request: AdmitJoinRequest,\n ): Promise<AdmitJoinResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: AdmitJoinResponseData }>(\n `/admin-api/namespaces/${namespaceId}/admit`,\n request,\n { timeoutMs: 65000 },\n ),\n );\n }\n\n async joinNamespace(\n namespaceId: string,\n request: JoinNamespaceRequest,\n ): Promise<JoinNamespaceResponseData> {\n const data = unwrap(\n await this.httpClient.post<{ data: JoinNamespaceResponseData }>(\n `/admin-api/namespaces/${namespaceId}/join`,\n request,\n { timeoutMs: 65000 },\n ),\n );\n\n // core 0.11.0-rc.25 renamed this response's `groupId` to `namespaceId`\n // (core#3598). Bind whichever spelling the node actually sent rather than\n // picking one: the rename lands as `undefined` on the field the client\n // reads, and nothing errors \u2014 no 4xx, no thrown parse \u2014 so a client that\n // knows only one spelling fails much later and somewhere else. Normalising\n // here means one mero-js works against nodes either side of that release.\n if (data && data.namespaceId === undefined && data.groupId !== undefined) {\n return { ...data, namespaceId: data.groupId };\n }\n return data;\n }\n\n async createGroupInNamespace(\n namespaceId: string,\n request?: CreateGroupInNamespaceRequest,\n ): Promise<CreateGroupInNamespaceResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateGroupInNamespaceResponseData }>(\n `/admin-api/namespaces/${namespaceId}/groups`,\n request ?? {},\n ),\n );\n }\n\n async listNamespaceGroups(namespaceId: string): Promise<SubgroupEntry[]> {\n return unwrap(await this.httpClient.get<{ data: SubgroupEntry[] }>(`/admin-api/namespaces/${namespaceId}/groups`));\n }\n\n // ---- Group Management ----\n\n async getGroupInfo(groupId: string): Promise<GroupInfoResponseData> {\n return unwrap(await this.httpClient.get<{ data: GroupInfoResponseData }>(`/admin-api/groups/${groupId}`));\n }\n\n /** Thin wrapper over {@link getGroupInfo}: returns the group's `defaultCapabilities` bitmask. */\n async getDefaultCapabilities(groupId: string): Promise<number> {\n return (await this.getGroupInfo(groupId)).defaultCapabilities;\n }\n\n /** Thin wrapper over {@link getGroupInfo}: returns the group's `subgroupVisibility`. */\n async getSubgroupVisibility(groupId: string): Promise<string> {\n return (await this.getGroupInfo(groupId)).subgroupVisibility;\n }\n\n async deleteGroup(groupId: string, request?: DeleteGroupRequest): Promise<DeleteGroupResponseData> {\n // Core requires `Content-Type: application/json` on this DELETE even with an\n // empty body, so always send the header and a (possibly empty) JSON body.\n return unwrap(\n await this.httpClient.request<{ data: DeleteGroupResponseData }>(`/admin-api/groups/${groupId}`, {\n method: 'DELETE',\n body: JSON.stringify(request ?? {}),\n headers: { 'Content-Type': 'application/json' },\n }),\n );\n }\n\n async listGroupMembers(groupId: string): Promise<ListGroupMembersResponseData> {\n const response = await this.httpClient.get<ListGroupMembersResponseData>(\n `/admin-api/groups/${groupId}/members`,\n );\n // Validate the field we declare as non-optional in the type so a\n // contract-violating response (proxy error body, future API drift,\n // etc.) surfaces as a clear error rather than silently producing an\n // empty list. Empty groups still satisfy this \u2014 merod returns\n // `members: []`, not an omitted field.\n if (!Array.isArray(response?.members)) {\n // Sanitize before interpolation: groupId reaches us from caller code,\n // not parsed input, but defending the message keeps untrusted bytes\n // out of error logs and downstream UIs.\n const safeId = String(groupId).replace(/[\\r\\n\\t\\s]/g, '').slice(0, 64);\n throw new Error(\n `Invalid listGroupMembers response for group ${safeId}: missing or non-array \\`members\\` field`,\n );\n }\n return response;\n }\n\n async listGroupContexts(groupId: string): Promise<ListGroupContextsResponseData> {\n return unwrap(await this.httpClient.get<{ data: ListGroupContextsResponseData }>(`/admin-api/groups/${groupId}/contexts`));\n }\n\n async addGroupMembers(groupId: string, request: AddGroupMembersRequest): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/members`, request);\n }\n\n async removeGroupMembers(groupId: string, request: RemoveGroupMembersRequest): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/members/remove`, request);\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async updateMemberRole(\n groupId: string,\n identity: string,\n request: UpdateMemberRoleRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/role`, request);\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async getMemberCapabilities(groupId: string, identity: string): Promise<MemberCapabilities> {\n return unwrap(\n await this.httpClient.get<{ data: MemberCapabilities }>(\n `/admin-api/groups/${groupId}/members/${identity}/capabilities`,\n ),\n );\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async setMemberCapabilities(\n groupId: string,\n identity: string,\n request: SetMemberCapabilitiesRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/capabilities`, request);\n }\n\n async setDefaultCapabilities(\n groupId: string,\n request: SetDefaultCapabilitiesRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/settings/default-capabilities`, request);\n }\n\n async setSubgroupVisibility(\n groupId: string,\n request: SetSubgroupVisibilityRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/settings/subgroup-visibility`, request);\n }\n\n async setTeeAdmissionPolicy(\n groupId: string,\n request: SetTeeAdmissionPolicyRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/settings/tee-admission-policy`, request);\n }\n\n async getTeeAdmissionPolicy(groupId: string): Promise<GetTeeAdmissionPolicyResponseData> {\n // Intersection (not union) so the type is unambiguous: `data` is optional, so\n // `?? response` cleanly falls back to a flat (un-enveloped) response.\n const response = await this.httpClient.get<\n GetTeeAdmissionPolicyResponseData & { data?: GetTeeAdmissionPolicyResponseData }\n >(`/admin-api/groups/${groupId}/settings/tee-admission-policy`);\n return response.data ?? response;\n }\n\n // ---- Group / member / context metadata ----\n\n async setGroupMetadata(groupId: string, request: SetGroupMetadataRequest): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/metadata`, request);\n }\n\n async getGroupMetadata(groupId: string): Promise<MetadataRecord | null> {\n // Core single-envelopes the record: `{ data: MetadataRecord | null }`.\n // \"No record yet\" is `{ data: null }` (or a bare null body on older nodes),\n // so optional-chain to a clean null. Returns the full record (name + data +\n // updatedAt/updatedBy), not just the data map.\n const response = await this.httpClient.get<GetMetadataResponseData | null>(\n `/admin-api/groups/${groupId}/metadata`,\n );\n return response?.data ?? null;\n }\n\n async setMemberMetadata(\n groupId: string,\n identity: string,\n request: SetMemberMetadataRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/metadata`, request);\n }\n\n /**\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async getMemberMetadata(groupId: string, identity: string): Promise<MetadataRecord | null> {\n // Single-enveloped record; see getGroupMetadata.\n const response = await this.httpClient.get<GetMetadataResponseData | null>(\n `/admin-api/groups/${groupId}/members/${identity}/metadata`,\n );\n return response?.data ?? null;\n }\n\n async setContextMetadata(\n groupId: string,\n contextId: string,\n request: SetContextMetadataRequest,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/contexts/${contextId}/metadata`, request);\n }\n\n async getContextMetadata(groupId: string, contextId: string): Promise<MetadataRecord | null> {\n // Single-enveloped record; see getGroupMetadata.\n const response = await this.httpClient.get<GetMetadataResponseData | null>(\n `/admin-api/groups/${groupId}/contexts/${contextId}/metadata`,\n );\n return response?.data ?? null;\n }\n\n async syncGroup(groupId: string, request?: SyncGroupRequest): Promise<SyncGroupResponseData> {\n return unwrap(await this.httpClient.post<{ data: SyncGroupResponseData }>(`/admin-api/groups/${groupId}/sync`, request ?? {}));\n }\n\n async upgradeGroup(groupId: string, request: UpgradeGroupRequest): Promise<UpgradeGroupResponseData> {\n return unwrap(await this.httpClient.post<{ data: UpgradeGroupResponseData }>(`/admin-api/groups/${groupId}/upgrade`, request));\n }\n\n async getGroupUpgradeStatus(groupId: string): Promise<GroupUpgradeStatusResponseData> {\n return unwrap(\n await this.httpClient.get<{ data: GroupUpgradeStatusResponseData }>(`/admin-api/groups/${groupId}/upgrade/status`),\n );\n }\n\n /**\n * The operator-facing \"have all peers migrated?\" rollup for a namespace.\n * The handler serializes the payload directly, so there is no `{ data }`\n * envelope to unwrap here (unlike most admin reads).\n */\n async getMigrationStatus(namespaceId: string): Promise<MigrationStatus> {\n const id = encodeURIComponent(namespaceId);\n return this.httpClient.get<MigrationStatus>(`/admin-api/groups/${id}/migration-status`);\n }\n\n /** Per-group cascade-migration snapshots for a namespace. */\n async getCascadeStatus(namespaceId: string): Promise<CascadeStatusEntry[]> {\n const id = encodeURIComponent(namespaceId);\n return unwrap(\n await this.httpClient.get<{ data: CascadeStatusEntry[] }>(`/admin-api/groups/${id}/cascade-status`),\n );\n }\n\n async retryGroupUpgrade(\n groupId: string,\n request?: RetryGroupUpgradeRequest,\n ): Promise<RetryGroupUpgradeResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: RetryGroupUpgradeResponseData }>(\n `/admin-api/groups/${groupId}/upgrade/retry`,\n request ?? {},\n ),\n );\n }\n\n /** Move `childGroupId` under `request.newParentId`. */\n async reparentGroup(\n childGroupId: string,\n request: ReparentGroupRequest,\n ): Promise<ReparentGroupResponseData> {\n // Core returns this flat ({ reparented }); tolerate the { data } envelope too.\n const r = await this.httpClient.post<\n ReparentGroupResponseData & { data?: ReparentGroupResponseData }\n >(`/admin-api/groups/${childGroupId}/reparent`, request);\n return (r?.data ?? r) as ReparentGroupResponseData;\n }\n\n async listSubgroups(groupId: string): Promise<SubgroupEntry[]> {\n const response = await this.httpClient.get<{ subgroups?: SubgroupEntry[]; data?: SubgroupEntry[] }>(\n `/admin-api/groups/${groupId}/subgroups`,\n );\n return response.subgroups ?? response.data ?? [];\n }\n\n async detachContextFromGroup(\n groupId: string,\n contextId: string,\n request?: DetachContextFromGroupRequest,\n ): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/contexts/${contextId}/remove`, request ?? {});\n }\n\n // ---- Group Invitation & Join ----\n\n async createGroupInvitation(\n groupId: string,\n request?: CreateGroupInvitationRequest,\n ): Promise<CreateGroupInvitationResponseData | CreateRecursiveGroupInvitationResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: CreateGroupInvitationResponseData | CreateRecursiveGroupInvitationResponseData }>(\n `/admin-api/groups/${groupId}/invite`,\n request ?? {},\n ),\n );\n }\n\n async joinGroup(request: JoinGroupRequest): Promise<JoinGroupResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: JoinGroupResponseData }>('/admin-api/groups/join', request),\n );\n }\n\n async joinSubgroupInheritance(groupId: string): Promise<JoinSubgroupInheritanceResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: JoinSubgroupInheritanceResponseData }>(\n `/admin-api/groups/${groupId}/join-via-inheritance`,\n {},\n ),\n );\n }\n\n // ---- TEE ----\n\n async getTeeInfo(): Promise<TeeInfoResponseData> {\n return unwrap(await this.httpClient.get<{ data: TeeInfoResponseData }>('/admin-api/tee/info'));\n }\n\n async teeAttest(request: TeeAttestRequest): Promise<TeeAttestResponseData> {\n return unwrap(await this.httpClient.post<{ data: TeeAttestResponseData }>('/admin-api/tee/attest', request));\n }\n\n async teeVerifyQuote(request: TeeVerifyQuoteRequest): Promise<TeeVerifyQuoteResponseData> {\n return unwrap(\n await this.httpClient.post<{ data: TeeVerifyQuoteResponseData }>('/admin-api/tee/verify-quote', request),\n );\n }\n\n // ---- Network ----\n\n async getPeersCount(): Promise<{ count: number }> {\n return this.httpClient.get<{ count: number }>('/admin-api/peers');\n }\n\n /** Node network status (GET /admin-api/network/status). */\n async getNetworkStatus(): Promise<unknown> {\n return this.httpClient.get<unknown>('/admin-api/network/status');\n }\n\n /** Node storage/usage stats (GET /admin-api/usage). */\n async getUsage(): Promise<unknown> {\n return this.httpClient.get<unknown>('/admin-api/usage');\n }\n\n /** Node TLS certificate, PEM text (GET /admin-api/certificate). */\n async getCertificate(): Promise<string> {\n return this.httpClient.get<string>('/admin-api/certificate', { parse: 'text' });\n }\n\n // ---- Group / context / namespace membership ----\n\n /** Create a standalone group (POST /admin-api/groups). */\n async createGroup(request: Record<string, unknown>): Promise<{ groupId: string }> {\n // `upgradePolicy` for the same reason as `createNamespace` above \u2014 these are\n // the only two requests a released node still requires it on, and it ignores\n // the extra key once the concept is gone. Spread after the caller's request\n // so an explicit value wins.\n return unwrap(\n await this.httpClient.post<{ data: { groupId: string } }>('/admin-api/groups', {\n upgradePolicy: 'LazyOnAccess',\n ...request,\n }),\n );\n }\n\n /** Leave a group (POST /admin-api/groups/:group_id/leave). */\n async leaveGroup(groupId: string, request?: Record<string, unknown>): Promise<void> {\n await this.httpClient.post(`/admin-api/groups/${groupId}/leave`, request ?? {});\n }\n\n /** Leave a context (POST /admin-api/contexts/:context_id/leave). */\n async leaveContext(contextId: string, request?: Record<string, unknown>): Promise<void> {\n await this.httpClient.post(`/admin-api/contexts/${contextId}/leave`, request ?? {});\n }\n\n /** Leave a namespace (POST /admin-api/namespaces/:namespace_id/leave). */\n async leaveNamespace(namespaceId: string, request?: Record<string, unknown>): Promise<void> {\n await this.httpClient.post(`/admin-api/namespaces/${namespaceId}/leave`, request ?? {});\n }\n\n /** Issue a group ownership proof (POST /admin-api/groups/:group_id/issue-ownership-proof). */\n async issueOwnershipProof(groupId: string, request?: Record<string, unknown>): Promise<unknown> {\n return this.httpClient.post<unknown>(`/admin-api/groups/${groupId}/issue-ownership-proof`, request ?? {});\n }\n\n /** Issue a namespace ownership proof (POST /admin-api/groups/:group_id/issue-namespace-ownership-proof). */\n async issueNamespaceOwnershipProof(groupId: string, request?: Record<string, unknown>): Promise<unknown> {\n return this.httpClient.post<unknown>(\n `/admin-api/groups/${groupId}/issue-namespace-ownership-proof`,\n request ?? {},\n );\n }\n\n /**\n * Set a member's auto-follow flag (PUT\n * /admin-api/groups/:group_id/members/:identity/auto-follow).\n *\n * `identity` is the member's ACCOUNT (64 hex), as returned by\n * {@link listGroupMembers} \u2014 not the signing key that added them. Both are\n * 64 hex, so nothing but the source tells them apart.\n */\n async setMemberAutoFollow(\n groupId: string,\n identity: string,\n request: Record<string, unknown>,\n ): Promise<void> {\n await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/auto-follow`, request);\n }\n\n /** Abort a namespace migration (POST /admin-api/groups/:namespace_id/migration/abort). */\n async abortMigration(namespaceId: string, request?: Record<string, unknown>): Promise<unknown> {\n return this.httpClient.post<unknown>(\n `/admin-api/groups/${namespaceId}/migration/abort`,\n request ?? {},\n );\n }\n}\n", "import { AdminApiClient } from './admin-client.js';\nimport { AdminApiClientConfig } from './admin-types.js';\nimport {\n HttpClient,\n createBrowserHttpClient,\n createNodeHttpClient,\n createUniversalHttpClient,\n} from '../http-client/index.js';\n\n// Factory functions for creating Admin API clients\n\n/** Admin client over a browser HTTP transport (global `fetch`). */\nexport function createBrowserAdminApiClient(\n config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(createBrowserHttpClient(config));\n}\n\n/** Admin client over a Node HTTP transport (Node 18+ `fetch`). */\nexport function createNodeAdminApiClient(\n config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(createNodeHttpClient(config));\n}\n\n/** Admin client over whichever transport suits the current runtime. */\nexport function createAdminApiClient(\n config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(createUniversalHttpClient(config));\n}\n\n/**\n * Admin client over a caller-supplied HTTP client \u2014 use this to share one\n * transport (and its token handling) with the other API clients.\n */\nexport function createAdminApiClientFromHttpClient(\n httpClient: HttpClient,\n _config: AdminApiClientConfig,\n): AdminApiClient {\n return new AdminApiClient(httpClient);\n}\n", "export interface AuthCallbackResult {\n accessToken: string;\n refreshToken: string;\n applicationId: string;\n contextId: string;\n contextIdentity: string;\n nodeUrl: string;\n}\n\nexport interface AuthLoginOptions {\n callbackUrl: string;\n packageName?: string;\n mode: string;\n permissions?: string[];\n registryUrl?: string;\n packageVersion?: string;\n}\n\n/**\n * Parse an auth callback URL hash fragment.\n * Returns null if access_token is missing.\n */\nexport function parseAuthCallback(url: string): AuthCallbackResult | null {\n try {\n const hashIndex = url.indexOf('#');\n if (hashIndex === -1) return null;\n\n const hash = url.substring(hashIndex + 1);\n const params = new URLSearchParams(hash);\n\n const accessToken = params.get('access_token');\n if (!accessToken) return null;\n\n return {\n accessToken,\n refreshToken: params.get('refresh_token') ?? '',\n applicationId: params.get('application_id') ?? '',\n contextId: params.get('context_id') ?? '',\n contextIdentity: params.get('context_identity') ?? '',\n nodeUrl: params.get('node_url') ?? '',\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Build the auth login URL for redirecting users to the node's auth page.\n */\nexport function buildAuthLoginUrl(nodeUrl: string, opts: AuthLoginOptions): string {\n const params = new URLSearchParams();\n params.set('callback-url', opts.callbackUrl);\n\n if (opts.permissions && opts.permissions.length > 0) {\n params.set('permissions', opts.permissions.join(','));\n }\n\n params.set('mode', opts.mode);\n\n if (opts.packageName) {\n params.set('package-name', opts.packageName);\n if (opts.packageVersion) {\n params.set('package-version', opts.packageVersion);\n }\n if (opts.registryUrl) {\n params.set('registry-url', opts.registryUrl);\n }\n }\n\n // Trim trailing slash from nodeUrl\n const base = nodeUrl.replace(/\\/+$/, '');\n return `${base}/auth/login?${params.toString()}`;\n}\n", "import type { HttpClient } from '../http-client/index.js';\n\n/** Result of the owner-driven `migrate_my_entries` convert (counts are u32). */\nexport interface MigrateMyEntriesSummary {\n converted: number;\n remaining: number;\n}\n\nexport interface ExecuteParams {\n contextId: string;\n method: string;\n argsJson?: Record<string, unknown>;\n /** @deprecated No longer used by the server. Ignored if provided. */\n executorPublicKey?: string;\n}\n\nexport class RpcError extends Error {\n code: number;\n type?: string;\n data?: unknown;\n\n constructor(code: number, message: string, data?: unknown, type?: string) {\n super(message);\n this.name = 'RpcError';\n this.code = code;\n this.data = data;\n this.type = type;\n }\n}\n\ninterface JsonRpcResponse {\n jsonrpc: string;\n id: number;\n result?: {\n output?: unknown;\n [key: string]: unknown;\n };\n error?: {\n // Standard JSON-RPC fields\n code?: number;\n message?: string;\n // Server-specific fields\n type?: string;\n data?: unknown;\n };\n}\n\n/**\n * POST a JSON-RPC call and unwrap `result`, converting an `error` payload into\n * an `RpcError`. The node returns `{ type, data }` (not always `{ code,\n * message }`), so this is the one place that normalization lives \u2014 every\n * JSON-RPC caller in this SDK shares it rather than re-deriving a bare\n * `Error(message)` and dropping the typed detail.\n */\nexport async function jsonRpcCall<T>(\n httpClient: HttpClient,\n method: string,\n params: unknown,\n): Promise<T> {\n const response = await httpClient.post<JsonRpcResponse>('/jsonrpc', {\n jsonrpc: '2.0',\n id: 1,\n method,\n params,\n });\n\n if (response.error) {\n const err = response.error;\n throw new RpcError(err.code ?? -1, err.message ?? err.type ?? 'RPC error', err.data, err.type);\n }\n\n return response.result as T;\n}\n\nexport class RpcClient {\n private httpClient: HttpClient;\n\n constructor(opts: { httpClient: HttpClient }) {\n this.httpClient = opts.httpClient;\n }\n\n async execute<T = unknown>(params: ExecuteParams): Promise<T> {\n const result = await jsonRpcCall<JsonRpcResponse['result']>(this.httpClient, 'execute', {\n contextId: params.contextId,\n method: params.method,\n argsJson: params.argsJson ?? {},\n });\n\n if (result && 'output' in result) {\n return result.output as T;\n }\n\n return result as T;\n }\n\n /**\n * One-tap owner-driven convert: re-signs the caller's identity-gated entries\n * to the current schema. The export converts all of the caller's\n * below-target entries in a single sweep, so this issues one call and returns\n * the resulting summary \u2014 it does not loop.\n */\n async migrateMyEntries(contextId: string): Promise<MigrateMyEntriesSummary> {\n return this.execute<MigrateMyEntriesSummary>({ contextId, method: 'migrate_my_entries' });\n }\n\n /** Read-only count of the caller's entries still below the target schema. */\n async countMyPending(contextId: string): Promise<number> {\n return this.execute<number>({ contextId, method: 'count_my_pending' });\n }\n}\n", "/** Parsed group-membership event (core's untagged `NodeEvent` group variant). */\nexport interface GroupMembershipEventData {\n groupId: string;\n type: 'MemberJoined' | 'MemberAdded' | 'MemberRemoved';\n data: {\n /** The member's ACCOUNT, hex-encoded 32 bytes (64 chars) - the principal the\n * governance rows name. Not a signing key: the field this replaced\n * carried one, and both are strings, so the rename is what makes a stale\n * consumer fail loudly instead of comparing accounts against keys forever. */\n memberAccount: string;\n /** Absent on `MemberRemoved`, and on a `MemberJoined` inherited from an Open\n * subgroup. Core's set is closed. */\n role?: 'Admin' | 'Member' | 'ReadOnly' | 'ReadOnlyTee';\n };\n}\n\n/**\n * A migration was accepted and its target ABI state version resolved.\n * `toStateVersion` is the `#[app::state(version = N)]` number, not the bundle\n * semver (`toVersion`).\n */\nexport interface MigrationStartedData {\n fromVersion: string;\n toVersion: string;\n toStateVersion: number;\n /** Contexts the EMITTING NODE enumerated for the migration. Node-local, never\n * the fleet cohort size that `MigrationProgressData.total` carries. */\n localContextsTotal: number;\n}\n\n/**\n * Fleet rollup counters, recomputed as peers' heartbeat facts change. Counters\n * only: the per-member detail behind them stays in the admin-gated\n * `getMigrationStatus` read.\n */\nexport interface MigrationProgressData {\n migrated: number;\n inProgress: number;\n unknown: number;\n failed: number;\n /** The pinned FLEET COHORT size, never a node-local context count like\n * `MigrationStartedData.localContextsTotal`. */\n total: number;\n}\n\n/**\n * One subgroup's local context swaps advanced on the emitting node.\n *\n * Admin-only: it names a descendant subgroup, which a plain namespace member\n * may not enumerate, so core withholds it from non-admin subscribers. A\n * non-admin never receiving this variant is correct behaviour, not a gap.\n */\nexport interface CascadeProgressData {\n /** Hex-encoded descendant subgroup id, never the namespace root the event is\n * keyed on. */\n subgroupId: string;\n localContextsSwapped: number;\n /** Contexts the emitting node holds for THIS SUBGROUP. Node-local and\n * per-subgroup; unrelated to both sibling totals. */\n localContextsTotal: number;\n}\n\n/** Every pinned-cohort member reported the target version. */\nexport interface MigrationCompletedData {\n toVersion: string;\n /** FLEET convergence, in seconds since the epoch: the same stamp\n * `MigrationStatus.fleetCompletedAt` returns. Not `GroupUpgradeStatus.completedAt`,\n * which is this node's own local swap completion. */\n completedAt: number;\n}\n\n/**\n * Parsed group-migration event (core's `GroupMigration` `NodeEvent` variant),\n * keyed on the namespace root a client subscribes with.\n *\n * `MigrationStarted`, `MigrationProgress` and `MigrationCompleted` reach every\n * subscribed member; `CascadeProgress` reaches namespace admins only.\n */\nexport type GroupMigrationEventData =\n | { groupId: string; type: 'MigrationStarted'; data: MigrationStartedData }\n | { groupId: string; type: 'MigrationProgress'; data: MigrationProgressData }\n | { groupId: string; type: 'CascadeProgress'; data: CascadeProgressData }\n | { groupId: string; type: 'MigrationCompleted'; data: MigrationCompletedData };\n\nconst MIGRATION_EVENT_TYPES: ReadonlySet<string> = new Set([\n 'MigrationStarted',\n 'MigrationProgress',\n 'CascadeProgress',\n 'MigrationCompleted',\n]);\n\n/** Narrows a raw `'event'` payload to the group-migration family by its tag. */\nexport function isGroupMigrationEvent(\n event: { type?: string },\n): event is GroupMigrationEventData {\n return event.type !== undefined && MIGRATION_EVENT_TYPES.has(event.type);\n}\n", "import type { GroupMembershipEventData, GroupMigrationEventData } from './group.js';\nimport { isGroupMigrationEvent } from './group.js';\nimport { AuthRevokedError, HTTPError } from '../http-client/index.js';\n\n/**\n * `x-auth-error` reasons that mean the whole token family is gone, mirroring\n * the request path in `web-client.ts`. Anything else \u2014 `token_expired` above\n * all \u2014 is recoverable by refreshing and reconnecting.\n */\nconst TERMINAL_AUTH_ERRORS = new Set(['token_reuse', 'token_revoked']);\n\nexport type { GroupMembershipEventData, GroupMigrationEventData };\n\nexport interface SseEventData {\n contextId: string;\n /** The context-event discriminator (core serializes it as a sibling of\n * `data`, e.g. `\"AppVersionChanged\"`). Undefined for events without a tag. */\n type?: string;\n data: unknown;\n}\n\n/** Parsed `AppVersionChanged` context event (bundle-version flip; skew #2). */\nexport interface AppVersionChangedEvent {\n contextId: string;\n fromVersion?: string;\n toVersion?: string;\n}\n\n/** Anything the `'event'` stream can deliver: context events plus the\n * group-keyed membership and migration families. */\ntype SseEvent = SseEventData | GroupMembershipEventData | GroupMigrationEventData;\ntype SseEventHandler = (event: SseEvent) => void;\ntype SseConnectHandler = (sessionId: string) => void;\ntype SseErrorHandler = (error: Error) => void;\n\ninterface SseListeners {\n connect: SseConnectHandler[];\n event: SseEventHandler[];\n error: SseErrorHandler[];\n}\n\nexport class SseClient {\n private baseUrl: string;\n private getAuthToken: () => Promise<string>;\n private reconnectDelayMs: number;\n private sessionId: string | null = null;\n private abortController: AbortController | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private subscribedContextIds: Set<string> = new Set();\n private subscribedGroupIds: Set<string> = new Set();\n private closed = false;\n private listeners: SseListeners = { connect: [], event: [], error: [] };\n\n constructor(opts: {\n baseUrl: string;\n getAuthToken: () => Promise<string>;\n reconnectDelayMs?: number;\n }) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, '');\n this.getAuthToken = opts.getAuthToken;\n this.reconnectDelayMs = opts.reconnectDelayMs ?? 3000;\n }\n\n on(event: 'connect', handler: SseConnectHandler): void;\n on(event: 'event', handler: SseEventHandler): void;\n on(event: 'error', handler: SseErrorHandler): void;\n on(event: string, handler: SseConnectHandler | SseEventHandler | SseErrorHandler): void {\n const key = event as keyof SseListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n if (!arr.includes(handler)) arr.push(handler);\n }\n }\n\n off(event: 'connect', handler: SseConnectHandler): void;\n off(event: 'event', handler: SseEventHandler): void;\n off(event: 'error', handler: SseErrorHandler): void;\n off(event: string, handler: SseConnectHandler | SseEventHandler | SseErrorHandler): void {\n const key = event as keyof SseListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n const idx = arr.indexOf(handler);\n if (idx !== -1) arr.splice(idx, 1);\n }\n }\n\n /**\n * Typed convenience over the generic `'event'` stream: invokes `handler` only\n * for `AppVersionChanged` context events, with the payload already parsed.\n * Returns an unsubscribe closure (so callers need not retain the listener).\n */\n onAppVersionChanged(handler: (e: AppVersionChangedEvent) => void): () => void {\n const listener: SseEventHandler = (ev) => {\n // Core flattens the tagged payload: the event carries `type` as a sibling\n // of `data`, and `data` is the `{ fromVersion?, toVersion? }` payload.\n if (ev.type !== 'AppVersionChanged') return;\n const d = ev.data as { fromVersion?: string; toVersion?: string } | undefined;\n handler({ contextId: ev.contextId, fromVersion: d?.fromVersion, toVersion: d?.toVersion });\n };\n this.on('event', listener);\n return () => this.off('event', listener);\n }\n\n /**\n * Typed convenience over the generic `'event'` stream: invokes `handler` only\n * for group-migration events, narrowed on `type` so `data` is the matching\n * payload. Returns an unsubscribe closure.\n *\n * A non-admin subscriber sees `MigrationStarted`, `MigrationProgress` and\n * `MigrationCompleted` but never `CascadeProgress`, which core delivers to\n * namespace admins only.\n */\n onMigrationEvent(handler: (e: GroupMigrationEventData) => void): () => void {\n const listener: SseEventHandler = (ev) => {\n if (isGroupMigrationEvent(ev)) handler(ev);\n };\n this.on('event', listener);\n return () => this.off('event', listener);\n }\n\n private emit(event: 'connect', sessionId: string): void;\n private emit(event: 'event', data: SseEvent): void;\n private emit(event: 'error', error: Error): void;\n private emit(event: string, arg?: string | SseEvent | Error): void {\n const key = event as keyof SseListeners;\n if (key in this.listeners) {\n for (const handler of this.listeners[key]) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (handler as any)(arg);\n } catch {\n // Swallow handler errors\n }\n }\n }\n }\n\n async connect(): Promise<void> {\n // Already connected \u2014 don't reconnect\n if (this.abortController && !this.closed) {\n return;\n }\n this.closed = false;\n this.abortController = new AbortController();\n\n try {\n const token = await this.getAuthToken();\n const url = `${this.baseUrl}/sse`;\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Accept': 'text/event-stream',\n },\n signal: this.abortController.signal,\n });\n\n if (!response.ok) {\n // Throw the same typed errors the request path throws. A bare\n // `Error(\"SSE connection failed: 401\")` forced callers to string-match\n // the status and guess what it meant, and the honest guess \u2014 treat any\n // 401 as fatal \u2014 logs the user out on a routine reconnect after the\n // access token ages out, discarding a refresh token that was still\n // good. The distinction is in the header; surface it.\n const authError = response.headers.get('x-auth-error');\n const bodyText = await response.text().catch(() => undefined);\n\n if (\n response.status === 401 &&\n authError &&\n TERMINAL_AUTH_ERRORS.has(authError)\n ) {\n throw new AuthRevokedError(\n authError,\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n }\n\n throw new HTTPError(\n response.status,\n response.statusText,\n url,\n response.headers,\n bodyText,\n );\n }\n\n if (!response.body) {\n throw new Error('SSE response has no body');\n }\n\n this.readStream(response.body).catch((err) => {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n this.scheduleReconnect();\n });\n } catch (err) {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n this.scheduleReconnect();\n }\n }\n\n private async readStream(body: ReadableStream<Uint8Array>): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split('\\n');\n // Keep the last partial line in the buffer\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data:')) {\n const jsonStr = line.slice(5).trim();\n if (jsonStr) {\n this.handleMessage(jsonStr);\n }\n }\n }\n }\n // Flush remaining bytes from the decoder\n buffer += decoder.decode();\n if (buffer.startsWith('data:')) {\n const jsonStr = buffer.slice(5).trim();\n if (jsonStr) {\n this.handleMessage(jsonStr);\n }\n }\n } catch (err) {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n }\n\n // Stream ended, reconnect\n if (!this.closed) {\n this.scheduleReconnect();\n }\n }\n\n private handleMessage(jsonStr: string): void {\n try {\n const msg = JSON.parse(jsonStr);\n\n // Connection message\n if (msg.type === 'connect' && msg.session_id) {\n this.sessionId = msg.session_id;\n this.emit('connect', msg.session_id);\n // Re-subscribe after reconnect\n if (this.subscribedContextIds.size > 0 || this.subscribedGroupIds.size > 0) {\n this.sendSubscription('subscribe', {\n contextIds: [...this.subscribedContextIds],\n groupIds: [...this.subscribedGroupIds],\n });\n }\n return;\n }\n\n if (!msg.result) return;\n\n let eventData = msg.result.data;\n // Decode byte-array data if needed\n if (Array.isArray(eventData)) {\n try {\n const bytes = new Uint8Array(eventData);\n const text = new TextDecoder().decode(bytes);\n eventData = JSON.parse(text);\n } catch {\n // Keep raw data\n }\n }\n\n // Context event message\n if (msg.result.contextId) {\n this.emit('event', {\n contextId: msg.result.contextId,\n // Forward the event tag (sibling of `data` in core's flattened\n // payload) so typed helpers like `onAppVersionChanged` can discriminate.\n type: msg.result.type,\n data: eventData,\n });\n return;\n }\n\n // Group-keyed event message (untagged NodeEvent's membership and\n // migration variants; the `type` tag tells them apart).\n if (msg.result.groupId) {\n this.emit('event', {\n groupId: msg.result.groupId,\n type: msg.result.type,\n data: eventData,\n });\n }\n } catch {\n // Invalid JSON, ignore\n }\n }\n\n async subscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): Promise<void> {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n const newContextIds = (opts.contextIds ?? []).filter(id => !this.subscribedContextIds.has(id));\n const newGroupIds = (opts.groupIds ?? []).filter(id => !this.subscribedGroupIds.has(id));\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.add(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.add(id);\n }\n if ((newContextIds.length > 0 || newGroupIds.length > 0) && this.sessionId) {\n await this.sendSubscription('subscribe', { contextIds: newContextIds, groupIds: newGroupIds });\n }\n }\n\n async unsubscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): Promise<void> {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n const hadContextIds = (opts.contextIds ?? []).filter(id => this.subscribedContextIds.has(id));\n const hadGroupIds = (opts.groupIds ?? []).filter(id => this.subscribedGroupIds.has(id));\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.delete(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.delete(id);\n }\n if ((hadContextIds.length > 0 || hadGroupIds.length > 0) && this.sessionId) {\n await this.sendSubscription('unsubscribe', { contextIds: hadContextIds, groupIds: hadGroupIds });\n }\n }\n\n private async sendSubscription(\n method: 'subscribe' | 'unsubscribe',\n ids: { contextIds?: string[]; groupIds?: string[] },\n ): Promise<void> {\n try {\n const token = await this.getAuthToken();\n const params: { contextIds?: string[]; groupIds?: string[] } = {};\n if (ids.contextIds && ids.contextIds.length > 0) params.contextIds = ids.contextIds;\n if (ids.groupIds && ids.groupIds.length > 0) params.groupIds = ids.groupIds;\n const response = await fetch(`${this.baseUrl}/sse/subscription`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n id: this.sessionId,\n method,\n params,\n }),\n });\n if (!response.ok) {\n this.emit('error', new Error(`SSE ${method} failed: ${response.status}`));\n }\n } catch (err) {\n this.emit('error', err instanceof Error ? err : new Error(`SSE ${method} failed`));\n }\n }\n\n private forceReconnect(): void {\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n this.sessionId = null;\n this.connect();\n }\n\n private scheduleReconnect(): void {\n if (this.closed) return;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.forceReconnect();\n }, this.reconnectDelayMs);\n }\n\n close(): void {\n this.closed = true;\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.sessionId = null;\n this.subscribedContextIds.clear();\n this.subscribedGroupIds.clear();\n }\n}\n", "import type { GroupMembershipEventData, GroupMigrationEventData } from './group.js';\n\nexport type { GroupMembershipEventData, GroupMigrationEventData };\n\nexport interface WsEventData {\n contextId: string;\n /** The context-event discriminator (core serializes it as a sibling of\n * `data`, e.g. `\"AppVersionChanged\"`). Undefined for events without a tag. */\n type?: string;\n data: unknown;\n}\n\n/** Anything the `'event'` stream can deliver: context events plus the\n * group-keyed membership and migration families. */\ntype WsEvent = WsEventData | GroupMembershipEventData | GroupMigrationEventData;\ntype WsEventHandler = (event: WsEvent) => void;\ntype WsConnectHandler = () => void;\ntype WsErrorHandler = (error: Error) => void;\n\ninterface WsListeners {\n connect: WsConnectHandler[];\n event: WsEventHandler[];\n error: WsErrorHandler[];\n}\n\n/**\n * @experimental WebSocket event client. The SSE client (`SseClient`) is the\n * recommended transport for production \u2014 use `MeroJs.events` instead of `MeroJs.ws`.\n */\nexport class WsClient {\n private baseUrl: string;\n private getAuthToken: () => Promise<string>;\n private ws: WebSocket | null = null;\n private closed = false;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private subscribedContextIds: Set<string> = new Set();\n private subscribedGroupIds: Set<string> = new Set();\n private listeners: WsListeners = { connect: [], event: [], error: [] };\n\n private static readonly MAX_BACKOFF_MS = 30000;\n\n constructor(opts: {\n baseUrl: string;\n getAuthToken: () => Promise<string>;\n }) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, '');\n this.getAuthToken = opts.getAuthToken;\n }\n\n on(event: 'connect', handler: WsConnectHandler): void;\n on(event: 'event', handler: WsEventHandler): void;\n on(event: 'error', handler: WsErrorHandler): void;\n on(event: string, handler: WsConnectHandler | WsEventHandler | WsErrorHandler): void {\n const key = event as keyof WsListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n if (!arr.includes(handler)) arr.push(handler);\n }\n }\n\n off(event: 'connect', handler: WsConnectHandler): void;\n off(event: 'event', handler: WsEventHandler): void;\n off(event: 'error', handler: WsErrorHandler): void;\n off(event: string, handler: WsConnectHandler | WsEventHandler | WsErrorHandler): void {\n const key = event as keyof WsListeners;\n if (key in this.listeners) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = this.listeners[key] as any[];\n const idx = arr.indexOf(handler);\n if (idx !== -1) arr.splice(idx, 1);\n }\n }\n\n private emit(event: 'connect'): void;\n private emit(event: 'event', data: WsEvent): void;\n private emit(event: 'error', error: Error): void;\n private emit(event: string, arg?: WsEvent | Error): void {\n const key = event as keyof WsListeners;\n if (key in this.listeners) {\n for (const handler of this.listeners[key]) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (handler as any)(arg);\n } catch {\n // Swallow handler errors\n }\n }\n }\n }\n\n async connect(): Promise<void> {\n if (this.ws && (this.ws.readyState === 0 /* CONNECTING */ || this.ws.readyState === 1 /* OPEN */)) {\n return;\n }\n this.closed = false;\n\n try {\n const token = await this.getAuthToken();\n if (!token) {\n throw new Error('No authentication token available for WebSocket connection');\n }\n // Browser WebSocket API can't set headers, use query param\n const wsUrl = this.baseUrl.replace(/^http/, 'ws');\n this.ws = new WebSocket(`${wsUrl}/ws?token=${encodeURIComponent(token)}`);\n\n this.ws.onopen = () => {\n this.reconnectAttempt = 0;\n this.emit('connect');\n this.resubscribeAfterReconnect();\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onerror = () => {\n this.emit('error', new Error('WebSocket error'));\n };\n\n this.ws.onclose = () => {\n if (!this.closed) {\n this.scheduleReconnect();\n }\n };\n } catch (err) {\n if (this.closed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit('error', error);\n this.scheduleReconnect();\n }\n }\n\n private handleMessage(raw: string | ArrayBuffer | Blob): void {\n if (typeof raw !== 'string') return;\n\n try {\n const msg = JSON.parse(raw);\n\n if (!msg.result) return;\n\n let eventData = msg.result.data;\n if (Array.isArray(eventData)) {\n try {\n const bytes = new Uint8Array(eventData);\n const text = new TextDecoder().decode(bytes);\n eventData = JSON.parse(text);\n } catch {\n // Keep raw data\n }\n }\n\n if (msg.result.contextId) {\n this.emit('event', {\n contextId: msg.result.contextId,\n // Forward the event tag (sibling of `data` in core's flattened\n // payload) so consumers can discriminate, matching `SseClient`.\n type: msg.result.type,\n data: eventData,\n });\n return;\n }\n\n // Group-keyed event message (untagged NodeEvent's membership and\n // migration variants; the `type` tag tells them apart).\n if (msg.result.groupId) {\n this.emit('event', {\n groupId: msg.result.groupId,\n type: msg.result.type,\n data: eventData,\n });\n }\n } catch {\n // Invalid JSON, ignore\n }\n }\n\n subscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): void {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.add(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.add(id);\n }\n\n if (this.ws && this.ws.readyState === 1 /* OPEN */) {\n this.sendMessage({\n id: null,\n method: 'subscribe',\n params: this.buildSubscriptionParams(opts.contextIds ?? [], opts.groupIds ?? []),\n });\n }\n }\n\n unsubscribe(idsOrOpts: string[] | { contextIds?: string[]; groupIds?: string[] }): void {\n const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;\n for (const id of opts.contextIds ?? []) {\n this.subscribedContextIds.delete(id);\n }\n for (const id of opts.groupIds ?? []) {\n this.subscribedGroupIds.delete(id);\n }\n\n if (this.ws && this.ws.readyState === 1 /* OPEN */) {\n this.sendMessage({\n id: null,\n method: 'unsubscribe',\n params: this.buildSubscriptionParams(opts.contextIds ?? [], opts.groupIds ?? []),\n });\n }\n }\n\n private resubscribeAfterReconnect(): void {\n if (this.subscribedContextIds.size === 0 && this.subscribedGroupIds.size === 0) return;\n this.sendMessage({\n id: null,\n method: 'subscribe',\n params: this.buildSubscriptionParams([...this.subscribedContextIds], [...this.subscribedGroupIds]),\n });\n }\n\n private buildSubscriptionParams(\n contextIds: string[],\n groupIds: string[],\n ): { contextIds?: string[]; groupIds?: string[] } {\n const params: { contextIds?: string[]; groupIds?: string[] } = {};\n if (contextIds.length > 0) params.contextIds = contextIds;\n if (groupIds.length > 0) params.groupIds = groupIds;\n return params;\n }\n\n private sendMessage(msg: unknown): void {\n if (this.ws && this.ws.readyState === 1 /* OPEN */) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private scheduleReconnect(): void {\n if (this.closed) return;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n const delay = Math.min(\n 1000 * Math.pow(2, this.reconnectAttempt),\n WsClient.MAX_BACKOFF_MS,\n );\n this.reconnectAttempt++;\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n\n close(): void {\n this.closed = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.ws) {\n this.ws.onclose = null;\n this.ws.close();\n this.ws = null;\n }\n this.subscribedContextIds.clear();\n this.subscribedGroupIds.clear();\n }\n}\n", "import type { Codec } from './types.js';\n\n/** Default codec: JSON text as a byte array. The wire carries `state` as\n * `number[]`, not a string, so this encodes to bytes rather than to text. */\nexport function jsonCodec<T>(): Codec<T> {\n return {\n encode(value: T): number[] {\n return Array.from(new TextEncoder().encode(JSON.stringify(value)));\n },\n decode(bytes: number[]): T {\n return JSON.parse(new TextDecoder().decode(new Uint8Array(bytes))) as T;\n },\n };\n}\n", "import type { HttpClient } from '../http-client/index.js';\nimport type { SseClient } from '../events/index.js';\nimport { jsonRpcCall } from '../rpc/index.js';\nimport { jsonCodec } from './codec.js';\nimport type { Codec, EphemeralEntry } from './types.js';\n\nexport { jsonCodec };\nexport type { Codec, EphemeralEntry };\n\n/**\n * Ephemeral presence: transient, encrypted, never-persisted state (cursors,\n * typing, presence) that gossips between nodes without a WASM run or DAG\n * growth.\n *\n * The write/read asymmetry is the model, not an oversight. `set` takes no\n * author: you can only ever write your OWN slot, and the node resolves the\n * author server-side from its owned context identity \u2014 which is also why a\n * client cannot publish as somebody else. `subscribe` returns everyone's\n * slots, so each carries its `author`. The store is N independent\n * single-writer registers keyed by author; there is no merge across authors.\n *\n * There is a single read path: `subscribe`. On subscribing to a context, the\n * node replays that context's current presence to this connection as\n * ordinary `Ephemeral` events (carrying `ageMs`), before any live deltas\n * (which carry no `ageMs`). There is no separate snapshot RPC.\n */\nexport class EphemeralClient {\n private httpClient: HttpClient;\n private sse: SseClient;\n\n constructor(opts: { httpClient: HttpClient; sse: SseClient }) {\n this.httpClient = opts.httpClient;\n this.sse = opts.sse;\n }\n\n /**\n * Publish your own presence slice, replacing it wholesale.\n *\n * Rejects with an `RpcError` (not a bare `Error`), so a typed failure such as\n * an oversized slice keeps its `type` and `data` \u2014 e.g. `SliceTooLarge` with\n * the offending size \u2014 and is `instanceof RpcError` like every other RPC in\n * this SDK.\n */\n async set<T>(contextId: string, state: T, codec: Codec<T> = jsonCodec<T>()): Promise<void> {\n await jsonRpcCall<Record<string, never>>(this.httpClient, 'set_ephemeral', {\n contextId,\n state: codec.encode(state),\n });\n }\n\n /**\n * Observe presence changes for a context.\n *\n * This adds NO transport \u2014 it is a typed filter over the existing SSE event\n * stream, which already carries `{ contextId, type, data }`. On subscribing,\n * the node replays that context's current presence to this connection as\n * ordinary `Ephemeral` events before any live deltas; a replayed entry\n * carries `ageMs`, a live delta does not (never synthesized as `0` \u2014 absent\n * and zero mean different things). Returns an unsubscribe function.\n */\n subscribe<T>(\n contextId: string,\n handler: (entry: EphemeralEntry<T>) => void,\n codec: Codec<T> = jsonCodec<T>(),\n ): () => void {\n const listener = (event: unknown): void => {\n const e = event as { contextId?: string; type?: string; data?: unknown };\n if (e.type !== 'Ephemeral' || e.contextId !== contextId) return;\n\n const data = e.data as\n | { author?: string; state?: number[]; removed?: boolean; ageMs?: number }\n | undefined;\n if (!data?.author) return;\n\n // `removed` is omitted on an upsert, so normalize to a boolean here and\n // spare every caller the truthiness rule.\n const removed = Boolean(data.removed);\n const entry: EphemeralEntry<T> = {\n author: data.author,\n state: removed || data.state === undefined ? undefined : codec.decode(data.state),\n removed,\n };\n // `ageMs` is present only on a replayed seed entry; pass it through as-is\n // rather than defaulting a live delta to 0.\n if (data.ageMs !== undefined) entry.ageMs = data.ageMs;\n handler(entry);\n };\n\n this.sse.on('event', listener);\n // Errors surface via the SSE client's own 'error' event; nothing more to\n // do with them here.\n void this.sse.connect().catch(() => undefined);\n void this.sse.subscribe([contextId]).catch(() => undefined);\n\n return () => {\n this.sse.off('event', listener);\n };\n }\n}\n", "import { createBrowserHttpClient } from './http-client/index.js';\nimport { createAuthApiClientFromHttpClient } from './auth-api/index.js';\nimport { createAdminApiClientFromHttpClient } from './admin-api/index.js';\nimport type { AuthApiClient } from './auth-api/index.js';\nimport type { AdminApiClient } from './admin-api/index.js';\nimport type { HttpClient } from './http-client/index.js';\nimport type { TokenStore } from './token-store/index.js';\nimport { parseAuthCallback, buildAuthLoginUrl } from './auth/index.js';\nimport type { AuthCallbackResult, AuthLoginOptions } from './auth/index.js';\nimport { RpcClient } from './rpc/index.js';\nimport { SseClient } from './events/sse.js';\nimport { WsClient } from './events/ws.js';\nimport { EphemeralClient } from './ephemeral/index.js';\n\nexport interface MeroJsConfig {\n /** Base URL for the Calimero node */\n baseUrl: string;\n /** Initial credentials for authentication */\n credentials?: {\n username: string;\n password: string;\n };\n /** Custom HTTP client timeout in milliseconds */\n timeoutMs?: number;\n /** Request credentials mode for fetch (omit, same-origin, include) */\n requestCredentials?: RequestCredentials;\n /** Optional token store for persistence */\n tokenStore?: TokenStore;\n /**\n * Called when the node reports that the credential family is gone\n * (`x-auth-error: token_reuse` / `token_revoked`). Terminal: the tokens have\n * already been cleared by the time this runs and nothing is retried, so use it\n * to send the user back through login. Errors thrown here are swallowed \u2014\n * never let a UI failure mask the auth error.\n */\n onAuthRevoked?: () => Promise<void> | void;\n}\n\nexport interface TokenData {\n access_token: string;\n refresh_token: string;\n expires_at: number;\n}\n\n/** Name of the Web Lock that serializes token refresh across tabs / webviews. */\nconst REFRESH_LOCK_NAME = 'mero-js:token-refresh';\n\n/** Minimal structural view of the Web Locks API (not available in every runtime). */\ninterface LockManagerLike {\n request<T>(name: string, callback: () => Promise<T>): Promise<T>;\n}\n\n/** Returns `navigator.locks` when the runtime supports the Web Locks API. */\nfunction getLockManager(): LockManagerLike | null {\n const nav = (globalThis as unknown as { navigator?: { locks?: LockManagerLike } }).navigator;\n const locks = nav?.locks;\n return locks && typeof locks.request === 'function' ? locks : null;\n}\n\n/** Try to extract `exp` (seconds) from a JWT, return ms timestamp or fallback. */\nfunction expiresAtFromJwt(token: string, fallbackMs: number): number {\n try {\n const parts = token.split('.');\n if (parts.length === 3) {\n // JWT uses base64url encoding: replace -/_ with +// and add padding\n let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n while (b64.length % 4) b64 += '=';\n const payload = JSON.parse(atob(b64));\n if (typeof payload.exp === 'number') {\n return payload.exp * 1000;\n }\n }\n } catch {\n // not a JWT or can't parse\n }\n return fallbackMs;\n}\n\n/**\n * Main MeroJs SDK class that manages all API clients and authentication\n */\nexport class MeroJs {\n private config: MeroJsConfig;\n private httpClient: HttpClient;\n private authClient: AuthApiClient;\n private adminClient: AdminApiClient;\n private tokenData: TokenData | null = null;\n private refreshPromise: Promise<TokenData> | null = null;\n private tokenStore: TokenStore | null;\n private rpcClient: RpcClient | null = null;\n private sseClient: SseClient | null = null;\n private wsClient: WsClient | null = null;\n private wsWarned = false;\n private ephemeralClient?: EphemeralClient;\n\n constructor(config: MeroJsConfig) {\n this.config = {\n timeoutMs: 10000,\n ...config,\n };\n\n this.tokenStore = config.tokenStore ?? null;\n\n // Restore tokens from store if available\n if (this.tokenStore) {\n this.tokenData = this.tokenStore.getTokens();\n }\n\n // Create HTTP client with token management\n // For Tauri, explicitly set credentials to 'omit' to avoid network errors\n const isTauri = typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window;\n this.httpClient = createBrowserHttpClient({\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n refreshToken: async () => {\n const refreshed = await this.performTokenRefresh();\n return refreshed.access_token;\n },\n onTokenRefresh: async (newToken: string) => {\n if (this.tokenData) {\n this.tokenData.access_token = newToken;\n this.tokenStore?.setTokens(this.tokenData);\n }\n },\n onAuthRevoked: async () => {\n // The refresh-token family is gone (a single-use refresh token was\n // replayed, or the token was revoked). Nothing left to refresh with \u2014\n // drop the bundle so the app can force a re-login, then let the app react.\n this.clearToken();\n try {\n await this.config.onAuthRevoked?.();\n } catch {\n // A failing app callback must not mask the auth error.\n }\n },\n timeoutMs: this.config.timeoutMs,\n credentials: this.config.requestCredentials ?? (isTauri ? 'omit' : undefined),\n });\n\n // Create API clients\n this.authClient = createAuthApiClientFromHttpClient(this.httpClient, {\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n timeoutMs: this.config.timeoutMs,\n });\n\n this.adminClient = createAdminApiClientFromHttpClient(this.httpClient, {\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n timeoutMs: this.config.timeoutMs,\n });\n }\n\n /**\n * Get the Auth API client\n */\n get auth(): AuthApiClient {\n return this.authClient;\n }\n\n /**\n * Get the Admin API client\n */\n get admin(): AdminApiClient {\n return this.adminClient;\n }\n\n /**\n * Get the RPC client (lazy initialized)\n */\n get rpc(): RpcClient {\n if (!this.rpcClient) {\n this.rpcClient = new RpcClient({ httpClient: this.httpClient });\n }\n return this.rpcClient;\n }\n\n /**\n * Get the SSE event client (lazy initialized)\n */\n get events(): SseClient {\n if (!this.sseClient) {\n this.sseClient = new SseClient({\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n });\n }\n return this.sseClient;\n }\n\n /**\n * Get the ephemeral-presence client (lazy initialized).\n *\n * Shares this instance's SSE client, so `subscribe` reuses the one event\n * stream rather than opening a second connection.\n */\n get ephemeral(): EphemeralClient {\n if (!this.ephemeralClient) {\n this.ephemeralClient = new EphemeralClient({\n httpClient: this.httpClient,\n sse: this.events,\n });\n }\n return this.ephemeralClient;\n }\n\n /**\n * Get the WebSocket event client (lazy initialized).\n * @experimental Use `events` (SSE) for production. WsClient is experimental.\n */\n get ws(): WsClient {\n if (!this.wsWarned) {\n this.wsWarned = true;\n console.warn('[mero-js] WsClient is experimental. Use mero.events (SSE) for production.');\n }\n if (!this.wsClient) {\n this.wsClient = new WsClient({\n baseUrl: this.config.baseUrl,\n getAuthToken: async () => {\n const token = await this.getValidToken();\n return token?.access_token || '';\n },\n });\n }\n return this.wsClient;\n }\n\n /**\n * Authenticate with the provided credentials\n * This will create the root key on first use\n */\n async authenticate(credentials?: {\n username: string;\n password: string;\n }): Promise<TokenData> {\n const creds = credentials || this.config.credentials;\n if (!creds) {\n throw new Error('No credentials provided for authentication');\n }\n\n try {\n const requestBody = {\n auth_method: 'user_password',\n public_key: creds.username,\n client_name: 'mero-js-sdk',\n permissions: ['admin'],\n timestamp: Math.floor(Date.now() / 1000),\n provider_data: {\n username: creds.username,\n password: creds.password,\n },\n };\n\n const response = await this.authClient.generateTokens(requestBody);\n\n const accessToken = response.data.access_token;\n this.tokenData = {\n access_token: accessToken,\n refresh_token: response.data.refresh_token,\n expires_at: expiresAtFromJwt(accessToken, Date.now() + 3600_000),\n };\n\n this.tokenStore?.setTokens(this.tokenData);\n\n return this.tokenData;\n } catch (error) {\n throw new Error(\n `Authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Get a valid token. Returns the current token as-is.\n * The server rejects refresh attempts while the access token is still valid,\n * so we never proactively refresh. Instead, the WebHttpClient handles 401\n * responses reactively via the refreshToken transport hook.\n */\n private async getValidToken(): Promise<TokenData | null> {\n return this.tokenData;\n }\n\n /**\n * Refresh the access token. Single-flight: every caller (including the HTTP\n * transport's 401 hook) goes through here.\n *\n * Refresh tokens are single-use (calimero-network/core#3083): each refresh\n * consumes the presented token and returns a new one, and replaying a consumed\n * token makes the server revoke the whole family. A refresh must therefore\n * happen exactly once per rotation, which needs three layers:\n * - an in-process promise, so concurrent 401s in this instance share one call;\n * - a Web Lock (when available), so other tabs/webviews don't refresh at the\n * same time on the same stored token;\n * - a re-read of the token store inside the lock, so a bundle that another\n * instance already rotated is adopted instead of replaying a stale token.\n */\n private async performTokenRefresh(): Promise<TokenData> {\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n // The access token that triggered this refresh. If the store holds a different\n // one by the time we get the lock, someone else already rotated for us.\n const triggeringAccessToken = this.tokenData?.access_token;\n\n const promise = this.withRefreshLock(() =>\n this.performTokenRefreshLocked(triggeringAccessToken),\n );\n this.refreshPromise = promise;\n\n try {\n return await promise;\n } finally {\n if (this.refreshPromise === promise) {\n this.refreshPromise = null;\n }\n }\n }\n\n /** Run `fn` under the cross-tab refresh lock, or directly if Web Locks are unavailable. */\n private withRefreshLock<T>(fn: () => Promise<T>): Promise<T> {\n const locks = getLockManager();\n return locks ? locks.request(REFRESH_LOCK_NAME, fn) : fn();\n }\n\n /**\n * Perform the actual token refresh. Runs with the refresh lock held.\n */\n private async performTokenRefreshLocked(\n triggeringAccessToken?: string,\n ): Promise<TokenData> {\n // Another instance/tab may have rotated the bundle while we were queued behind\n // the lock \u2014 the store, not our in-memory copy, is the source of truth.\n const stored = this.tokenStore?.getTokens() ?? null;\n if (stored?.refresh_token) {\n this.tokenData = stored;\n\n if (triggeringAccessToken && stored.access_token !== triggeringAccessToken) {\n // Someone else already refreshed. Reuse their bundle rather than replaying\n // our (now consumed) refresh token, which would revoke the family.\n return stored;\n }\n }\n\n if (!this.tokenData?.refresh_token) {\n throw new Error('No refresh token available');\n }\n\n try {\n const response = await this.authClient.refreshToken({\n access_token: this.tokenData.access_token,\n refresh_token: this.tokenData.refresh_token,\n });\n\n const accessToken = response.data.access_token;\n this.tokenData = {\n access_token: accessToken,\n // The refresh token is rotated on every refresh \u2014 persist the new one or\n // the next refresh replays a consumed token.\n refresh_token: response.data.refresh_token,\n expires_at: expiresAtFromJwt(accessToken, Date.now() + 3600_000),\n };\n\n this.tokenStore?.setTokens(this.tokenData);\n\n return this.tokenData;\n } catch (error) {\n // Don't clear tokens on refresh failure \u2014 the access token may still be\n // valid (server rejects refresh while access token hasn't expired yet).\n // A genuinely dead family arrives as `x-auth-error: token_reuse` and is\n // handled by the onAuthRevoked transport hook. Let the caller handle this.\n throw new Error(\n `Token refresh failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Clear the current token\n */\n public clearToken(): void {\n this.refreshPromise = null;\n this.tokenData = null;\n this.tokenStore?.clear();\n }\n\n /**\n * Check if the SDK is authenticated\n */\n public isAuthenticated(): boolean {\n return this.tokenData !== null;\n }\n\n /**\n * Set token data directly (e.g., from auth callback).\n * If `expires_at` is missing or 0, attempts to parse the JWT exp claim,\n * falling back to 1 hour from now.\n */\n public setTokenData(data: TokenData): void {\n const expiresAt = data.expires_at || expiresAtFromJwt(data.access_token, Date.now() + 3600_000);\n this.tokenData = { ...data, expires_at: expiresAt };\n this.tokenStore?.setTokens(this.tokenData);\n }\n\n /**\n * Get the current token data (for debugging)\n */\n public getTokenData(): TokenData | null {\n return this.tokenData;\n }\n\n /**\n * Close all event connections and clean up resources\n */\n public close(): void {\n this.sseClient?.close();\n this.wsClient?.close();\n }\n\n /**\n * Parse an auth callback URL hash fragment (static utility)\n */\n static parseAuthCallback(url: string): AuthCallbackResult | null {\n return parseAuthCallback(url);\n }\n\n /**\n * Build an auth login URL (static utility)\n */\n static buildAuthLoginUrl(nodeUrl: string, opts: AuthLoginOptions): string {\n return buildAuthLoginUrl(nodeUrl, opts);\n }\n}\n\n/**\n * Create a new MeroJs SDK instance\n */\nexport function createMeroJs(config: MeroJsConfig): MeroJs {\n return new MeroJs(config);\n}\n", "import type { TokenData } from '../mero-js.js';\n\nexport interface TokenStore {\n getTokens(): TokenData | null;\n setTokens(data: TokenData): void;\n clear(): void;\n}\n\nexport class MemoryTokenStore implements TokenStore {\n private tokens: TokenData | null = null;\n\n getTokens(): TokenData | null {\n return this.tokens;\n }\n\n setTokens(data: TokenData): void {\n this.tokens = data;\n }\n\n clear(): void {\n this.tokens = null;\n }\n}\n\nconst STORAGE_KEY = 'mero-tokens';\n\nexport class LocalStorageTokenStore implements TokenStore {\n private readonly key: string;\n\n constructor(key: string = STORAGE_KEY) {\n this.key = key;\n }\n\n getTokens(): TokenData | null {\n try {\n if (typeof localStorage === 'undefined') return null;\n const raw = localStorage.getItem(this.key);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (parsed && parsed.access_token && parsed.refresh_token) {\n return {\n access_token: parsed.access_token,\n refresh_token: parsed.refresh_token,\n expires_at: typeof parsed.expires_at === 'number' ? parsed.expires_at : Date.now() + 3600_000,\n };\n }\n return null;\n } catch {\n return null;\n }\n }\n\n setTokens(data: TokenData): void {\n try {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.key, JSON.stringify(data));\n } catch {\n // Storage unavailable\n }\n }\n\n clear(): void {\n try {\n if (typeof localStorage === 'undefined') return;\n localStorage.removeItem(this.key);\n } catch {\n // Storage unavailable\n }\n }\n}\n", "export interface CloudClientConfig {\n cloudBaseUrl?: string;\n}\n\nexport interface EnableHAOptions {\n groupId: string;\n contextId: string;\n redirectUrl?: string;\n}\n\nexport interface DisableHAOptions {\n groupId: string;\n contextId: string;\n redirectUrl?: string;\n}\n\nexport class CloudClient {\n private baseUrl: string;\n\n constructor(config: CloudClientConfig = {}) {\n this.baseUrl = (config.cloudBaseUrl || 'https://cloud.calimero.network').replace(/\\/+$/, '');\n }\n\n enableHA(options: EnableHAOptions): void {\n const params = new URLSearchParams({\n group_id: options.groupId,\n context_id: options.contextId,\n });\n if (options.redirectUrl) {\n params.set('redirect_url', options.redirectUrl);\n }\n window.open(`${this.baseUrl}/enable-ha?${params.toString()}`);\n }\n\n disableHA(options: DisableHAOptions): void {\n const params = new URLSearchParams({\n group_id: options.groupId,\n context_id: options.contextId,\n });\n if (options.redirectUrl) {\n params.set('redirect_url', options.redirectUrl);\n }\n window.open(`${this.baseUrl}/disable-ha?${params.toString()}`);\n }\n}\n", "/**\n * Byte-level primitives shared by everything in this package that signs.\n *\n * Extracted from `warrant/warrant.ts` when the device-cert signer arrived and\n * needed the same `domainHash`, hex handling and ed25519 import. Keeping one\n * copy is the point: these have to stay byte-identical with core, and two\n * copies drifting apart is exactly the failure the byte-parity e2e exists to\n * catch. Internal \u2014 not exported from the package root.\n */\n\nconst PKCS8_ED25519_PREFIX = new Uint8Array([\n 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04,\n 0x22, 0x04, 0x20,\n]);\n\n/** Little-endian u32, for borsh fixed-width fields and epoch counters. */\nexport function u32le(value: number): Uint8Array {\n const out = new Uint8Array(4);\n new DataView(out.buffer).setUint32(0, value, true);\n return out;\n}\n\nexport function hex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport function fromHex(value: string, label: string, expectedBytes: number): Uint8Array {\n const clean = value.trim();\n if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {\n throw new Error(\n `${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`,\n );\n }\n // Indexed rather than `match(/../g)!`: the length is already validated above,\n // so the assertion would only be telling the compiler what the guard proved,\n // and this needs no assertion at all.\n const bytes = new Uint8Array(expectedBytes);\n for (let i = 0; i < expectedBytes; i += 1) {\n bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\nexport function u64le(value: number | bigint): Uint8Array {\n const out = new Uint8Array(8);\n new DataView(out.buffer).setBigUint64(0, BigInt(value), true);\n return out;\n}\n\nexport function concat(...parts: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n\n/**\n * core's `domain_hash`: SHA-256 over the length-prefixed domain, then each\n * length-prefixed part. The lengths are what stop two different field splits from\n * hashing alike.\n */\nexport async function domainHash(\n domain: Uint8Array,\n parts: Uint8Array[],\n): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [u64le(domain.length), domain];\n for (const part of parts) {\n chunks.push(u64le(part.length), part);\n }\n return new Uint8Array(\n await crypto.subtle.digest('SHA-256', concat(...chunks)),\n );\n}\n\nexport async function importSigningKey(secretHex: string): Promise<CryptoKey> {\n const seed = fromHex(secretHex, 'deviceSecret', 32);\n const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);\n try {\n return await crypto.subtle.importKey(\n 'pkcs8',\n pkcs8,\n { name: 'Ed25519' },\n false,\n ['sign'],\n );\n } catch (cause) {\n // The original message is folded in rather than passed as `cause`: this\n // package targets ES2020, where `Error` has no `cause` option.\n const detail = cause instanceof Error ? `: ${cause.message}` : '';\n throw new Error(\n 'this runtime has no WebCrypto Ed25519, so a warrant cannot be signed ' +\n 'here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it; ' +\n 'otherwise mint the warrant with `merod account warrant`' +\n detail,\n );\n }\n}\n\n/**\n * The public half of an ed25519 seed.\n *\n * Derived rather than taken as an argument, for the reason core does the same: a\n * caller able to name a key it does not hold could produce a warrant it cannot\n * sign, and the field would stop meaning \"who authorised this\".\n */\nexport async function derivePublicKey(secretHex: string): Promise<Uint8Array> {\n const seed = fromHex(secretHex, 'deviceSecret', 32);\n const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);\n const key = await crypto.subtle.importKey(\n 'pkcs8',\n pkcs8,\n { name: 'Ed25519' },\n true,\n ['sign'],\n );\n const jwk = await crypto.subtle.exportKey('jwk', key);\n const raw = (jwk as JsonWebKey & { x: string }).x;\n return Uint8Array.from(atob(raw.replace(/-/g, '+').replace(/_/g, '/')), (c) =>\n c.charCodeAt(0),\n );\n}\n", "/**\n * Mint a warrant: the author's consent for one relay to run one intent, once.\n *\n * This exists because the case delegated authorship is *for* is an account that\n * holds no node \u2014 a browser tab, a Node service, a bot. Every one of those is a\n * JS runtime, and until now the only thing that could mint a warrant was `merod`,\n * so \"a member with no node\" in practice meant \"a member with a node it is not\n * allowed to use for anything else\".\n *\n * **No dependencies, and that is not incidental.** The three primitives are all\n * built in: `crypto.subtle.digest('SHA-256')` for the hash, `crypto.subtle`\n * Ed25519 for the signature, and `DataView.setBigUint64` for the two u64s. The\n * warrant's every field is fixed-width, so its encoding is concatenation \u2014 there\n * is no borsh here because none is needed.\n *\n * **The byte contract is pinned in core**, at\n * `crates/account/src/tests/warrant_wire_fixture.rs`. The domain strings below\n * are `pub(crate)` there, so nothing in that repository forces anyone to notice\n * this file depends on them \u2014 which is exactly why the fixture lives on that side\n * and this module's test asserts the same vectors. A drift would otherwise leave\n * this producing well-formed warrants whose signatures verify nowhere, surfacing\n * at a relay as a 403: an authorization refusal, nowhere near the cause.\n */\n\nimport {\n concat,\n derivePublicKey,\n domainHash,\n fromHex,\n hex,\n importSigningKey,\n u64le,\n} from '../crypto/internal.js';\n\nconst SIGN_DOMAIN = new TextEncoder().encode('calimero.warrant.v1');\nconst INTENT_DOMAIN = new TextEncoder().encode('calimero.warrant.intent.v1');\n\n/** Ed25519 PKCS#8 prefix, so a raw 32-byte seed can be imported by WebCrypto. */\n/** What a warrant authorises. */\nexport interface WarrantInput {\n /**\n * The context, hex \u2014 the same string every other method here takes.\n *\n * Hex like everything else on this interface. It was base58 while the node\n * spelled `ContextId` and `PublicKey` that way and `AccountId` and `DeviceId`\n * in hex; that split is gone, so this module no longer needs a rule per field\n * and no longer needs a base58 decoder to enforce one.\n */\n context: string;\n /** The author's account, hex \u2014 whose consent this is. */\n authorAccount: string;\n /** The relay authorised to act, hex. An account, not a key. */\n executor: string;\n /** The method the relay may run. */\n method: string;\n /** Its arguments, as the JSON the guest will receive. */\n argsJson: unknown;\n /**\n * Monotonic per author **device**.\n *\n * Per device rather than per account because two devices of one account are\n * independent replicas: they cannot coordinate on a counter, so an\n * account-scoped sequence would have them refusing each other's warrants.\n */\n nonce: number | bigint;\n /** Unix seconds after which the relay must refuse it. */\n notAfter: number | bigint;\n /**\n * The author device's ed25519 signing secret, hex (32 bytes).\n *\n * Never sent anywhere. It signs locally and only the signature travels, which\n * is the whole reason a warrant can be minted by something holding no node.\n */\n deviceSecret: string;\n}\n\n\n\n\n\n\n\n/**\n * The commitment a warrant carries in place of the intent itself.\n *\n * Its own domain, distinct from the signing one, so a value computed for one\n * purpose cannot be presented for the other.\n */\nexport async function intentHash(\n method: string,\n argsJson: unknown,\n): Promise<Uint8Array> {\n const args = new TextEncoder().encode(JSON.stringify(argsJson));\n return domainHash(INTENT_DOMAIN, [new TextEncoder().encode(method), args]);\n}\n\n\n/**\n * Sign a warrant and return it hex-encoded, ready for `performIntent`.\n *\n * The 240 bytes are the canonical form: the signature covers exactly them, which\n * is why this returns the encoding rather than an object. A caller that rebuilt\n * the fields from JSON would have a second spelling able to disagree with what\n * was signed.\n */\nexport async function signWarrant(input: WarrantInput): Promise<string> {\n const context = fromHex(input.context, 'context', 32);\n const authorAccount = fromHex(input.authorAccount, 'authorAccount', 32);\n const executor = fromHex(input.executor, 'executor', 32);\n\n const key = await importSigningKey(input.deviceSecret);\n const publicKey = await derivePublicKey(input.deviceSecret);\n\n const commitment = await intentHash(input.method, input.argsJson);\n const nonce = u64le(input.nonce);\n const notAfter = u64le(input.notAfter);\n\n const preimage = await domainHash(SIGN_DOMAIN, [\n context,\n authorAccount,\n publicKey,\n executor,\n commitment,\n nonce,\n notAfter,\n ]);\n\n const signature = new Uint8Array(\n await crypto.subtle.sign({ name: 'Ed25519' }, key, preimage),\n );\n\n return hex(\n concat(\n context,\n authorAccount,\n publicKey,\n executor,\n commitment,\n nonce,\n notAfter,\n signature,\n ),\n );\n}\n\n", "/**\n * Minting and certifying a device offline, with a key that never reaches a node.\n *\n * This is the second half of the keyholder story. `signWarrant` lets an account\n * with no node *write*; this lets one exist in the first place \u2014 an account root\n * certifies a device, and the resulting credential is what a joiner presents.\n *\n * As with the warrant signer, the risk is that this reproduces core's encoding\n * and has to keep doing so. The answer is the same: a golden vector here, and an\n * e2e that diffs this output against `merod account sign-cert` byte for byte.\n *\n * Everything below is derived from core:\n *\n * - `DeviceCert::signing_payload` \u2014 `crates/account/src/device.rs`\n * - `DeviceId::mint` \u2014 `crates/primitives/src/identity.rs`\n * - `AccountProof` / `AccountGenesis` borsh layout \u2014 `crates/account/src/{signed,account}.rs`\n */\nimport {\n concat,\n derivePublicKey,\n domainHash,\n fromHex,\n hex,\n importSigningKey,\n u32le,\n} from '../crypto/internal.js';\n\nconst CERT_DOMAIN = new TextEncoder().encode('calimero.device.cert.v1');\nconst ACCOUNT_ID_DOMAIN = new TextEncoder().encode('calimero.account.genesis.v1');\nconst DEVICE_ID_DOMAIN = new TextEncoder().encode('calimero.device.id.v1');\n\n/** `AccountGenesis::version`, which the credential's borsh encoding leads with. */\n/**\n * Core's `ACCOUNT_GENESIS_VERSION`. It is part of the `AccountId` preimage, so\n * this value decides which account a root key names \u2014 a mismatch does not fail\n * as a version error at the edge, it silently derives a different account and\n * core refuses the credential as unverifiable.\n *\n * `2` since the genesis dropped its per-namespace nonce. This was `1`, which\n * produced credentials current core rejects outright; the shape was already v2,\n * only the tag was stale.\n */\nconst ACCOUNT_GENESIS_VERSION = 2;\n\n/** What a root certifies about one device. */\nexport interface DeviceCertInput {\n /** The account root's signing secret, 64 hex. Signs the certificate. */\n rootSecret: string;\n /** The device being certified, 64 hex \u2014 see {@link mintDeviceId}. */\n device: string;\n /** The key that device signs with, 64 hex. */\n signPublicKey: string;\n /** The key the group key is delivered to, 64 hex (X25519). */\n kemPublicKey: string;\n /**\n * Must strictly exceed any epoch already folded for this device.\n *\n * The projection refuses a link that does not advance it, so a re-issued\n * certificate reusing an epoch is inert rather than a rollback.\n */\n deviceEpoch: number;\n}\n\n/**\n * Mint a device id: `H(DEVICE_ID_DOMAIN, account \u2016 nonce)`.\n *\n * Derived from the account and a fresh nonce rather than from the device's keys,\n * so rotating a keypair keeps the replica identity \u2014 and with it the counter\n * slots and HLC lineage \u2014 intact.\n */\nexport async function mintDeviceId(\n account: string,\n nonce: Uint8Array,\n): Promise<string> {\n if (nonce.length !== 16) {\n throw new Error(`nonce must be 16 bytes, got ${nonce.length}`);\n }\n const accountBytes = fromHex(account, 'account', 32);\n return hex(await domainHash(DEVICE_ID_DOMAIN, [accountBytes, nonce]));\n}\n\n/**\n * The 32 bytes a root signs to certify a device.\n *\n * Both keys are covered, so neither the signing key nor the delivery key can be\n * substituted into a certificate that otherwise verifies \u2014 which is what stops a\n * relay carrying someone's credential from making itself the reader.\n */\nexport async function deviceCertPayload(input: {\n account: string;\n device: string;\n signPublicKey: string;\n kemPublicKey: string;\n keyEpoch: number;\n deviceEpoch: number;\n}): Promise<Uint8Array> {\n return domainHash(CERT_DOMAIN, [\n fromHex(input.account, 'account', 32),\n fromHex(input.device, 'device', 32),\n fromHex(input.signPublicKey, 'signPublicKey', 32),\n fromHex(input.kemPublicKey, 'kemPublicKey', 32),\n u32le(input.keyEpoch),\n u32le(input.deviceEpoch),\n ]);\n}\n\n/**\n * Borsh-encode an `AccountProof<DeviceCert>` \u2014 what core calls a\n * `JoinAccountCredential`.\n *\n * Extracted so the device-cert path and the namespace-op signer encode this from\n * one implementation. Two copies of a borsh layout drift silently: the encoding\n * is only checked by a peer rejecting a signature, which points at the signature\n * rather than at whichever copy went stale.\n *\n * Layout is `AccountProof { genesis, chain, statement }`:\n * `AccountGenesis` (version u8 + root pk 32) + `chain` (empty Vec, u32 len) +\n * `DeviceCert` (account 32 + device 32 + sign pk 32 + kem pk 32 + key_epoch u32\n * + device_epoch u32 + signature 64) = 237 bytes with an empty chain.\n */\nexport function accountProofBytes(input: {\n rootPublicKey: Uint8Array;\n account: string;\n device: string;\n signPublicKey: string;\n kemPublicKey: string;\n keyEpoch: number;\n deviceEpoch: number;\n signature: Uint8Array;\n}): Uint8Array {\n return concat(\n new Uint8Array([ACCOUNT_GENESIS_VERSION]),\n input.rootPublicKey,\n u32le(0),\n fromHex(input.account, 'account', 32),\n fromHex(input.device, 'device', 32),\n fromHex(input.signPublicKey, 'signPublicKey', 32),\n fromHex(input.kemPublicKey, 'kemPublicKey', 32),\n u32le(input.keyEpoch),\n u32le(input.deviceEpoch),\n input.signature,\n );\n}\n\n/**\n * Certify a device, returning the hex credential `merod account sign-cert`\n * prints \u2014 a borsh-encoded `AccountProof<DeviceCert>`.\n *\n * The layout, field for field, is core's:\n *\n * ```\n * AccountProof { genesis: AccountGenesis, chain: Vec<RootKeyHandoff>, statement: DeviceCert }\n * AccountGenesis { version: u8, root_sign_pk: [u8; 32] }\n * chain \u2192 u32-LE count, then that many handoffs\n * DeviceCert { account, device, sign_pk, kem_pk: [u8; 32] x4,\n * key_epoch: u32, device_epoch: u32, signature: [u8; 64] }\n * ```\n *\n * Borsh for plain fixed-width data is concatenation; the only variable part is\n * the chain's length prefix. `chain` is empty here for the same reason it is in\n * `sign-cert`: a root that has never been handed off signs directly, and a\n * handoff chain is only needed once it has.\n *\n * `keyEpoch` is 0 for the same reason \u2014 it names the root epoch that signed, and\n * an un-rotated root is at 0. Re-signing after a handoff is a separate flow that\n * needs the chain, so this deliberately does not take it as an argument rather\n * than accepting a value it would then have to ignore.\n */\nexport async function signDeviceCert(input: DeviceCertInput): Promise<string> {\n const rootPublicKey = await derivePublicKey(input.rootSecret);\n const account = hex(\n await domainHash(ACCOUNT_ID_DOMAIN, [\n concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey),\n ]),\n );\n\n const keyEpoch = 0;\n const payload = await deviceCertPayload({\n account,\n device: input.device,\n signPublicKey: input.signPublicKey,\n kemPublicKey: input.kemPublicKey,\n keyEpoch,\n deviceEpoch: input.deviceEpoch,\n });\n\n const key = await importSigningKey(input.rootSecret);\n const signature = new Uint8Array(\n await crypto.subtle.sign('Ed25519', key, payload),\n );\n\n const credential = accountProofBytes({\n rootPublicKey,\n account,\n device: input.device,\n signPublicKey: input.signPublicKey,\n kemPublicKey: input.kemPublicKey,\n keyEpoch,\n deviceEpoch: input.deviceEpoch,\n signature,\n });\n\n return hex(credential);\n}\n\n/** The account this root owns \u2014 the content address of its genesis. */\nexport async function accountForRoot(rootSecret: string): Promise<string> {\n const rootPublicKey = await derivePublicKey(rootSecret);\n return hex(\n await domainHash(ACCOUNT_ID_DOMAIN, [\n concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey),\n ]),\n );\n}\n", "/**\n * Sign a namespace governance op from the SDK \u2014 specifically the membership op a\n * keyholder needs to join without running a node.\n *\n * `admitJoin` carries an already-signed op to a node the inviter named as an\n * admitter. Producing that op is the piece a keyholder could not do before: the\n * op must be signed by the device key in the credential it carries, because every\n * peer checks `signer == credential.statement.sign_pk` when applying a join. An\n * admitter can relay it and can never author it.\n *\n * The encoding is borsh, hand-written to match core's structs. Correctness is not\n * asserted against bytes recorded here \u2014 a layout transcribed by eye is exactly\n * how a golden ends up confidently wrong. It is asserted by a node accepting the\n * op, which is what the e2e does.\n */\nimport type { SignedGroupOpenInvitation } from '../admin-api/admin-types.js';\nimport {\n concat,\n derivePublicKey,\n fromHex,\n hex,\n importSigningKey,\n u32le,\n u64le,\n} from '../crypto/internal.js';\n\n/** Core's `SIGNED_NAMESPACE_OP_SCHEMA_VERSION`. A node refuses any other value. */\nexport const SIGNED_NAMESPACE_OP_SCHEMA_VERSION = 8;\n\n/** Domain prefixed to the signable bytes; core's `NAMESPACE_GOVERNANCE_SIGN_DOMAIN`. */\nconst NAMESPACE_SIGN_DOMAIN = new TextEncoder().encode('calimero.namespace.v1');\n\n/** `NamespaceOp::Root` is the first variant. */\nconst NAMESPACE_OP_ROOT = 0;\n\n/**\n * `RootOp` discriminants, in declaration order. Only the two join variants are\n * emitted here; the rest are listed so the numbering is checkable against core\n * rather than inferred from the two in use.\n */\nconst ROOT_OP = {\n GroupCreated: 0,\n GroupReparented: 1,\n GroupDeleted: 2,\n AdminChanged: 3,\n PolicyUpdated: 4,\n MemberJoined: 5,\n KeyDelivery: 6,\n MemberJoinedOpen: 7,\n MemberJoinedAt: 8,\n NamespaceCreated: 9,\n MemberJoinedViaTeeAttestation: 10,\n} as const;\n\n/** A required `[u8; 32]`, as JSON carries it: 32 byte values. */\nfunction bytes32(value: readonly number[], label: string): Uint8Array {\n if (value.length !== 32) {\n throw new Error(`${label} must be 32 bytes, got ${value.length}`);\n }\n return new Uint8Array(value);\n}\n\n/**\n * Borsh `Option<[u8; 32]>` from the byte array JSON carries it as.\n *\n * `[u8; 32]` crosses JSON as 32 numbers, not as hex \u2014 the hex spelling belongs to\n * `AccountId`, which has its own representation. Encoding one of these from a hex\n * string would silently produce the wrong 32 bytes.\n */\nfunction optionalBytes32(\n value: readonly number[] | null | undefined,\n label: string,\n): Uint8Array {\n if (value === null || value === undefined) {\n return new Uint8Array([0]);\n }\n if (value.length !== 32) {\n throw new Error(`${label} must be 32 bytes, got ${value.length}`);\n }\n return concat(new Uint8Array([1]), new Uint8Array(value));\n}\n\n/** Borsh `String`: u32 length then UTF-8 bytes. */\nfunction borshString(value: string): Uint8Array {\n const bytes = new TextEncoder().encode(value);\n return concat(u32le(bytes.length), bytes);\n}\n\n\n/**\n * Borsh-encode a `SignedGroupOpenInvitation`.\n *\n * Re-encoded rather than passed through, because it has to go inside the op that\n * gets signed. That makes this function version-locked to core: a field added to\n * the invitation and omitted here produces an op whose inner invitation no longer\n * matches the inviter's signature over it. That exact drift, in client-py, broke\n * 93 scenarios \u2014 the failure surfaces as `invalid invitation signature` and points\n * nowhere near the encoder.\n */\nexport function encodeSignedInvitation(signed: SignedGroupOpenInvitation): Uint8Array {\n const body = signed.invitation;\n const admitters = body.admitters ?? [];\n const admitterAddrs = signed.admitter_addrs ?? [];\n\n return concat(\n // GroupInvitationFromAdmin.\n //\n // `SignerId` and `ContextGroupId` cross JSON as 32 numbers; `AccountId`\n // crosses as hex. Same width, different spelling, and reading either the\n // wrong way yields 32 bytes that encode cleanly and verify as nothing.\n bytes32(body.inviter_identity, 'inviter_identity'),\n bytes32(body.group_id, 'group_id'),\n u64le(body.expiration_timestamp),\n bytes32(body.secret_salt, 'secret_salt'),\n new Uint8Array([body.invited_role]),\n u32le(admitters.length),\n ...admitters.map((a, i) => fromHex(a, `admitters[${i}]`, 32)),\n // ...then the enclosing SignedGroupOpenInvitation, in declaration order.\n // `inviter_account` sits between the signature and the addresses; putting it\n // anywhere else still encodes 32 bytes and still verifies as nothing.\n borshString(signed.inviter_signature),\n signed.inviter_account\n ? concat(new Uint8Array([1]), fromHex(signed.inviter_account, 'inviter_account', 32))\n : new Uint8Array([0]),\n // A `Vec<String>`, so each entry is a bare borsh string. This carried an\n // enum until core dropped the URL variant, and an enum writes a\n // discriminant byte ahead of each entry \u2014 encoding one here now would shift\n // every following byte and fail as `invalid invitation signature`, pointing\n // nowhere near this line.\n u32le(admitterAddrs.length),\n ...admitterAddrs.map(borshString),\n optionalBytes32(signed.application_id, 'application_id'),\n // Borsh order follows core's field order, where this is `bytecode_id`; the\n // JSON key is `app_key`, a rename covering both directions that core pins in\n // a test. Encoding by the Rust name would read `undefined` and emit a None\n // where the inviter signed a Some.\n optionalBytes32(signed.app_key, 'app_key'),\n );\n}\n\nexport interface SignMemberJoinInput {\n /** The namespace being joined, 64 hex. */\n readonly namespaceId: string;\n /** The account joining, 64 hex \u2014 the subject of the credential. */\n readonly member: string;\n /** The invitation, as the admin API returned it. */\n readonly invitation: SignedGroupOpenInvitation;\n /**\n * The joiner's `AccountProof<DeviceCert>`, hex \u2014 from `signDeviceCert`.\n *\n * Its `sign_pk` must be the public key of `deviceSecret`; a peer checks that\n * when applying the join and refuses otherwise.\n */\n readonly credential: string;\n /** The device signing secret, 64 hex. Must match the credential's `sign_pk`. */\n readonly deviceSecret: string;\n /**\n * Heads this op is written against. Empty means \"signed against an empty head\"\n * \u2014 which is NOT the same as genesis, and a node with a non-empty head will\n * reject it as stale rather than treat it as a first op.\n */\n readonly parentOpHashes?: readonly string[];\n /** Anti-replay nonce; a node keeps a window per signer. */\n readonly nonce: number | bigint;\n /**\n * When the join happened, unix seconds. Defaults to now.\n *\n * Carried only by `MemberJoinedAt`, which is the variant used whenever the\n * invitation expires \u2014 and since core clamps every invitation to\n * `MAX_INVITATION_VALIDITY_SECS`, that is every invitation. The variant is\n * inferred from the invitation rather than selected by a flag: an expiring\n * invitation joined with plain `MemberJoined` is refused at apply with\n * \"expiration is set but joined_at is absent\", which is not a mistake worth\n * leaving available.\n */\n readonly joinedAt?: number | bigint;\n}\n\n/**\n * Sign a `MemberJoined` (or `MemberJoinedAt`) namespace op and return it\n * borsh-encoded and hex \u2014 the `signedOp` that `admitJoin` takes.\n */\nexport async function signMemberJoinOp(input: SignMemberJoinInput): Promise<string> {\n const parents = input.parentOpHashes ?? [];\n const credential = fromHex(input.credential, 'credential', input.credential.length / 2);\n\n // An invitation that expires must be claimed with `MemberJoinedAt`, which\n // carries `joined_at` between the invitation and the credential. Choosing the\n // variant from the invitation keeps the two in step: the discriminant and the\n // presence of that field are one decision, and splitting them produces bytes\n // that decode into the wrong shape rather than failing to decode.\n const expires = BigInt(input.invitation.invitation.expiration_timestamp ?? 0) !== 0n;\n const joinedAt =\n input.joinedAt ?? BigInt(Math.floor(Date.now() / 1000));\n\n const rootOp = expires\n ? concat(\n new Uint8Array([ROOT_OP.MemberJoinedAt]),\n fromHex(input.member, 'member', 32),\n encodeSignedInvitation(input.invitation),\n u64le(joinedAt),\n credential,\n )\n : concat(\n new Uint8Array([ROOT_OP.MemberJoined]),\n fromHex(input.member, 'member', 32),\n encodeSignedInvitation(input.invitation),\n credential,\n );\n\n const op = concat(new Uint8Array([NAMESPACE_OP_ROOT]), rootOp);\n\n const key = await importSigningKey(input.deviceSecret);\n const signer = await derivePublicKey(input.deviceSecret);\n\n const signable = concat(\n new Uint8Array([SIGNED_NAMESPACE_OP_SCHEMA_VERSION]),\n fromHex(input.namespaceId, 'namespaceId', 32),\n u32le(parents.length),\n ...parents.map((p, i) => fromHex(p, `parentOpHashes[${i}]`, 32)),\n signer,\n u64le(input.nonce),\n op,\n );\n\n const signature = new Uint8Array(\n await crypto.subtle.sign('Ed25519', key, concat(NAMESPACE_SIGN_DOMAIN, signable)),\n );\n\n // The signed struct repeats the signable fields, then the signature, then the\n // admitter endorsement. The domain is a signing prefix only and is never part\n // of the encoded op.\n //\n // The endorsement is written as borsh `None` \u2014 a single `0x00` \u2014 and that is\n // the correct value from here, not a placeholder. It authorises the membership\n // and can only be signed by an account the invitation named as an admitter,\n // which a keyholder is not. The admitter attaches its own as it relays the op\n // through `admitJoin`.\n //\n // It sits outside `signable`, so it is outside this signature and outside the\n // op's id. That is what makes attaching it possible: the admitter changes\n // neither what was signed here nor which op this is.\n const unendorsed = new Uint8Array([0]);\n\n return hex(concat(signable, signature, unendorsed));\n}\n", "// Member capability bitmask constants \u2014 mirrors core's `MemberCapabilities`\n// (crates/context/config/src/lib.rs). The value stored per-member is a u32\n// bitmask. Core currently assigns bits 0..=8; bits 9 and above are unassigned\n// and may be claimed by future core versions, so an application MUST NOT\n// assume any particular bit is safe for its own use unless core documents it\n// as reserved for applications.\n\n/**\n * Capability bits as defined by core's `MemberCapabilities`.\n *\n * The per-member value is a u32 bitmask. Core currently assigns bits 0..=8\n * (the entries below); bits 9 and above are unassigned \u2014 do not repurpose\n * them for application data, as a future core release may claim them.\n */\nexport const CAPABILITIES = {\n CAN_CREATE_CONTEXT: 1 << 0,\n CAN_INVITE_MEMBERS: 1 << 1,\n CAN_JOIN_OPEN_SUBGROUPS: 1 << 2,\n MANAGE_MEMBERS: 1 << 3,\n MANAGE_APPLICATION: 1 << 4,\n CAN_CREATE_SUBGROUP: 1 << 5,\n CAN_DELETE_SUBGROUP: 1 << 6,\n CAN_MANAGE_VISIBILITY: 1 << 7,\n CAN_MANAGE_METADATA: 1 << 8,\n} as const;\n\nexport type CapabilityName = keyof typeof CAPABILITIES;\nexport type CapabilityBit = (typeof CAPABILITIES)[CapabilityName];\n\n/**\n * Returns true if `mask` has every bit of `cap` set. Both operands are\n * coerced to unsigned 32-bit (`>>> 0`) before comparing so a high bit such\n * as `1 << 31` doesn't fall foul of `&` yielding a signed result.\n */\nexport function hasCap(mask: number, cap: number): boolean {\n const capU32 = cap >>> 0;\n return ((mask & capU32) >>> 0) === capU32;\n}\n\n/** Returns `mask` with every bit of `cap` set (u32-normalized). */\nexport function withCap(mask: number, cap: number): number {\n return (mask | cap) >>> 0;\n}\n\n/** Returns `mask` with every bit of `cap` cleared (u32-normalized). */\nexport function withoutCap(mask: number, cap: number): number {\n return (mask & ~cap) >>> 0;\n}\n", "/**\n * Local-node discovery.\n *\n * Calimero dev/desktop nodes expose a public, unauthenticated health endpoint\n * at `GET {nodeUrl}/admin-api/health` that returns `{ \"data\": { \"status\":\n * \"alive\" } }`. The most common local layouts run on a small, well-known set of\n * ports, so instead of forcing the user to type a URL we probe those ports and\n * offer whatever is actually running.\n */\n\n/**\n * Default ports probed when discovering local nodes. Covers the two-node dev\n * stacks used across the Calimero apps (RPC + alt ports for node1 / node2).\n */\nexport const DEFAULT_LOCAL_NODE_PORTS = [2428, 2429, 2528, 2529] as const;\n\n/** Host used to build local candidate URLs. */\nconst LOCAL_HOST = 'localhost';\n\n/** Per-probe timeout. A reachable local node answers almost instantly; a\n * closed port rejects fast, but a firewalled/black-holed one can hang, so we\n * cap each probe. */\nconst DEFAULT_PROBE_TIMEOUT_MS = 2000;\n\nexport interface DiscoverLocalNodesOptions {\n /** Ports to probe. Defaults to {@link DEFAULT_LOCAL_NODE_PORTS}. */\n ports?: readonly number[];\n /** Per-probe timeout in ms. Defaults to 2000. */\n timeoutMs?: number;\n /** Abort the whole discovery (e.g. when the modal closes). */\n signal?: AbortSignal;\n}\n\n/** Build the canonical base URL for a local node on the given port. */\nexport function localNodeUrl(port: number): string {\n return `http://${LOCAL_HOST}:${port}`;\n}\n\n/**\n * Resolve an API `path` against a node `baseUrl`. Ensures the base ends with a\n * slash first, so a base that carries a path prefix (e.g. a `NODE_PATH_PREFIX`\n * deployment like `http://host/node1`) keeps that segment instead of having it\n * stripped by relative URL resolution.\n */\nexport function nodeEndpoint(baseUrl: string, path: string): string {\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n return new URL(path, base).toString();\n}\n\n/**\n * Probe a single node's health endpoint. Resolves `true` only when the node\n * answers with a 2xx and (when the body is JSON) reports a non-dead status.\n * Any network error, timeout, or non-ok response resolves `false` \u2014 never\n * throws (except on an external abort, which is swallowed as `false`).\n */\nexport async function probeNodeHealth(\n baseUrl: string,\n options: { timeoutMs?: number; signal?: AbortSignal } = {},\n): Promise<boolean> {\n const { timeoutMs = DEFAULT_PROBE_TIMEOUT_MS, signal } = options;\n\n // Already cancelled before we start \u2014 don't fetch, and don't register a\n // timer or listener that would then need cleanup.\n if (signal?.aborted) return false;\n\n // Per-probe timeout, also linked to the caller's abort signal so closing the\n // modal cancels every in-flight probe. Bind the signal to a local so the\n // cleanup below stays symmetric with registration without re-narrowing.\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n const abortSignal = signal;\n if (abortSignal) abortSignal.addEventListener('abort', onAbort, { once: true });\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const url = nodeEndpoint(baseUrl, 'admin-api/health');\n const res = await fetch(url, {\n method: 'GET',\n signal: controller.signal,\n });\n\n if (!res.ok) return false;\n\n // Health body is `{ data: { status: \"alive\" } }`, but tolerate plain\n // `{ status }` and non-JSON 2xx responses. A *missing* status is treated as\n // alive (the 2xx is enough); a status that is present but not \"alive\"\n // (including an explicit `null`) is treated as unhealthy.\n try {\n const body = (await res.json()) as\n | { data?: { status?: string | null }; status?: string | null }\n | undefined;\n const status =\n body?.data?.status !== undefined ? body?.data?.status : body?.status;\n if (status === undefined) return true;\n return typeof status === 'string' && status.toLowerCase() === 'alive';\n } catch {\n return true;\n }\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n if (abortSignal) abortSignal.removeEventListener('abort', onAbort);\n }\n}\n\n/**\n * Probe the configured local ports in parallel and return the base URLs that\n * responded as healthy, in the same order as the `ports` argument (which\n * defaults to ascending). Returns an empty array when nothing local is running.\n */\nexport async function discoverLocalNodes(\n options: DiscoverLocalNodesOptions = {},\n): Promise<string[]> {\n const { ports = DEFAULT_LOCAL_NODE_PORTS, timeoutMs, signal } = options;\n\n const results = await Promise.all(\n ports.map(async (port) => {\n const url = localNodeUrl(port);\n const ok = await probeNodeHealth(url, { timeoutMs, signal });\n return ok ? url : null;\n }),\n );\n\n return results.filter((url): url is string => url !== null);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["TERMINAL_AUTH_ERRORS"]
|
|
7
7
|
}
|