@calimero-network/mero-js 28.0.0 → 28.1.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/crypto/internal.ts", "../src/sealed/noise.ts", "../src/sealed/sealed.ts", "../src/sealed/sigstore-trust-root.ts", "../src/sealed/x509.ts", "../src/sealed/sigstore.ts", "../src/sealed/verify.ts", "../src/sealed/release.ts", "../src/cloud-v2/attestation.ts", "../src/cloud-v2/directory.ts", "../src/cloud-v2/errors.ts", "../src/cloud-v2/passkey.ts", "../src/cloud-v2/approvals.ts", "../src/cloud-v2/client.ts", "../src/cloud-v2/capabilities.ts", "../src/agent-gate/chacha20poly1305.ts", "../src/agent-gate/hpke.ts", "../src/agent-gate/gate.ts", "../src/agent-gate/policy.ts"],
4
- "sourcesContent": ["// Mero.js: the JavaScript client for Calimero 1.0, the confidential cloud.\n//\n// `CalimeroClient` verifies a node's TDX attestation, seals every request to\n// it, and signs people in with passkeys and machines with API keys. Everything\n// below it is the pieces it is built from, exported for callers who need one\n// on its own.\n\n// The client, its errors and its types\nexport * from './cloud-v2/index.js';\n\n// Sealed transport: requests encrypted end to end to a TEE node's attested key,\n// and the checks that decide whether a quote is trusted.\nexport * from './sealed/index.js';\n\n// Private agents (mero-tee's agent gate): attest one, claim it with your key,\n// give it its secrets sealed to its TD.\nexport * from './agent-gate/index.js';\n", "/**\n * Byte-level primitives shared by the sealed transport, the attestation check\n * and the agent gate: hex handling, fixed-width integers and concatenation.\n * Internal \u2014 not exported from the package root.\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\n/**\n * Decode hex of an unknown length.\n *\n * The sized {@link fromHex} is the right default \u2014 every key and digest here\n * has a fixed width, and checking it catches a truncated paste at the edge\n * rather than deep inside a signature check. This one exists for the already-\n * encoded structures whose length is genuinely variable: a device certificate,\n * a login statement, a request signature. It still rejects odd-length and\n * non-hex input, so the only check it gives up is the one that cannot apply.\n */\nexport function fromHexUnsized(value: string, label: string): Uint8Array {\n const clean = value.trim();\n if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {\n throw new Error(`${label} must be an even number of hex characters`);\n }\n const bytes = new Uint8Array(clean.length / 2);\n for (let i = 0; i < bytes.length; 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 * The Noise NK handshake (`Noise_NK_25519_AESGCM_SHA256`) that opens a sealed\n * session, written against WebCrypto from the Noise specification\n * (revision 34, http://www.noiseprotocol.org/noise.html). The node runs the\n * other side with `snow`; core's published vectors check the two against each\n * other.\n *\n * NK: the initiator knows the responder's static key in advance \u2014 here the\n * transport key the node's quote commits to \u2014 and sends nothing but an\n * ephemeral key before both ephemerals are mixed in, so everything after the\n * handshake has forward secrecy.\n */\n\nimport { concat } from '../crypto/internal.js';\n\nconst PROTOCOL_NAME = 'Noise_NK_25519_AESGCM_SHA256';\nconst DH_LEN = 32;\nconst TAG_LEN = 16;\n/** PKCS#8 wrapping of a raw X25519 private key (RFC 8410). */\nconst PKCS8_X25519_PREFIX = new Uint8Array([\n 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x04,\n 0x22, 0x04, 0x20,\n]);\n\n/** Noise's `SymmetricState`: the chaining key, the handshake hash and the cipher key. */\nexport class SymmetricState {\n private ck: Uint8Array;\n private h: Uint8Array;\n private k: CryptoKey | null = null;\n private n = 0;\n\n private constructor(h: Uint8Array) {\n this.ck = h;\n this.h = h;\n }\n\n static async initialize(): Promise<SymmetricState> {\n // A name of 32 bytes or fewer is used as the hash, zero-padded.\n const name = new TextEncoder().encode(PROTOCOL_NAME);\n const h = new Uint8Array(32);\n h.set(name);\n return new SymmetricState(h);\n }\n\n async mixHash(data: Uint8Array): Promise<void> {\n this.h = await sha256(concat(this.h, data));\n }\n\n async mixKey(inputKeyMaterial: Uint8Array): Promise<void> {\n const [ck, key] = await hkdf2(this.ck, inputKeyMaterial);\n this.ck = ck;\n this.k = await crypto.subtle.importKey('raw', key, 'AES-GCM', false, ['encrypt', 'decrypt']);\n this.n = 0;\n }\n\n async encryptAndHash(plaintext: Uint8Array): Promise<Uint8Array> {\n if (!this.k) throw new Error('Noise: no cipher key yet');\n const ciphertext = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: noiseNonce(this.n), additionalData: this.h },\n this.k,\n plaintext,\n ),\n );\n this.n += 1;\n await this.mixHash(ciphertext);\n return ciphertext;\n }\n\n async decryptAndHash(ciphertext: Uint8Array): Promise<Uint8Array> {\n if (!this.k) throw new Error('Noise: no cipher key yet');\n const plaintext = new Uint8Array(\n await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: noiseNonce(this.n), additionalData: this.h },\n this.k,\n ciphertext,\n ),\n );\n this.n += 1;\n await this.mixHash(ciphertext);\n return plaintext;\n }\n\n /** The initiator-to-responder key, then the responder-to-initiator key. */\n split(): Promise<[Uint8Array, Uint8Array]> {\n return hkdf2(this.ck, new Uint8Array());\n }\n}\n\nexport interface X25519KeyPair {\n privateKey: CryptoKey;\n publicKey: Uint8Array;\n}\n\n/**\n * Start an NK handshake to `remoteStatic`. `fixedEphemeral` pins the\n * ephemeral secret, for the published test vectors only; leave it out.\n */\nexport async function initiate(\n remoteStatic: Uint8Array,\n prologue: Uint8Array,\n fixedEphemeral?: Uint8Array,\n): Promise<{\n message1: Uint8Array;\n finish(message2: Uint8Array): Promise<{ payload: Uint8Array; split: [Uint8Array, Uint8Array] }>;\n}> {\n const state = await SymmetricState.initialize();\n await state.mixHash(prologue);\n // <- s (known in advance)\n await state.mixHash(remoteStatic);\n // -> e, es\n const ephemeral = await x25519KeyPair(fixedEphemeral);\n await state.mixHash(ephemeral.publicKey);\n await state.mixKey(await dh(ephemeral.privateKey, remoteStatic));\n const message1 = concat(ephemeral.publicKey, await state.encryptAndHash(new Uint8Array()));\n\n return {\n message1,\n async finish(message2) {\n if (message2.length < DH_LEN + TAG_LEN) throw new Error('Noise: message 2 is too short');\n // <- e, ee\n const remoteEphemeral = message2.slice(0, DH_LEN);\n await state.mixHash(remoteEphemeral);\n await state.mixKey(await dh(ephemeral.privateKey, remoteEphemeral));\n const payload = await state.decryptAndHash(message2.slice(DH_LEN));\n return { payload, split: await state.split() };\n },\n };\n}\n\nexport async function x25519KeyPair(secret?: Uint8Array): Promise<X25519KeyPair> {\n if (!secret) {\n let pair: CryptoKeyPair;\n try {\n pair = (await crypto.subtle.generateKey({ name: 'X25519' }, true, [\n 'deriveBits',\n ])) as CryptoKeyPair;\n } catch (error) {\n throw new Error(\n 'Sealed transport needs WebCrypto with X25519, which this runtime lacks ' +\n `(${(error as Error)?.name ?? 'no crypto.subtle'}). Current browsers and Node have ` +\n 'it; in React Native, install react-native-quick-crypto as the global crypto.',\n );\n }\n const publicKey = new Uint8Array(await crypto.subtle.exportKey('raw', pair.publicKey));\n return { privateKey: pair.privateKey, publicKey };\n }\n const privateKey = await crypto.subtle.importKey(\n 'pkcs8',\n concat(PKCS8_X25519_PREFIX, secret),\n { name: 'X25519' },\n true,\n ['deriveBits'],\n );\n const jwk = await crypto.subtle.exportKey('jwk', privateKey);\n return { privateKey, publicKey: base64UrlDecode(jwk.x as string) };\n}\n\nexport async function dh(privateKey: CryptoKey, publicKey: Uint8Array): Promise<Uint8Array> {\n const peer = await crypto.subtle.importKey('raw', publicKey, { name: 'X25519' }, false, []);\n return new Uint8Array(\n await crypto.subtle.deriveBits({ name: 'X25519', public: peer } as EcdhKeyDeriveParams, privateKey, 256),\n );\n}\n\n/** Noise's AESGCM nonce: 32 zero bits, then the counter as a big-endian u64. */\nfunction noiseNonce(n: number): Uint8Array {\n const nonce = new Uint8Array(12);\n new DataView(nonce.buffer).setBigUint64(4, BigInt(n), false);\n return nonce;\n}\n\nasync function sha256(data: Uint8Array): Promise<Uint8Array> {\n return new Uint8Array(await crypto.subtle.digest('SHA-256', data));\n}\n\nasync function hmacSha256(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {\n const hmacKey = await crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, [\n 'sign',\n ]);\n return new Uint8Array(await crypto.subtle.sign('HMAC', hmacKey, data));\n}\n\n/** Noise's `HKDF` with two outputs. */\nasync function hkdf2(chainingKey: Uint8Array, inputKeyMaterial: Uint8Array): Promise<[Uint8Array, Uint8Array]> {\n const temp = await hmacSha256(chainingKey, inputKeyMaterial);\n const first = await hmacSha256(temp, new Uint8Array([1]));\n const second = await hmacSha256(temp, concat(first, new Uint8Array([2])));\n return [first, second];\n}\n\nfunction base64UrlDecode(value: string): Uint8Array {\n const base64 = value.replace(/-/g, '+').replace(/_/g, '/');\n const binary = atob(base64 + '='.repeat((4 - (base64.length % 4)) % 4));\n return Uint8Array.from(binary, (char) => char.charCodeAt(0));\n}\n", "/**\n * Sealed transport: requests encrypted end to end to a TEE node's attested key.\n *\n * A node speaks plain HTTP and any TLS in front of it ends outside the enclave,\n * at whatever proxy or relay the operator runs, so everything crossing that hop\n * (the bearer token, JSON-RPC arguments, results) is readable there. Sealing\n * encrypts it so that only the attested TD can read it, and only the TD can\n * produce a response the client accepts.\n *\n * The client opens a session with a Noise NK handshake to the X25519 transport\n * key the node's quote commits to (`fetchAttestedKey`, `GET /attestation`). The\n * transport key only authenticates the node: the session keys come from both\n * sides' ephemeral keys, so once a session is gone (an hour at most) what was\n * sent in it cannot be opened, not even with the transport key. Each request\n * is sealed under the session; each response streams back in sealed frames, so\n * server-sent events are sealed too. WebSockets cannot be, and the node\n * refuses one inside the envelope with a 501.\n *\n * The node's side, and the wire format this implements byte for byte, are in\n * core's `crates/sealed` (`calimero-sealed`):\n *\n * ```text\n * handshake Noise_NK_25519_AESGCM_SHA256, prologue \"calimero/sealed-http/v2\"\n * request POST /sealed/v2/handshake 0x02 || transport_pk || Noise message 1\n * response 0x02 || Noise message 2 (payload = session_id(16) || lifetime secs, u32 BE)\n * keys (req key, resp key) = Split()\n * exchange POST /sealed/v2\n * header 0x02 || session_id(16) || request_id (u64 BE; from 1, each used once)\n * request header || AES-256-GCM(req key, nonce = request_id || 0u32, aad = header, inner)\n * response frames, each u32 BE length || AES-256-GCM(resp key,\n * nonce = request_id || frame index (u32 BE, from 0), aad = header, kind || data)\n * kind 0 = head (JSON), 1 = body bytes, 2 = end; no end frame = cut short\n * inner u32 BE head length || head (JSON) || body\n * ```\n *\n * `CalimeroClient` seals every request this way; {@link createSealedFetch} is\n * the same channel as a plain `fetch`.\n */\n\nimport { concat } from '../crypto/internal.js';\nimport { initiate } from './noise.js';\nimport type { DcapCollateral } from './verify.js';\n\n/** Where a session is opened, relative to the node's base URL. */\nexport const HANDSHAKE_PATH = '/sealed/v2/handshake';\n/** Where sealed requests are posted, relative to the node's base URL. */\nexport const SEALED_PATH = '/sealed/v2';\n/** Content type of every sealed body. */\nexport const SEALED_CONTENT_TYPE = 'application/vnd.calimero.sealed';\n\nconst VERSION = 2;\nconst PROLOGUE = new TextEncoder().encode('calimero/sealed-http/v2');\nconst SESSION_ID_LEN = 16;\nconst HEADER_LEN = 1 + SESSION_ID_LEN + 8;\nconst FRAME_HEAD = 0;\nconst FRAME_DATA = 1;\nconst FRAME_END = 2;\n/**\n * The largest frame the node sends: a kind byte, at most 64 KiB of data, a tag.\n * Anything larger is refused before it is buffered, so a proxy cannot make the\n * client hold an unbounded frame it has yet to authenticate.\n */\nconst MAX_FRAME_LEN = 1 + 64 * 1024 + 16;\n/** Far more than a handshake reply (69 bytes) ever is. */\nconst MAX_HANDSHAKE_REPLY = 1024;\n/** Open a new session this long before the node would drop the current one. */\nconst RENEW_BEFORE_MS = 60_000;\nconst TRANSPORT_BINDING_DOMAIN = 'calimero.tee-attest.transport-key.v1';\nconst NULL_BODY_STATUSES = [101, 204, 205, 304];\n\nconst utf8 = new TextEncoder();\n\n/** The node no longer holds the transport key this client attested (it restarted). */\nexport class StaleTransportKeyError extends Error {\n name = 'StaleTransportKeyError';\n\n constructor() {\n super('The node no longer holds the attested transport key; attest again for the current one');\n }\n}\n\n/** The node refused the envelope itself, before anything inside it ran. */\nexport class SealedTransportError extends Error {\n name = 'SealedTransportError';\n\n constructor(\n public status: number,\n public code: string | undefined,\n message: string,\n /** How long the node asked to wait before retrying (`Retry-After`), if it did. */\n public retryAfterMs?: number,\n ) {\n super(message);\n }\n}\n\n/**\n * What the attest endpoint puts in report data bytes `32..64` when asked to\n * bind its transport key. `inner` is what would have been there otherwise: the\n * expected application hash, or 32 zero bytes when none was asked for.\n * Mirrors core's `attest_transport_binding`.\n */\nexport async function transportKeyBinding(\n inner: Uint8Array,\n transportKey: Uint8Array,\n): Promise<Uint8Array> {\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n concat(utf8.encode(TRANSPORT_BINDING_DOMAIN), inner, transportKey),\n );\n return new Uint8Array(digest);\n}\n\nexport interface VerifyTransportQuote {\n /**\n * Verify `quoteB64` \u2014 never by asking the node being attested \u2014 and check\n * that its report data is `nonce || reportDataSuffix` (both hex). Resolve\n * true only when the quote is genuine, its measurements are ones you accept,\n * and the report data matches. {@link createQuoteVerifier} does all of this\n * in the page. `collateral` is what the node sent with the quote, when the\n * verifier asked for it.\n */\n (args: {\n quoteB64: string;\n nonce: string;\n reportDataSuffix: string;\n collateral?: DcapCollateral;\n }): Promise<boolean>;\n /**\n * Set by the verifiers this package builds. A Calimero 1.0 node sends no\n * collateral with its quote; the verifier fetches it itself.\n */\n readonly includeCollateral?: boolean;\n}\n\nexport interface SealedFetchOptions {\n /** The node's base URL. */\n baseUrl: string;\n /**\n * The node's attested transport key, or a function that attests and returns\n * it \u2014 typically `() => fetchAttestedKey(baseUrl, policy)`. Given a\n * function, a restarted node is handled: the key is attested again, through\n * your verifier, and the request retried once. Given bytes, a restart\n * surfaces as {@link StaleTransportKeyError}.\n */\n transportPublicKey: Uint8Array | (() => Promise<Uint8Array>);\n /** Fetch that carries the sealed envelope. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\n/**\n * A `fetch` that seals every request to the node's attested transport key.\n *\n * A request for any URL outside `baseUrl` is refused rather than sent in the\n * clear: falling back to plaintext would silently undo the point of sealing.\n */\nexport function createSealedFetch(options: SealedFetchOptions): typeof fetch {\n const base = new URL(options.baseUrl);\n const basePath = base.pathname.replace(/\\/+$/, '');\n const nodeUrl = `${base.origin}${basePath}`;\n const baseFetch = options.fetch ?? ((input, init) => fetch(input, init));\n const attest =\n typeof options.transportPublicKey === 'function' ? options.transportPublicKey : undefined;\n let transportKey: Promise<Uint8Array> = attest\n ? Promise.resolve().then(attest)\n : Promise.resolve(options.transportPublicKey as Uint8Array);\n // Attesting starts now, before any request awaits it. A node that fails to\n // attest must surface on the request that needed the key, not earlier as an\n // unhandled rejection; the failure is still thrown to every awaiter.\n transportKey.catch(() => undefined);\n let session: Promise<Session> | undefined;\n\n const openSession = async (): Promise<Session> => {\n try {\n return await handshake(baseFetch, nodeUrl, await checkedKey(transportKey));\n } catch (error) {\n if (!(error instanceof StaleTransportKeyError) || !attest) throw error;\n transportKey = Promise.resolve().then(attest);\n return handshake(baseFetch, nodeUrl, await checkedKey(transportKey));\n }\n };\n /** The session to use now, and the promise it came from, to name it if it turns out stale. */\n const currentSession = async (): Promise<[Session, Promise<Session>]> => {\n const pending = session ?? renew(undefined);\n const open = await pending;\n if (Date.now() < open.renewAt) return [open, pending];\n const renewed = renew(pending);\n return [await renewed, renewed];\n };\n // Replace the session only if it is still the one found stale, so concurrent\n // requests that all find it stale open one new session between them.\n const renew = (stale: Promise<Session> | undefined): Promise<Session> => {\n if (session === stale) {\n const opening = openSession();\n session = opening;\n opening.catch(() => {\n if (session === opening) session = undefined;\n });\n }\n return session as Promise<Session>;\n };\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = new Request(input, init);\n const url = new URL(request.url);\n if (url.origin !== base.origin || !url.pathname.startsWith(`${basePath}/`)) {\n throw new Error(`Refusing to send ${url.href} outside the sealed node at ${options.baseUrl}`);\n }\n const headers: Array<[string, string]> = [];\n request.headers.forEach((value, name) => headers.push([name, value]));\n const head = { method: request.method, path: url.pathname.slice(basePath.length) + url.search, headers };\n const body = new Uint8Array(await request.arrayBuffer());\n // The caller's own signal, not `request.signal`: a Request's signal follows\n // the one it was built from only through a weak reference (undici), so once\n // the Request is garbage collected (it is, while a stream stays open) an\n // abort no longer reaches the fetch, and an event stream never closes.\n const signal = init?.signal ?? (input instanceof Request ? input.signal : undefined);\n\n const send = async (open: Session): Promise<Response> => {\n const { requestId, header, envelope } = await sealRequest(open, head, body);\n const response = await baseFetch(`${nodeUrl}${SEALED_PATH}`, {\n method: 'POST',\n headers: { 'content-type': SEALED_CONTENT_TYPE },\n body: envelope,\n signal,\n });\n if (response.headers.get('content-type') !== SEALED_CONTENT_TYPE) {\n throw await envelopeRefusal(response);\n }\n return openResponse(response, open.responseKey, header, requestId);\n };\n\n const [open, pending] = await currentSession();\n try {\n return await send(open);\n } catch (error) {\n // The node refused the envelope before running anything in it, so the\n // request can be sent again safely under a new session.\n if (!(error instanceof SealedTransportError) || error.code !== 'unknown_session') throw error;\n return send(await renew(pending));\n }\n };\n}\n\nasync function checkedKey(key: Promise<Uint8Array>): Promise<Uint8Array> {\n const bytes = await key;\n if (bytes.length !== 32) throw new Error('transportPublicKey must be 32 bytes');\n return bytes;\n}\n\nexport interface Session {\n requestKey: CryptoKey;\n responseKey: CryptoKey;\n nextRequestId: number;\n renewAt: number;\n header(requestId: number): Uint8Array;\n}\n\nasync function handshake(\n baseFetch: typeof fetch,\n nodeUrl: string,\n transportKey: Uint8Array,\n): Promise<Session> {\n try {\n return await handshakeOnce(baseFetch, nodeUrl, transportKey);\n } catch (error) {\n // The node limits how fast sessions open. A refused handshake opened\n // nothing, so trying once more after the pause it asks for is safe.\n if (!(error instanceof SealedTransportError) || error.code !== 'busy') throw error;\n await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 1000));\n return handshakeOnce(baseFetch, nodeUrl, transportKey);\n }\n}\n\nasync function handshakeOnce(\n baseFetch: typeof fetch,\n nodeUrl: string,\n transportKey: Uint8Array,\n): Promise<Session> {\n const noise = await initiate(transportKey, PROLOGUE);\n const response = await baseFetch(`${nodeUrl}${HANDSHAKE_PATH}`, {\n method: 'POST',\n headers: { 'content-type': SEALED_CONTENT_TYPE },\n body: concat(new Uint8Array([VERSION]), transportKey, noise.message1),\n });\n if (response.headers.get('content-type') !== SEALED_CONTENT_TYPE) {\n throw await envelopeRefusal(response);\n }\n const reply = await readAtMost(response, MAX_HANDSHAKE_REPLY);\n return sessionFrom(noise, reply);\n}\n\n/** Finish the handshake with the node's reply. Exported for the published vectors. */\nexport async function sessionFrom(\n noise: Awaited<ReturnType<typeof initiate>>,\n reply: Uint8Array,\n): Promise<Session> {\n if (reply[0] !== VERSION) throw new Error('The handshake reply is malformed');\n let finished: Awaited<ReturnType<(typeof noise)['finish']>>;\n try {\n finished = await noise.finish(reply.slice(1));\n } catch {\n throw new Error('The handshake reply did not open: it did not come from the attested node');\n }\n const { payload, split } = finished;\n if (payload.length !== SESSION_ID_LEN + 4) throw new Error('The handshake reply is malformed');\n const sessionId = payload.slice(0, SESSION_ID_LEN);\n const lifetimeSecs = new DataView(payload.buffer, payload.byteOffset).getUint32(SESSION_ID_LEN, false);\n const [requestKey, responseKey] = await Promise.all([\n crypto.subtle.importKey('raw', split[0], 'AES-GCM', false, ['encrypt']),\n crypto.subtle.importKey('raw', split[1], 'AES-GCM', false, ['decrypt']),\n ]);\n split[0].fill(0);\n split[1].fill(0);\n return {\n requestKey,\n responseKey,\n nextRequestId: 1,\n renewAt: Date.now() + lifetimeSecs * 1000 - RENEW_BEFORE_MS,\n header(requestId) {\n const header = new Uint8Array(HEADER_LEN);\n header[0] = VERSION;\n header.set(sessionId, 1);\n new DataView(header.buffer).setBigUint64(1 + SESSION_ID_LEN, BigInt(requestId), false);\n return header;\n },\n };\n}\n\n/** Seal one request under the session's next request id. */\nexport async function sealRequest(\n session: Session,\n head: RequestHead,\n body: Uint8Array,\n): Promise<{ requestId: number; header: Uint8Array; envelope: Uint8Array }> {\n const requestId = session.nextRequestId;\n session.nextRequestId += 1;\n const header = session.header(requestId);\n const sealed = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: nonce(requestId, 0), additionalData: header },\n session.requestKey,\n joinInner(head, body),\n );\n return { requestId, header, envelope: concat(header, new Uint8Array(sealed)) };\n}\n\n/** `request_id || index`, as the node numbers them. */\nfunction nonce(requestId: number, index: number): Uint8Array {\n const bytes = new Uint8Array(12);\n const view = new DataView(bytes.buffer);\n view.setBigUint64(0, BigInt(requestId), false);\n view.setUint32(8, index, false);\n return bytes;\n}\n\nexport interface RequestHead {\n method: string;\n path: string;\n headers: Array<[string, string]>;\n}\n\nexport interface ResponseHead {\n status: number;\n headers: Array<[string, string]>;\n}\n\nfunction joinInner(head: RequestHead, body: Uint8Array): Uint8Array {\n const encoded = utf8.encode(JSON.stringify(head));\n const len = new Uint8Array(4);\n new DataView(len.buffer).setUint32(0, encoded.length, false);\n return concat(len, encoded, body);\n}\n\n/**\n * Open a sealed response as it streams: wait for its head, then hand back a\n * `Response` whose body opens each frame as it arrives. A frame that does not\n * open, arrives out of order, or a stream that stops before its end frame\n * errors the body rather than passing anything unauthenticated on.\n */\nexport async function openResponse(\n response: Response,\n responseKey: CryptoKey,\n header: Uint8Array,\n requestId: number,\n): Promise<Response> {\n if (!response.body) throw new Error('The sealed response has no body');\n const frames = frameReader(response.body.getReader());\n let index = 0;\n const next = async (): Promise<{ kind: number; data: Uint8Array } | null> => {\n const sealed = await frames.next();\n if (!sealed) return null;\n let plain: Uint8Array;\n try {\n plain = new Uint8Array(\n await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: nonce(requestId, index), additionalData: header },\n responseKey,\n sealed,\n ),\n );\n } catch {\n throw new Error('A sealed response frame did not open: it was not sealed by the attested node');\n }\n index += 1;\n return { kind: plain[0], data: plain.slice(1) };\n };\n\n const first = await next();\n if (!first || first.kind !== FRAME_HEAD) throw new Error('The sealed response is malformed');\n const head = JSON.parse(new TextDecoder().decode(first.data)) as ResponseHead;\n if (NULL_BODY_STATUSES.includes(head.status)) {\n await frames.cancel();\n return new Response(null, { status: head.status, headers: head.headers });\n }\n\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const frame = await next();\n if (!frame) {\n controller.error(new Error('The sealed response was cut short'));\n } else if (frame.kind === FRAME_DATA) {\n controller.enqueue(frame.data);\n } else if (frame.kind === FRAME_END) {\n controller.close();\n await frames.cancel();\n } else {\n controller.error(new Error('The sealed response is malformed'));\n }\n } catch (error) {\n controller.error(error);\n }\n },\n cancel() {\n return frames.cancel();\n },\n });\n return new Response(body, { status: head.status, headers: head.headers });\n}\n\n/** Split a byte stream into length-prefixed frames. */\nfunction frameReader(reader: ReadableStreamDefaultReader<Uint8Array>): {\n next(): Promise<Uint8Array | null>;\n cancel(): Promise<void>;\n} {\n let buffer = new Uint8Array();\n const fill = async (length: number): Promise<boolean> => {\n while (buffer.length < length) {\n const { done, value } = await reader.read();\n if (done) return false;\n buffer = concat(buffer, value);\n }\n return true;\n };\n return {\n async next() {\n if (!(await fill(4))) return null;\n const length = new DataView(buffer.buffer, buffer.byteOffset).getUint32(0, false);\n if (length > MAX_FRAME_LEN) {\n await reader.cancel();\n throw new Error('The sealed response is malformed: a frame is larger than the node sends');\n }\n if (!(await fill(4 + length))) return null;\n const frame = buffer.slice(4, 4 + length);\n buffer = buffer.slice(4 + length);\n return frame;\n },\n cancel: () => reader.cancel(),\n };\n}\n\n/** Read a body, refusing one longer than `limit` rather than buffering it. */\nasync function readAtMost(response: Response, limit: number): Promise<Uint8Array> {\n if (!response.body) return new Uint8Array();\n const reader = response.body.getReader();\n let bytes = new Uint8Array();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return bytes;\n bytes = concat(bytes, value);\n if (bytes.length > limit) {\n await reader.cancel();\n throw new Error('The handshake reply is malformed: it is too long');\n }\n }\n}\n\nasync function envelopeRefusal(response: Response): Promise<Error> {\n let code: string | undefined;\n let message = `Sealed request refused: HTTP ${response.status}`;\n try {\n const body = (await response.json()) as { error?: { code?: string; message?: string } };\n code = body?.error?.code;\n if (body?.error?.message) message = `Sealed request refused: ${body.error.message}`;\n } catch {\n // Not the node's JSON refusal \u2014 a proxy's page, most likely. The status is\n // all that can honestly be reported.\n }\n if (code === 'stale_transport_key') return new StaleTransportKeyError();\n const retryAfter = Number(response.headers.get('retry-after'));\n const retryAfterMs =\n Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter, 5) * 1000 : undefined;\n return new SealedTransportError(response.status, code, message, retryAfterMs);\n}\n", "/**\n * The parts of the Sigstore public-good trust root that verifying a mero-tee\n * release's cosign bundle needs: the Fulcio certificate authorities that issue\n * the release workflow's short-lived signing certificates, and the Rekor log\n * key that signs the bundle's signed entry timestamp. Each with the window in\n * which the trust root says it was in use.\n *\n * Copied from the `trusted_root.json` that Sigstore publishes through its TUF\n * repository (https://tuf-repo-cdn.sigstore.dev, target `trusted_root.json`),\n * as shipped by the `sigstore` Python client 4.5.0 in\n * `sigstore/_store/https%3A%2F%2Ftuf-repo-cdn.sigstore.dev/trusted_root.json`.\n * Embedded rather than fetched: fetching it at run time would trust whoever\n * serves it, the very thing this check exists to avoid.\n *\n * Left out, because a legacy cosign bundle never uses them: the CT logs (the\n * certificate's SCT is not checked here, as core does not either), the\n * timestamp authority, and the Rekor v2 log `log2025-1.rekor.sigstore.dev`,\n * whose Ed25519 key signs checkpoints rather than signed entry timestamps. A\n * bundle that names any log but those below is refused.\n *\n * To refresh it when Sigstore rotates a key or adds a CA: take the current\n * `trusted_root.json` from a TUF client (`python -m sigstore` or `cosign\n * initialize` both keep one, verified against the TUF root), and copy each\n * `certificateAuthorities[].certChain.certificates[].rawBytes` with its\n * `validFor`, and each ECDSA `tlogs[]` entry's `publicKey.rawBytes`,\n * `publicKey.validFor` and `logId.keyId` (as hex). The tests check each log id\n * is the SHA-256 of its key and each chain verifies.\n */\n\n/** A Fulcio CA: its chain from the certificate that issues leaves up to the root, DER as base64. */\nexport interface FulcioAuthority {\n uri: string;\n /** When the trust root says this CA issued certificates. No `end`: it still does. */\n validFor: { start: string; end?: string };\n certChain: string[];\n}\n\n/** A Rekor log whose signed entry timestamps are accepted. */\nexport interface RekorLog {\n baseUrl: string;\n /** The log id a bundle names it by: the SHA-256 of its public key, hex. */\n logId: string;\n /** Its public key: DER SubjectPublicKeyInfo, base64. ECDSA P-256 with SHA-256. */\n publicKey: string;\n validFor: { start: string; end?: string };\n}\n\nexport const FULCIO_AUTHORITIES: readonly FulcioAuthority[] = [\n {\n uri: 'https://fulcio.sigstore.dev',\n validFor: { start: '2021-03-07T03:20:29Z', end: '2022-12-31T23:59:59.999Z' },\n certChain: [\n 'MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9y' +\n 'ZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIxMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UE' +\n 'ChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSyA7Ii5k+p' +\n 'NO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0JcastaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+' +\n '2Yfswe/QuLolRUCrcOE2+2iA5+tzd6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYD' +\n 'VR0OBBYEFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2uSu1KBtPsMAoGCCqG' +\n 'SM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJxVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjR' +\n 'ay5/aj/jsKKGIkmQatjI8uupHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ==',\n ],\n },\n {\n uri: 'https://fulcio.sigstore.dev',\n validFor: { start: '2022-04-13T20:06:15Z' },\n certChain: [\n 'MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3Rv' +\n 'cmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNV' +\n 'BAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EE' +\n 'ACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798' +\n 'LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAww' +\n 'CgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYD' +\n 'VR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfx' +\n 'Xx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsP' +\n 'mygUY7Ii2zbdCdliiow=',\n 'MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3Rv' +\n 'cmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNV' +\n 'BAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3' +\n 'PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS' +\n '5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud' +\n 'DgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjO' +\n 'PQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9' +\n 'ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ',\n ],\n },\n];\n\nexport const REKOR_LOGS: readonly RekorLog[] = [\n {\n baseUrl: 'https://rekor.sigstore.dev',\n logId: 'c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d',\n publicKey:\n 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwrkBbmLSGtks4L3qX6yYY0zufB' +\n 'nhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==',\n validFor: { start: '2021-01-12T11:53:27Z' },\n },\n];\n", "/**\n * Just enough DER and X.509 to check a Sigstore signing certificate with\n * WebCrypto: read a certificate's signed part, validity, key and extensions,\n * and verify the ECDSA signatures (P-256 and P-384) Sigstore uses.\n *\n * Written here, rather than taken from a library, so the SDK keeps no runtime\n * dependencies and runs wherever WebCrypto does. It parses strictly and throws\n * on anything it does not expect; it is not a general X.509 implementation.\n */\n\nconst SEQUENCE = 0x30;\nconst OID = 0x06;\nconst INTEGER = 0x02;\nconst BIT_STRING = 0x03;\nconst OCTET_STRING = 0x04;\nconst BOOLEAN = 0x01;\nconst UTC_TIME = 0x17;\nconst GENERALIZED_TIME = 0x18;\nconst CONTEXT_0 = 0xa0;\nconst CONTEXT_3 = 0xa3;\n\nconst EC_PUBLIC_KEY = '1.2.840.10045.2.1';\nconst CURVES: Record<string, Curve> = {\n '1.2.840.10045.3.1.7': 'P-256',\n '1.3.132.0.34': 'P-384',\n};\nconst CURVE_SIZE: Record<Curve, number> = { 'P-256': 32, 'P-384': 48 };\n/** The certificate signature algorithms accepted: ECDSA with SHA-256 or SHA-384. */\nconst SIGNATURE_HASHES: Record<string, Hash> = {\n '1.2.840.10045.4.3.2': 'SHA-256',\n '1.2.840.10045.4.3.3': 'SHA-384',\n};\n\nexport type Curve = 'P-256' | 'P-384';\nexport type Hash = 'SHA-256' | 'SHA-384';\n\n/** One DER element: its tag, and where it and its contents lie in `bytes`. */\nexport interface Element {\n tag: number;\n bytes: Uint8Array;\n /** Offset of the element's first (tag) byte. */\n offset: number;\n /** Offset of its contents. */\n start: number;\n /** Offset just past it. */\n end: number;\n}\n\nfunction read(bytes: Uint8Array, offset: number, limit: number): Element {\n if (offset + 2 > limit) throw new Error('it is truncated');\n const tag = bytes[offset];\n if ((tag & 0x1f) === 0x1f) throw new Error('it uses a tag this parser does not read');\n let length = bytes[offset + 1];\n let start = offset + 2;\n if (length & 0x80) {\n const count = length & 0x7f;\n if (count === 0 || count > 4 || start + count > limit) throw new Error('it has a length this parser does not read');\n length = 0;\n for (let i = 0; i < count; i += 1) length = length * 256 + bytes[start + i];\n start += count;\n }\n const end = start + length;\n if (end > limit) throw new Error('it is truncated');\n return { tag, bytes, offset, start, end };\n}\n\n/** Parse one complete DER element, refusing trailing bytes. */\nexport function parseDer(bytes: Uint8Array): Element {\n const element = read(bytes, 0, bytes.length);\n if (element.end !== bytes.length) throw new Error('it has trailing bytes');\n return element;\n}\n\nexport function children(element: Element): Element[] {\n const out: Element[] = [];\n for (let offset = element.start; offset < element.end; ) {\n const child = read(element.bytes, offset, element.end);\n out.push(child);\n offset = child.end;\n }\n return out;\n}\n\n/** `element` if it has `tag`; otherwise throws naming `what`. */\nexport function expectTag(element: Element | undefined, tag: number, what: string): Element {\n if (!element || element.tag !== tag) throw new Error(`${what} is not where it should be`);\n return element;\n}\n\nexport function contents(element: Element): Uint8Array {\n return element.bytes.slice(element.start, element.end);\n}\n\n/** The whole element, header included. */\nfunction whole(element: Element): Uint8Array {\n return element.bytes.slice(element.offset, element.end);\n}\n\nfunction oid(element: Element | undefined): string {\n const value = contents(expectTag(element, OID, 'An object identifier'));\n if (value.length === 0 || value[value.length - 1] & 0x80) throw new Error('it has a malformed object identifier');\n const arcs: number[] = [];\n let arc = 0;\n for (const byte of value) {\n arc = arc * 128 + (byte & 0x7f);\n if (!(byte & 0x80)) {\n arcs.push(arc);\n arc = 0;\n }\n }\n const first = arcs.shift() as number;\n const head = first < 80 ? [Math.floor(first / 40), first % 40] : [2, first - 80];\n return [...head, ...arcs].join('.');\n}\n\nfunction time(element: Element): number {\n const text = new TextDecoder().decode(contents(element));\n const utc = element.tag === UTC_TIME ? /^(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})Z$/.exec(text) : null;\n const generalized =\n element.tag === GENERALIZED_TIME ? /^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})Z$/.exec(text) : null;\n const parts = utc ?? generalized;\n if (!parts) throw new Error(`it holds the time ${JSON.stringify(text)}, which is not one a certificate may hold`);\n let year = Number(parts[1]);\n if (utc) year += year < 50 ? 2000 : 1900;\n const [month, day, hour, minute, second] = parts.slice(2).map(Number);\n return Date.UTC(year, month - 1, day, hour, minute, second);\n}\n\nexport interface Certificate {\n der: Uint8Array;\n /** The signed part, exactly as the issuer signed it. */\n tbs: Uint8Array;\n /** The hash of the ECDSA signature the issuer made over `tbs`. */\n signatureHash: Hash;\n /** That signature, DER. */\n signature: Uint8Array;\n /** The issuer and subject names, DER, to compare byte for byte. */\n issuer: Uint8Array;\n subject: Uint8Array;\n /** Validity, in milliseconds since the epoch, both ends inclusive. */\n notBefore: number;\n notAfter: number;\n /** The subject's key, DER SubjectPublicKeyInfo, and its curve. */\n spki: Uint8Array;\n curve: Curve;\n /** Each extension's value (the contents of its OCTET STRING), by object identifier. */\n extensions: Map<string, Uint8Array>;\n}\n\n/**\n * Parse a DER X.509 certificate with an ECDSA key, signed with ECDSA. Throws\n * naming what is wrong.\n */\nexport function parseCertificate(der: Uint8Array): Certificate {\n try {\n const [tbsElement, algorithm, signature, ...rest] = children(\n expectTag(parseDer(der), SEQUENCE, 'The certificate'),\n );\n if (rest.length > 0) throw new Error('it has fields after its signature');\n const fields = children(expectTag(tbsElement, SEQUENCE, 'The signed part'));\n // `version` is [0] EXPLICIT; everything after it is positional.\n const first = fields[0]?.tag === CONTEXT_0 ? 1 : 0;\n const [serial, innerAlgorithm, issuer, validity, subject, spki, ...optional] = fields.slice(first);\n expectTag(serial, INTEGER, 'The serial number');\n\n const algorithmId = oid(children(expectTag(algorithm, SEQUENCE, 'The signature algorithm'))[0]);\n const innerId = oid(children(expectTag(innerAlgorithm, SEQUENCE, 'The signature algorithm'))[0]);\n if (innerId !== algorithmId) throw new Error('it names two different signature algorithms');\n const signatureHash = SIGNATURE_HASHES[algorithmId];\n if (!signatureHash) throw new Error(`it is signed with ${algorithmId}, not ECDSA with SHA-256 or SHA-384`);\n\n const [notBefore, notAfter] = children(expectTag(validity, SEQUENCE, 'The validity')).map(time);\n if (notAfter === undefined) throw new Error('its validity is incomplete');\n\n const [keyAlgorithm, keyBits] = children(expectTag(spki, SEQUENCE, 'The public key'));\n expectTag(keyBits, BIT_STRING, 'The public key');\n const [keyType, keyCurve] = children(expectTag(keyAlgorithm, SEQUENCE, 'The key algorithm'));\n if (oid(keyType) !== EC_PUBLIC_KEY) throw new Error('its key is not an elliptic-curve key');\n const curve = CURVES[oid(keyCurve)];\n if (!curve) throw new Error('its key is on a curve other than P-256 or P-384');\n\n const extensions = new Map<string, Uint8Array>();\n const extensionsField = optional.find((field) => field.tag === CONTEXT_3);\n if (extensionsField) {\n const [list] = children(extensionsField);\n for (const extension of children(expectTag(list, SEQUENCE, 'The extensions'))) {\n const parts = children(expectTag(extension, SEQUENCE, 'An extension'));\n if (parts.length === 3) expectTag(parts[1], BOOLEAN, 'An extension\\'s critical flag');\n else if (parts.length !== 2) throw new Error('it has a malformed extension');\n const id = oid(parts[0]);\n if (extensions.has(id)) throw new Error(`it has extension ${id} twice`);\n extensions.set(id, contents(expectTag(parts[parts.length - 1], OCTET_STRING, 'An extension value')));\n }\n }\n\n const signatureBits = contents(expectTag(signature, BIT_STRING, 'The signature'));\n if (signatureBits[0] !== 0) throw new Error('its signature is not a whole number of bytes');\n return {\n der,\n tbs: whole(tbsElement),\n signatureHash,\n signature: signatureBits.slice(1),\n issuer: whole(expectTag(issuer, SEQUENCE, 'The issuer')),\n subject: whole(expectTag(subject, SEQUENCE, 'The subject')),\n notBefore,\n notAfter,\n spki: whole(spki),\n curve,\n extensions,\n };\n } catch (error) {\n throw new Error(`The certificate is malformed: ${(error as Error).message}`);\n }\n}\n\n/** The object identifiers in a DER `SEQUENCE OF OBJECT IDENTIFIER` (an extended key usage). */\nexport function objectIdentifiers(der: Uint8Array): string[] {\n return children(expectTag(parseDer(der), SEQUENCE, 'The list')).map(oid);\n}\n\n/**\n * An ECDSA signature as WebCrypto takes it (IEEE P1363: `r || s`, each the\n * curve's size), from the DER `SEQUENCE { r INTEGER, s INTEGER }` X.509 and\n * cosign use.\n */\nexport function ecdsaSignatureToP1363(der: Uint8Array, curve: Curve): Uint8Array {\n const size = CURVE_SIZE[curve];\n const integers = children(expectTag(parseDer(der), SEQUENCE, 'The signature'));\n if (integers.length !== 2) throw new Error('The signature is not an ECDSA signature');\n const out = new Uint8Array(size * 2);\n integers.forEach((integer, index) => {\n let value = contents(expectTag(integer, INTEGER, 'The signature'));\n // r and s are positive: a set top bit with no leading zero is a negative number.\n if (value.length === 0 || value[0] & 0x80) throw new Error('The signature is not an ECDSA signature');\n while (value.length > 1 && value[0] === 0) value = value.subarray(1);\n if (value.length > size) throw new Error('The signature is not an ECDSA signature');\n out.set(value, index * size + size - value.length);\n });\n return out;\n}\n\n/** Verify a DER ECDSA `signature` over `data` with a DER SubjectPublicKeyInfo key. */\nexport async function verifyEcdsa(\n spki: Uint8Array,\n curve: Curve,\n hash: Hash,\n signature: Uint8Array,\n data: Uint8Array,\n): Promise<boolean> {\n let p1363: Uint8Array;\n try {\n p1363 = ecdsaSignatureToP1363(signature, curve);\n } catch {\n return false;\n }\n const key = await crypto.subtle.importKey('spki', spki, { name: 'ECDSA', namedCurve: curve }, false, ['verify']);\n return crypto.subtle.verify({ name: 'ECDSA', hash }, key, p1363, data);\n}\n\n/** Decode base64 (standard alphabet), refusing anything else. */\nexport function fromBase64(value: string, what: string): Uint8Array {\n const clean = value.replace(/\\s+/g, '');\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(clean) || clean.length % 4 !== 0) {\n throw new Error(`${what} is not base64`);\n }\n const binary = atob(clean);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\n/** The DER of the one `CERTIFICATE` block a PEM holds. */\nexport function pemCertificate(pem: string, what: string): Uint8Array {\n const blocks = [...pem.matchAll(/-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g)];\n if (blocks.length !== 1 || pem.replace(blocks[0][0], '').trim() !== '') {\n throw new Error(`${what} is not exactly one PEM certificate`);\n }\n return fromBase64(blocks[0][1], what);\n}\n", "/**\n * Verifying a cosign keyless signature, as `cosign verify-blob --bundle` does,\n * with WebCrypto and the Sigstore trust root embedded in this package.\n *\n * mero-tee signs each release asset with cosign keyless: there is no release\n * key, only a Fulcio certificate that lives ten minutes, issued to one GitHub\n * Actions workflow run, and a Rekor log entry that proves the signature was\n * made while the certificate was valid. So the checks are: the signature over\n * the bytes verifies with the certificate's key; Rekor's signed entry\n * timestamp verifies, and the entry it signs is this signature over these\n * bytes by this certificate; the certificate chains to a Fulcio CA and was\n * valid when Rekor logged it; and the certificate names the workflow expected.\n * The same checks core runs in `crates/tee-release/src/sigstore_verify.rs`.\n *\n * Nothing here reads the clock. Every time is Rekor's `integratedTime`, which\n * its signature covers, so a verification that passes once passes forever,\n * whatever the client's clock says.\n */\n\nimport { hex } from '../crypto/internal.js';\nimport { FULCIO_AUTHORITIES, REKOR_LOGS } from './sigstore-trust-root.js';\nimport {\n children,\n contents,\n expectTag,\n fromBase64,\n objectIdentifiers,\n parseCertificate,\n parseDer,\n pemCertificate,\n verifyEcdsa,\n type Certificate,\n} from './x509.js';\n\nconst SUBJECT_ALT_NAME = '2.5.29.17';\nconst EXTENDED_KEY_USAGE = '2.5.29.37';\nconst CODE_SIGNING = '1.3.6.1.5.5.7.3.3';\n/** Fulcio's OIDC issuer extension, a DER UTF8String. */\nconst FULCIO_ISSUER_V2 = '1.3.6.1.4.1.57264.1.8';\n/** Its deprecated predecessor, the raw issuer bytes; read only when the other is absent. */\nconst FULCIO_ISSUER_V1 = '1.3.6.1.4.1.57264.1.1';\nconst SAN_URI = 0x86;\nconst UTF8_STRING = 0x0c;\nconst SEQUENCE = 0x30;\n\nconst utf8 = new TextEncoder();\n// Not `fatal`: not every runtime's TextDecoder takes options. A malformed byte\n// decodes to U+FFFD, which no pinned identity holds, so it can only fail a match.\nconst fromUtf8 = (bytes: Uint8Array) => new TextDecoder().decode(bytes);\n\n/** Who must have signed: the certificate's SAN URI and its OIDC issuer, each matched exactly. */\nexport interface SignerIdentity {\n identity: string;\n issuer: string;\n}\n\n/** A legacy cosign bundle (`cosign sign-blob --bundle`), as the fields verified here. */\ninterface CosignBundle {\n base64Signature: string;\n cert: string;\n rekorBundle: {\n SignedEntryTimestamp: string;\n Payload: { body: string; integratedTime: number; logIndex: number; logID: string };\n };\n}\n\n/**\n * Verify a cosign keyless `bundle` over `body`, signed by `signer`. Resolves\n * with the time Rekor logged it (seconds); rejects with the reason otherwise.\n * `signature`, when given, is the detached `.sig` published beside the file,\n * and must be the bundle's.\n */\nexport async function verifyCosignBundle(\n body: Uint8Array,\n bundle: unknown,\n signer: SignerIdentity,\n signature?: string,\n): Promise<{ integratedTime: number }> {\n const { base64Signature, cert, rekorBundle } = cosignBundle(bundle);\n const payload = rekorBundle.Payload;\n if (signature !== undefined && signature.trim() !== base64Signature.trim()) {\n throw new Error('The detached signature is not the one in the bundle');\n }\n const sig = fromBase64(base64Signature, 'The bundle signature');\n const leafDer = pemCertificate(fromUtf8(fromBase64(cert, 'The bundle certificate')), 'The bundle certificate');\n const leaf = parseCertificate(leafDer);\n\n // Rekor vouches for the entry and its time: nothing below is trusted before this.\n const log = REKOR_LOGS.find((candidate) => candidate.logId === payload.logID.toLowerCase());\n if (!log) throw new Error(`The bundle names Rekor log ${payload.logID}, which the Sigstore trust root does not know`);\n const canonical = utf8.encode(\n `{\"body\":${JSON.stringify(payload.body)},\"integratedTime\":${payload.integratedTime},` +\n `\"logID\":${JSON.stringify(payload.logID)},\"logIndex\":${payload.logIndex}}`,\n );\n const setVerifies = await verifyEcdsa(\n fromBase64(log.publicKey, 'The Rekor key'),\n 'P-256',\n 'SHA-256',\n fromBase64(rekorBundle.SignedEntryTimestamp, 'The signed entry timestamp'),\n canonical,\n );\n if (!setVerifies) {\n throw new Error(\"Rekor's signed entry timestamp does not verify: the log entry, its time or its index was altered\");\n }\n const at = payload.integratedTime * 1000;\n if (!within(at, log.validFor)) {\n throw new Error(`Rekor log ${log.baseUrl} was not in use at ${iso(at)}, when the entry says it was logged`);\n }\n\n // The entry Rekor signed is this signature, over these bytes, by this certificate.\n const entry = hashedRekord(payload.body);\n const digest = hex(new Uint8Array(await crypto.subtle.digest('SHA-256', body)));\n if (entry.hash !== digest) throw new Error(\"The file's SHA-256 is not the one Rekor logged: the file is not the one signed\");\n if (!equal(fromBase64(entry.signature, 'The logged signature'), sig)) {\n throw new Error(\"The bundle's signature is not the one Rekor logged\");\n }\n const loggedCert = pemCertificate(fromUtf8(fromBase64(entry.publicKey, 'The logged certificate')), 'The logged certificate');\n if (!equal(loggedCert, leafDer)) throw new Error(\"The bundle's certificate is not the one Rekor logged\");\n\n if (leaf.curve !== 'P-256' || !(await verifyEcdsa(leaf.spki, 'P-256', 'SHA-256', sig, body))) {\n throw new Error(\"The signature over the file does not verify with the bundle's certificate\");\n }\n\n await chainsToFulcio(leaf, at);\n checkSigner(leaf, signer);\n return { integratedTime: payload.integratedTime };\n}\n\n/**\n * Check that `leaf` was issued by a Fulcio CA in the trust root, and that it,\n * the CA's certificates and the CA itself (by the trust root's `validFor`)\n * were all valid at `at` (milliseconds): when Rekor logged the signature, not\n * now, since a Fulcio certificate lives ten minutes. Every signature on the\n * way is checked, with the algorithm its certificate names.\n */\nexport async function chainsToFulcio(leaf: Certificate, at: number): Promise<void> {\n if (!validAt(leaf, at)) {\n throw new Error(\n `The signing certificate was valid ${iso(leaf.notBefore)} to ${iso(leaf.notAfter)}, not at ${iso(at)} when Rekor logged it`,\n );\n }\n const reasons: string[] = [];\n for (const authority of FULCIO_AUTHORITIES) {\n const chain = authority.certChain.map((der) => parseCertificate(fromBase64(der, 'A Fulcio certificate')));\n if (!(await issuedBy(leaf, chain[0]))) continue;\n // The issuer is found; from here a failure is this CA's, so say which.\n const reason = await authorityRefusal(chain, authority.validFor, at);\n if (!reason) return;\n reasons.push(`${authority.uri} (valid from ${authority.validFor.start}): ${reason}`);\n }\n throw new Error(\n reasons.length > 0\n ? `The signing certificate's CA is not trusted at ${iso(at)}: ${reasons.join('; ')}`\n : 'The signing certificate was not issued by a Fulcio CA in the Sigstore trust root',\n );\n}\n\nasync function authorityRefusal(\n chain: Certificate[],\n validFor: { start: string; end?: string },\n at: number,\n): Promise<string | undefined> {\n if (!within(at, validFor)) return 'the trust root says it was not issuing certificates then';\n for (const [index, certificate] of chain.entries()) {\n if (!validAt(certificate, at)) return `its certificate ${index} was not valid then`;\n const parent = chain[index + 1] ?? certificate; // the root signs itself\n if (!(await issuedBy(certificate, parent))) return `its certificate ${index} is not signed by the next`;\n }\n return undefined;\n}\n\nasync function issuedBy(child: Certificate, parent: Certificate): Promise<boolean> {\n if (!equal(child.issuer, parent.subject)) return false;\n return verifyEcdsa(parent.spki, parent.curve, child.signatureHash, child.signature, child.tbs);\n}\n\nfunction checkSigner(leaf: Certificate, signer: SignerIdentity): void {\n const san = leaf.extensions.get(SUBJECT_ALT_NAME);\n if (!san) throw new Error('The signing certificate names no identity');\n const names = children(expectTag(parseDer(san), SEQUENCE, 'The subject alternative name'));\n const uris = names.filter((name) => name.tag === SAN_URI).map((name) => fromUtf8(contents(name)));\n if (uris.length !== 1 || names.length !== 1 || uris[0] !== signer.identity) {\n throw new Error(\n `The release was signed by ${JSON.stringify(uris.length === 1 ? uris[0] : uris)}, not by ${signer.identity}`,\n );\n }\n\n const v2 = leaf.extensions.get(FULCIO_ISSUER_V2);\n const v1 = leaf.extensions.get(FULCIO_ISSUER_V1);\n const issuer = v2\n ? fromUtf8(contents(expectTag(parseDer(v2), UTF8_STRING, 'The OIDC issuer')))\n : v1\n ? fromUtf8(v1)\n : undefined;\n if (issuer !== signer.issuer) {\n throw new Error(\n `The signing certificate's OIDC issuer is ${issuer === undefined ? 'missing' : JSON.stringify(issuer)}, not ${signer.issuer}`,\n );\n }\n\n const usage = leaf.extensions.get(EXTENDED_KEY_USAGE);\n if (!usage || !objectIdentifiers(usage).includes(CODE_SIGNING)) {\n throw new Error('The signing certificate is not for code signing');\n }\n}\n\nfunction cosignBundle(value: unknown): CosignBundle {\n let bundle = value;\n if (typeof bundle === 'string') {\n try {\n bundle = JSON.parse(bundle);\n } catch {\n throw new Error('The bundle is not JSON');\n }\n }\n const b = bundle as Partial<CosignBundle> | null;\n const p = b?.rekorBundle?.Payload;\n const ok =\n typeof b?.base64Signature === 'string' &&\n typeof b.cert === 'string' &&\n typeof b.rekorBundle?.SignedEntryTimestamp === 'string' &&\n typeof p?.body === 'string' &&\n typeof p.logID === 'string' &&\n /^[0-9a-fA-F]{64}$/.test(p.logID) &&\n Number.isSafeInteger(p.integratedTime) &&\n p.integratedTime >= 0 &&\n Number.isSafeInteger(p.logIndex) &&\n p.logIndex >= 0;\n if (!ok) throw new Error('The bundle is not a cosign bundle with a Rekor entry');\n return b as CosignBundle;\n}\n\n/** The fields of a logged `hashedrekord` entry that are compared. */\nfunction hashedRekord(body: string): { hash: string; signature: string; publicKey: string } {\n let entry: {\n kind?: unknown;\n spec?: {\n data?: { hash?: { algorithm?: unknown; value?: unknown } };\n signature?: { content?: unknown; publicKey?: { content?: unknown } };\n };\n };\n try {\n entry = JSON.parse(fromUtf8(fromBase64(body, 'The logged entry')));\n } catch {\n throw new Error('The logged entry is not JSON');\n }\n const hash = entry?.spec?.data?.hash;\n const signature = entry?.spec?.signature;\n if (\n entry?.kind !== 'hashedrekord' ||\n hash?.algorithm !== 'sha256' ||\n typeof hash.value !== 'string' ||\n typeof signature?.content !== 'string' ||\n typeof signature.publicKey?.content !== 'string'\n ) {\n throw new Error('The logged entry is not a SHA-256 hashedrekord');\n }\n return { hash: hash.value.toLowerCase(), signature: signature.content, publicKey: signature.publicKey.content };\n}\n\nfunction validAt(certificate: Certificate, at: number): boolean {\n return certificate.notBefore <= at && at <= certificate.notAfter;\n}\n\nfunction within(at: number, window: { start: string; end?: string }): boolean {\n return Date.parse(window.start) <= at && (window.end === undefined || at <= Date.parse(window.end));\n}\n\nfunction iso(ms: number): string {\n return new Date(ms).toISOString();\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n return a.length === b.length && a.every((byte, index) => byte === b[index]);\n}\n", "/**\n * Verifying a TEE node's quote in the page, before trusting the key it binds.\n *\n * A quote proves what runs in a TD only once it has been checked: its\n * signatures against Intel's root, the TCB status of the platform, the\n * measurements of the image, and that its report data is the nonce and the\n * binding this client asked for. {@link createQuoteVerifier} does all of that\n * here. A Calimero 1.0 node sends no collateral: the verifier fetches Intel's\n * (`fetchCollateral`), which the node can neither forge nor choose.\n *\n * The DCAP verification itself \u2014 parsing the quote, checking its signature\n * chain and appraising its TCB level against the collateral \u2014 comes from a\n * library you pass in, normally `verify` from `@phala/dcap-qvl`, a pure\n * JavaScript implementation that runs in browsers, Node and React Native. It\n * is passed in rather than bundled so this SDK keeps no runtime dependencies,\n * and applications that never talk to a TEE node pay nothing for it.\n */\n\nimport { hex } from '../crypto/internal.js';\nimport type { VerifyTransportQuote } from './sealed.js';\n\n/**\n * The collateral a quote is verified against \u2014 TCB info, QE identity, CRLs and\n * their chains \u2014 in dcap-qvl's form: byte fields are hex strings or byte\n * arrays. What `@phala/dcap-qvl`'s `getCollateral` fetches.\n */\nexport interface DcapCollateral {\n pck_crl_issuer_chain: string;\n root_ca_crl: number[] | string;\n pck_crl: number[] | string;\n tcb_info_issuer_chain: string;\n tcb_info: string;\n tcb_info_signature: number[] | string;\n qe_identity_issuer_chain: string;\n qe_identity: string;\n qe_identity_signature: number[] | string;\n}\n\n/** The fields of a TDX report this verifier reads. */\ninterface TdReport {\n mrTd: Uint8Array;\n rtMr0: Uint8Array;\n rtMr1: Uint8Array;\n rtMr2: Uint8Array;\n rtMr3: Uint8Array;\n reportData: Uint8Array;\n tdAttributes?: Uint8Array;\n}\n\n/** What a DCAP verifier returns for a quote whose signature chain verified. */\nexport interface DcapVerifiedReport {\n status: string;\n advisory_ids?: string[];\n report: { type: string; data: unknown };\n}\n\n/**\n * Verify a quote's signature chain against `collateral` as of `nowSecs`, and\n * appraise its TCB level. Throws when it does not verify. `verify` from\n * `@phala/dcap-qvl` has exactly this shape.\n */\nexport type DcapVerify = (\n quote: Uint8Array,\n collateral: DcapCollateral,\n nowSecs: number,\n) => DcapVerifiedReport;\n\n/**\n * One image's measurements, all five registers, hex. A quote matches it only\n * when every register does, so measurements of different images never combine.\n */\nexport interface TrustedMeasurements {\n mrtd: string;\n rtmr0: string;\n rtmr1: string;\n rtmr2: string;\n rtmr3: string;\n}\n\nexport interface QuoteVerifierOptions {\n /** DCAP verification: `verify` from `@phala/dcap-qvl`. */\n dcapVerify: DcapVerify;\n /**\n * The images trusted, each by all of its measurements. The way to say which\n * code may read the traffic: build it with {@link trustedMeasurementsFromReleases}\n * from the `published-mrtds.json` of the releases you trust.\n */\n allowedMeasurements?: TrustedMeasurements[];\n /**\n * MRTDs (hex) accepted. On its own this does not name an image: on GCP the\n * MRTD measures the platform's TD firmware, which every image shares, and\n * the image is in RTMR1\u20133. So a verifier needs either\n * {@link allowedMeasurements}, or this with all of `allowedRtmr1`\u2013`3`.\n */\n allowedMrtd?: string[];\n /** RTMR allowlists (hex); a register is not checked when its list is left out. */\n allowedRtmr0?: string[];\n allowedRtmr1?: string[];\n allowedRtmr2?: string[];\n allowedRtmr3?: string[];\n /**\n * TCB statuses accepted. Defaults to `['UpToDate']`. `Revoked` is refused\n * even when listed.\n */\n allowedTcbStatuses?: string[];\n /**\n * Where to get collateral (a Calimero 1.0 node sends none): for example\n * `(quote) => getCollateral(PHALA_PCCS_URL, quote)` from `@phala/dcap-qvl`.\n * Without it, a quote that came without collateral is refused.\n */\n fetchCollateral?: (quote: Uint8Array) => Promise<DcapCollateral>;\n /** The current time in milliseconds; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\n/** A quote verifier as this package builds one ({@link createQuoteVerifier}). */\nexport type QuoteVerifier = VerifyTransportQuote & { readonly includeCollateral: true };\n\nconst MEASUREMENT_HEX = /^[0-9a-f]{96}$/;\nconst REGISTERS = ['mrtd', 'rtmr0', 'rtmr1', 'rtmr2', 'rtmr3'] as const;\n\n/**\n * A verifier that checks a TEE node's quote here, in the page, and accepts it\n * only when every check passes:\n *\n * - its signatures verify against Intel's root, with collateral that is valid\n * now;\n * - the platform's TCB status is one allowed (`UpToDate` by default), and\n * never `Revoked`;\n * - its measurements are those of a trusted image: one of\n * `allowedMeasurements` in full, and the MRTD and any RTMRs listed;\n * - its report data is the nonce followed by the binding the client computed.\n *\n * Any failure rejects with the reason; nothing is trusted from a quote that\n * does not pass. Mock quotes never pass: they carry no signature.\n *\n * ```ts\n * import { verify as dcapVerify } from '@phala/dcap-qvl';\n *\n * const verifier = createQuoteVerifier({\n * dcapVerify,\n * ...trustedMeasurementsFromReleases([publishedMrtds], { profile: 'locked-read-only' }),\n * });\n * const client = new CalimeroClient({ baseUrl, policy: { verifyQuote: verifier } });\n * ```\n */\nexport function createQuoteVerifier(options: QuoteVerifierOptions): QuoteVerifier {\n const allowedMrtd = measurements(options.allowedMrtd ?? [], 'allowedMrtd');\n const allowedImages = (options.allowedMeasurements ?? []).map((image, index) => {\n const label = `allowedMeasurements[${index}]`;\n return REGISTERS.map((register) => measurements([image?.[register] ?? ''], `${label}.${register}`)[0]).join();\n });\n const allowedRtmr = [\n measurements(options.allowedRtmr0 ?? [], 'allowedRtmr0'),\n measurements(options.allowedRtmr1 ?? [], 'allowedRtmr1'),\n measurements(options.allowedRtmr2 ?? [], 'allowedRtmr2'),\n measurements(options.allowedRtmr3 ?? [], 'allowedRtmr3'),\n ];\n if (options.allowedMeasurements !== undefined && allowedImages.length === 0) {\n throw new Error('allowedMeasurements is empty, so no quote would ever be accepted');\n }\n if (allowedImages.length === 0) {\n if (allowedMrtd.length === 0) {\n throw new Error('No image is trusted: give allowedMeasurements, or allowedMrtd with allowedRtmr1-3');\n }\n if (allowedRtmr.slice(1).some((list) => list.length === 0)) {\n throw new Error(\n 'allowedMrtd alone does not name an image: the MRTD measures the TD firmware, which ' +\n 'images share, and the image is in RTMR1-3. Give allowedMeasurements, or allowedRtmr1-3 too',\n );\n }\n }\n const allowedStatuses = options.allowedTcbStatuses ?? ['UpToDate'];\n const now = options.now ?? Date.now;\n\n const verifier = async ({\n quoteB64,\n nonce,\n reportDataSuffix,\n collateral,\n }: Parameters<VerifyTransportQuote>[0]): Promise<boolean> => {\n const quote = fromBase64(quoteB64);\n const against = collateral ?? (await options.fetchCollateral?.(quote));\n if (!against) {\n throw new Error(\n 'The node sent no collateral for its quote, and no fetchCollateral was given to get it',\n );\n }\n\n let verified: DcapVerifiedReport;\n try {\n verified = options.dcapVerify(quote, against, Math.floor(now() / 1000));\n } catch (error) {\n throw new Error(`The quote did not verify: ${(error as Error)?.message ?? String(error)}`);\n }\n\n if (verified.status === 'Revoked' || !allowedStatuses.includes(verified.status)) {\n throw new Error(`The platform's TCB status is ${verified.status}, which is not accepted`);\n }\n const td = tdReport(verified.report);\n // TUD bit 0. A debug TD's memory and registers are open to the host, so its\n // measurements prove nothing about what runs in it. Checked here, not left\n // to `dcapVerify`, which a caller may swap for one that allows debug; an\n // attribute field that cannot be read counts as debug.\n if (td.tdAttributes?.length !== 8 || (td.tdAttributes[0] & 0x01) !== 0) {\n throw new Error('The quote is from a debug TD, or its TD attributes cannot be read');\n }\n const measured = [td.mrTd, td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3].map((register) => hex(register));\n if (allowedImages.length > 0 && !allowedImages.includes(measured.join())) {\n throw new Error(\n `The measurements (MRTD ${measured[0]}, RTMR0-3 ${measured.slice(1).join(', ')}) are not an image this verifier trusts`,\n );\n }\n if (allowedMrtd.length > 0 && !allowedMrtd.includes(measured[0])) {\n throw new Error(`MRTD ${measured[0]} is not an image this verifier trusts`);\n }\n const registers = [td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3];\n registers.forEach((register, index) => {\n const allowed = allowedRtmr[index];\n if (allowed.length > 0 && !allowed.includes(hex(register))) {\n throw new Error(`RTMR${index} ${hex(register)} is not one this verifier trusts`);\n }\n });\n if (hex(td.reportData) !== `${nonce}${reportDataSuffix}`.toLowerCase()) {\n throw new Error('The quote does not commit to this nonce and binding');\n }\n return true;\n };\n return Object.assign(verifier, { includeCollateral: true as const });\n}\n\nfunction measurements(values: string[], label: string): string[] {\n return values.map((value) => {\n const normalized = value.trim().toLowerCase();\n if (!MEASUREMENT_HEX.test(normalized)) {\n throw new Error(`${label} holds ${JSON.stringify(value)}, which is not a 48-byte hex measurement`);\n }\n return normalized;\n });\n}\n\n/** The TD report of a TDX quote (1.0 or 1.5); anything else is refused. */\nfunction tdReport(report: DcapVerifiedReport['report']): TdReport {\n const data = report.data as (TdReport & { base?: TdReport }) | undefined;\n if (report.type === 'td10' && data) return data;\n if (report.type === 'td15' && data?.base) return data.base;\n throw new Error(`The quote is a ${report.type} quote, not a TDX one`);\n}\n\nfunction fromBase64(value: string): Uint8Array {\n const binary = atob(value);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\n/**\n * A mero-tee node release's `published-mrtds.json`: the measurements the\n * release workflow observed booting each profile of its image on TDX, signed\n * with the release. Only the fields read here are typed.\n */\nexport interface PublishedMrtds {\n role?: string;\n tag?: string;\n profiles: Record<\n string,\n {\n mrtd: string;\n rtmr0: string;\n rtmr1: string;\n rtmr2: string;\n rtmr3: string;\n allowed_tcb_statuses?: string[];\n }\n >;\n}\n\n/** TCB statuses as DCAP reports them; the release lists them in lower case. */\nconst TCB_STATUSES = [\n 'UpToDate',\n 'SWHardeningNeeded',\n 'ConfigurationNeeded',\n 'ConfigurationAndSWHardeningNeeded',\n 'OutOfDate',\n 'OutOfDateConfigurationNeeded',\n];\n\n/**\n * The {@link QuoteVerifierOptions} that trust exactly one profile of the given\n * releases: each release's image by all of its measurements, and only the TCB\n * statuses every one of those releases accepts.\n *\n * Pass every release a node you talk to may run. During a rollout that is the\n * old one and the new one; drop the old one once no node runs it.\n *\n * ```ts\n * import published from './trusted/mero-tee-v2.3.78.published-mrtds.json';\n *\n * const verifier = createQuoteVerifier({\n * dcapVerify,\n * ...trustedMeasurementsFromReleases([published], { profile: 'locked-read-only' }),\n * });\n * ```\n *\n * Where the file comes from is the trust decision. Shipping it with the app\n * (checked out of a release you verified) trusts that release; fetching it at\n * run time trusts whoever serves it.\n */\n/**\n * The one image profile a release publishes for production. The `debug` and\n * `debug-read-only` images are signed and published beside it, but run with\n * SSH and the operator's tooling inside the TD, so trusting one trusts an\n * image the operator can read.\n */\nexport const PRODUCTION_PROFILE = 'locked-read-only';\n\nexport interface TrustedProfileOptions {\n /** The image profile to trust, e.g. `locked-read-only`. */\n profile: string;\n /**\n * Trust a profile other than {@link PRODUCTION_PROFILE}, such as `debug`.\n * Its image is readable by whoever operates the node, so only for testing.\n */\n allowDebugProfile?: boolean;\n}\n\nexport function trustedMeasurementsFromReleases(\n releases: PublishedMrtds[],\n { profile, allowDebugProfile = false }: TrustedProfileOptions,\n): Required<Pick<QuoteVerifierOptions, 'allowedMeasurements' | 'allowedTcbStatuses'>> {\n if (releases.length === 0) {\n throw new Error('No release given, so no image would be trusted');\n }\n let statuses: string[] | undefined;\n const allowedMeasurements = releases.map((release, index) => {\n const name = release?.tag ?? `releases[${index}]`;\n if (release?.role !== undefined && release.role !== 'node') {\n throw new Error(`${name} lists the measurements of a ${release.role}, not of a node image`);\n }\n const image = release?.profiles?.[profile];\n if (!image) {\n const known = Object.keys(release?.profiles ?? {}).join(', ') || 'none';\n throw new Error(`${name} has no profile ${JSON.stringify(profile)} (it has: ${known})`);\n }\n if (profile !== PRODUCTION_PROFILE && !allowDebugProfile) {\n throw new Error(\n `${JSON.stringify(profile)} is not a production profile: its image is readable by whoever ` +\n `operates the node. Trust ${JSON.stringify(PRODUCTION_PROFILE)}, or pass allowDebugProfile to test`,\n );\n }\n const accepted = (image.allowed_tcb_statuses ?? ['uptodate']).map((status) => tcbStatus(status, name));\n statuses = statuses === undefined ? accepted : statuses.filter((status) => accepted.includes(status));\n return {\n mrtd: image.mrtd,\n rtmr0: image.rtmr0,\n rtmr1: image.rtmr1,\n rtmr2: image.rtmr2,\n rtmr3: image.rtmr3,\n };\n });\n if (!statuses || statuses.length === 0) {\n throw new Error('The releases given accept no TCB status in common');\n }\n return { allowedMeasurements, allowedTcbStatuses: statuses };\n}\n\nfunction tcbStatus(status: string, release: string): string {\n const known = TCB_STATUSES.find((candidate) => candidate.toLowerCase() === String(status).toLowerCase());\n if (!known) {\n throw new Error(`${release} accepts TCB status ${JSON.stringify(status)}, which this verifier does not know`);\n }\n return known;\n}\n", "/**\n * Trusting a TEE node's image by its signed release, fetched at run time from\n * anywhere, instead of shipping the release's `published-mrtds.json` with the\n * app.\n *\n * Each mero-tee node release publishes `published-mrtds.json` (the\n * measurements of its image) with a cosign keyless bundle, signed by the\n * mero-tee release workflow on GitHub Actions. {@link verifySignedNodeRelease}\n * checks that signature here, against the Sigstore trust root embedded in this\n * package, so the file can come from any source: the cloud's mirror\n * (`GET https://cloud.calimero.network/api/tee/node-releases/{version}`), a\n * mirror of your own, or a file bundled with the app. None of them is\n * trusted; a file whose signature does not verify is refused.\n *\n * What is trusted:\n *\n * - the signer: the node release workflow of `calimero-network/mero-tee` on\n * `master` ({@link NODE_RELEASE_SIGNER}), the identity core pins as\n * `NODE_RELEASE_IDENTITY`;\n * - the Sigstore public-good trust root: Fulcio's CAs and Rekor's key;\n * - the minimum release you pass, below which no release is accepted.\n *\n * What is not: the transport, the server that serves the release, and the\n * node's choice of release. A node can present any genuinely signed release\n * at or above the minimum, and no other; its quote must then match that\n * release's measurements exactly, so it cannot claim one release and run\n * another.\n */\n\nimport { verifyCosignBundle, type SignerIdentity } from './sigstore.js';\nimport {\n createQuoteVerifier,\n trustedMeasurementsFromReleases,\n type DcapVerify,\n type PublishedMrtds,\n type QuoteVerifier,\n type QuoteVerifierOptions,\n type TrustedProfileOptions,\n} from './verify.js';\n\n/** The workflow that signs every mero-tee node release, and the issuer of its identity. */\nexport const NODE_RELEASE_SIGNER: Readonly<SignerIdentity> = Object.freeze({\n identity:\n 'https://github.com/calimero-network/mero-tee/.github/workflows/release-node-image-gcp.yaml@refs/heads/master',\n issuer: 'https://token.actions.githubusercontent.com',\n});\n\nconst MEASUREMENTS = ['mrtd', 'rtmr0', 'rtmr1', 'rtmr2', 'rtmr3'] as const;\n\n/**\n * The public mirror of signed node releases, used when no other source is\n * given. Only a transport: what it serves is verified, so it can fail to\n * answer but cannot make a release trusted.\n */\nexport const DEFAULT_RELEASE_MIRROR = 'https://cloud.calimero.network';\n\n/**\n * Where browsers get Intel's collateral for a quote: the cloud's mirror of the\n * PCCS paths `@phala/dcap-qvl` reads, open to any origin. Intel's PCS sends no\n * CORS header. The mirror only carries Intel-signed items.\n */\nexport const DEFAULT_COLLATERAL_MIRROR = `${DEFAULT_RELEASE_MIRROR}/api/tee/pcs`;\n\n/**\n * A node release as the servers hand it out, wrapped as `{\"data\": ...}`: the\n * release's `published-mrtds.json`, byte for byte, and its cosign bundle.\n * Unverified until {@link verifySignedNodeRelease} says otherwise.\n */\nexport interface SignedNodeRelease {\n /** The release, e.g. `2.3.87`. It must be the signed file's `tag`. */\n version: string;\n /** `published-mrtds.json`, exactly as signed. */\n publishedMrtds: string;\n /** `published-mrtds.json.bundle.json`, as JSON text. */\n bundle: string;\n}\n\nexport interface VerifySignedNodeReleaseOptions {\n /** Require the file's `tag` to be this release. */\n expectedVersion?: string;\n /** The certificate identity required. Defaults to {@link NODE_RELEASE_SIGNER}'s. */\n identity?: string;\n /** The OIDC issuer required. Defaults to {@link NODE_RELEASE_SIGNER}'s. */\n issuer?: string;\n /** The release's detached `published-mrtds.json.sig`, when you have it; it must be the bundle's. */\n signature?: string;\n}\n\n/**\n * Verify a node release's `published-mrtds.json` against its cosign bundle,\n * as `cosign verify-blob` would, and return the file parsed. Rejects, with the\n * reason, unless:\n *\n * - the signature over the exact bytes verifies with the bundle's certificate;\n * - that certificate chains to a Fulcio CA in the Sigstore trust root, and it\n * and the CA were valid when Rekor logged the signature;\n * - it names the node release workflow and GitHub Actions as its issuer;\n * - Rekor's signed entry timestamp verifies, for an entry that is this\n * signature over this file by this certificate;\n * - the file is a node release (`role: \"node\"`), and `expectedVersion`, when\n * given, is its `tag`.\n *\n * Nothing is read from the clock: the certificate is checked at the time Rekor\n * logged the signature, so a release that verifies once always does.\n */\nexport async function verifySignedNodeRelease(\n publishedMrtds: string | Uint8Array,\n bundle: string | object,\n options: VerifySignedNodeReleaseOptions = {},\n): Promise<PublishedMrtds> {\n const body = typeof publishedMrtds === 'string' ? new TextEncoder().encode(publishedMrtds) : publishedMrtds;\n await verifyCosignBundle(\n body,\n bundle,\n {\n identity: options.identity ?? NODE_RELEASE_SIGNER.identity,\n issuer: options.issuer ?? NODE_RELEASE_SIGNER.issuer,\n },\n options.signature,\n );\n\n let release: PublishedMrtds;\n try {\n release = JSON.parse(new TextDecoder().decode(body));\n } catch {\n throw new Error('The signed release is not JSON');\n }\n if (release?.role !== 'node') {\n throw new Error(`The signed release is a ${JSON.stringify(release?.role)} release, not a node one`);\n }\n // The workflow signs other files too, some with a `role` and `profiles` of\n // their own (`release-provenance.json`): the signature covers bytes, not a\n // file name, so check this is the measurements file.\n const profiles = Object.values(release.profiles ?? {});\n const measured = (image: unknown) =>\n MEASUREMENTS.every((register) => /^[0-9a-f]{96}$/i.test(String((image as Record<string, unknown>)?.[register])));\n if (typeof release.tag !== 'string' || profiles.length === 0 || !profiles.every(measured)) {\n throw new Error(\"The signed file is not a release's published-mrtds.json: it lists no measured profiles\");\n }\n if (options.expectedVersion !== undefined && release.tag !== options.expectedVersion) {\n throw new Error(`The signed release is ${release.tag}, not ${options.expectedVersion}`);\n }\n return release;\n}\n\n/**\n * Fetch a {@link SignedNodeRelease} from a server that wraps it as\n * `{\"data\": ...}`, such as the cloud's {@link cloudNodeReleaseUrl}. It is\n * only fetched: pass it to\n * {@link trustSignedRelease}, or {@link verifySignedNodeRelease}, before using it.\n */\nexport async function fetchNodeRelease(\n url: string,\n options: { fetch?: typeof fetch } = {},\n): Promise<SignedNodeRelease> {\n const response = await (options.fetch ?? fetch)(url, { headers: { accept: 'application/json' } });\n if (!response.ok) throw new Error(`Fetching the node release from ${url} failed: HTTP ${response.status}`);\n let release: Partial<SignedNodeRelease> | undefined;\n try {\n release = ((await response.json()) as { data?: Partial<SignedNodeRelease> })?.data;\n } catch {\n throw new Error(`${url} did not answer with JSON`);\n }\n if (\n typeof release?.version !== 'string' ||\n typeof release.publishedMrtds !== 'string' ||\n typeof release.bundle !== 'string'\n ) {\n throw new Error(`${url} did not answer with a signed node release`);\n }\n return { version: release.version, publishedMrtds: release.publishedMrtds, bundle: release.bundle };\n}\n\n/** Where mero-tee publishes its releases' assets, as core's `calimero-tee-release` fetches them. */\nexport const GITHUB_RELEASES = 'https://github.com/calimero-network/mero-tee/releases/download';\n\n/**\n * Node release `version` straight from its GitHub release (`mero-tee-v{version}`):\n * `published-mrtds.json` and its cosign bundle, the files core's Rust client\n * verifies. Only fetched: verify it with {@link trustSignedRelease}. GitHub's\n * downloads send no CORS headers, so in a browser use a mirror\n * ({@link cloudNodeReleaseUrl}) instead.\n */\nexport async function fetchGithubNodeRelease(\n version: string,\n options: { fetch?: typeof fetch; base?: string } = {},\n): Promise<SignedNodeRelease> {\n const tag = `mero-tee-v${releaseVersion(version, 'version')}`;\n const base = `${(options.base ?? GITHUB_RELEASES).replace(/\\/+$/, '')}/${tag}/published-mrtds.json`;\n const get = async (url: string): Promise<string> => {\n const response = await (options.fetch ?? fetch)(url);\n if (!response.ok) throw new Error(`Fetching ${url} failed: HTTP ${response.status}`);\n return response.text();\n };\n const [publishedMrtds, bundle] = await Promise.all([get(base), get(`${base}.bundle.json`)]);\n return { version, publishedMrtds, bundle };\n}\n\n/** Where the cloud at `cloudUrl` (e.g. `https://cloud.calimero.network`) mirrors node release `version`. */\nexport function cloudNodeReleaseUrl(cloudUrl: string, version: string): string {\n return `${cloudUrl.replace(/\\/+$/, '')}/api/tee/node-releases/${releaseVersion(version, 'version')}`;\n}\n\nexport interface TrustSignedReleaseOptions extends TrustedProfileOptions {\n /** The release, from any source; it is verified here. */\n release: SignedNodeRelease;\n /**\n * The oldest release accepted, e.g. `2.3.87`. Required: every release ever\n * signed stays validly signed, so without a floor a node could present an\n * old release, with a flaw since fixed, and a quote from that old image\n * would pass. Raise it when a release must no longer be trusted.\n */\n minReleaseVersion: string;\n /** Override the signer; defaults to {@link NODE_RELEASE_SIGNER}. */\n identity?: string;\n issuer?: string;\n}\n\n/**\n * The {@link QuoteVerifierOptions} that trust one profile of a signed node\n * release, from an untrusted source: its signature is verified, its signed\n * `tag` must be `release.version` and no older than `minReleaseVersion`, and\n * then it is read as {@link trustedMeasurementsFromReleases} reads a bundled\n * file.\n *\n * ```ts\n * const version = claimedRelease(attestationDoc, '2.3.109'); // the release the node names\n * const release = await fetchNodeRelease(cloudNodeReleaseUrl(DEFAULT_RELEASE_MIRROR, version));\n * const verifier = createQuoteVerifier({\n * dcapVerify,\n * ...(await trustSignedRelease({ release, profile: 'locked-read-only', minReleaseVersion: '2.3.87' })),\n * });\n * ```\n */\nexport async function trustSignedRelease(\n options: TrustSignedReleaseOptions,\n): Promise<Required<Pick<QuoteVerifierOptions, 'allowedMeasurements' | 'allowedTcbStatuses'>>> {\n const minimum = releaseVersion(options.minReleaseVersion, 'minReleaseVersion');\n const version = releaseVersion(options.release?.version, 'The release version');\n const published = await verifySignedNodeRelease(options.release.publishedMrtds, options.release.bundle, {\n expectedVersion: version,\n identity: options.identity,\n issuer: options.issuer,\n });\n if (compareReleaseVersions(version, minimum) < 0) {\n throw new Error(`Release ${version} is older than the minimum trusted, ${minimum}`);\n }\n return trustedMeasurementsFromReleases([published], {\n profile: options.profile,\n allowDebugProfile: options.allowDebugProfile,\n });\n}\n\nexport interface SignedReleaseVerifierOptions extends Omit<TrustSignedReleaseOptions, 'release'> {\n /** DCAP verification: `verify` from `@phala/dcap-qvl`. */\n dcapVerify: DcapVerify;\n /**\n * Where to get the node's release, asked again each time the node is\n * attested (a restarted node may run a newer one). Untrusted: it is\n * verified, and the quote must match it.\n */\n release: () => Promise<SignedNodeRelease>;\n /** As {@link QuoteVerifierOptions.fetchCollateral}. */\n fetchCollateral?: QuoteVerifierOptions['fetchCollateral'];\n /** The current time in milliseconds, for the quote's collateral; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\n/**\n * A {@link createQuoteVerifier} whose trusted image is the signed release the\n * node says it runs. On each attestation it gets the release, checks it with\n * {@link trustSignedRelease}, and verifies the quote against that release's\n * measurements only.\n *\n * The node's choice of release is the one thing taken from it, and it is\n * bounded: only a genuinely signed release at or above `minReleaseVersion`\n * passes, and the quote must then be of exactly that release's image. Pass it\n * as `CloudPolicy.verifyQuote` to choose where the release comes from yourself.\n */\nexport function createSignedReleaseVerifier(options: SignedReleaseVerifierOptions): QuoteVerifier {\n releaseVersion(options.minReleaseVersion, 'minReleaseVersion');\n const verifier = async (args: Parameters<QuoteVerifier>[0]): Promise<boolean> => {\n const trusted = await trustSignedRelease({\n release: await options.release(),\n profile: options.profile,\n allowDebugProfile: options.allowDebugProfile,\n minReleaseVersion: options.minReleaseVersion,\n identity: options.identity,\n issuer: options.issuer,\n });\n return createQuoteVerifier({\n dcapVerify: options.dcapVerify,\n fetchCollateral: options.fetchCollateral,\n now: options.now,\n ...trusted,\n })(args);\n };\n return Object.assign(verifier, { includeCollateral: true as const });\n}\n\nconst RELEASE_VERSION = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/;\n\n/** `value` if it is a release version (`2.3.87`, `2.3.88-rc.1`); throws otherwise. */\nexport function releaseVersion(value: unknown, what: string): string {\n const match = typeof value === 'string' ? RELEASE_VERSION.exec(value) : null;\n const pre = match?.[4];\n if (!match || (pre !== undefined && pre.split('.').some((id) => id === ''))) {\n throw new Error(`${what} is ${JSON.stringify(value)}, not a release version like 2.3.87`);\n }\n return value as string;\n}\n\n/**\n * Order two release versions as semver does, and as core's\n * `compare_release_versions`: numerically by `X.Y.Z`, a pre-release before its\n * release, build metadata ignored.\n */\nexport function compareReleaseVersions(a: string, b: string): number {\n const [aCore, aPre] = splitVersion(a);\n const [bCore, bPre] = splitVersion(b);\n for (let i = 0; i < 3; i += 1) {\n if (aCore[i] !== bCore[i]) return aCore[i] < bCore[i] ? -1 : 1;\n }\n if (aPre === undefined || bPre === undefined) return aPre === bPre ? 0 : aPre === undefined ? 1 : -1;\n const aIds = aPre.split('.');\n const bIds = bPre.split('.');\n for (let i = 0; i < Math.max(aIds.length, bIds.length); i += 1) {\n const [x, y] = [aIds[i], bIds[i]];\n if (x === undefined || y === undefined) return x === undefined ? -1 : 1;\n const [xNum, yNum] = [/^\\d+$/.test(x), /^\\d+$/.test(y)];\n const order =\n xNum && yNum ? Math.sign(Number(x) - Number(y)) : xNum !== yNum ? (xNum ? -1 : 1) : x < y ? -1 : x > y ? 1 : 0;\n if (order !== 0) return order;\n }\n return 0;\n}\n\nfunction splitVersion(version: string): [number[], string | undefined] {\n const match = RELEASE_VERSION.exec(version) as RegExpExecArray;\n return [[Number(match[1]), Number(match[2]), Number(match[3])], match[4]];\n}\n", "/**\n * The check every cloud client runs before it sends anything: the node's quote\n * must be genuine (or, in development, an explicitly allowed mock), from an\n * image this client trusts, and its report data must bind this nonce, the\n * expected app and the transport key the sealed channel will be opened to.\n *\n * Report data, as core's `calimero-cloud-client::attest` builds it:\n * `nonce(32) || SHA-256(\"calimero.tee-attest.transport-key.v1\" | app_hash | transport_key)`.\n *\n * A real quote is judged as the Rust client judges it (`attest::verify` with\n * `Measurements::Release`): the node names the mero-tee release it runs; that\n * release must be at least `minReleaseVersion`; its `published-mrtds.json` is\n * fetched and its Sigstore signature checked against the node release workflow;\n * the quote's signature chain and TCB status are checked against Intel's\n * collateral (fetched here: the node sends none, and cannot forge it); the TD\n * must not be a debug TD; and its registers must be the release's image for the\n * trusted profile, `locked-read-only` unless a debug profile is explicitly\n * allowed. Nothing here reads the environment: mock quotes pass only with\n * `allowMock`.\n */\n\nimport { fromHex, hex } from '../crypto/internal.js';\nimport {\n DEFAULT_COLLATERAL_MIRROR,\n DEFAULT_RELEASE_MIRROR,\n cloudNodeReleaseUrl,\n compareReleaseVersions,\n fetchGithubNodeRelease,\n fetchNodeRelease,\n releaseVersion,\n trustSignedRelease,\n type SignedNodeRelease,\n} from '../sealed/release.js';\nimport { transportKeyBinding, type VerifyTransportQuote } from '../sealed/sealed.js';\nimport { PRODUCTION_PROFILE, createQuoteVerifier, type DcapCollateral, type DcapVerify } from '../sealed/verify.js';\n\n/** The mock quote format development clusters use. */\nexport const MOCK_QUOTE_HEADER = 'MOCK_TDX_QUOTE_V1';\n\n/** How the signed release a node names is trusted (core's `Measurements::Release`). */\nexport interface CloudReleasePolicy {\n /**\n * The oldest mero-tee release trusted, e.g. `2.3.109`. Required: every\n * release ever signed stays validly signed, so without a floor a node could\n * name an old release with a flaw since fixed.\n */\n minReleaseVersion: string;\n /** The image profile trusted; defaults to `locked-read-only`. */\n profile?: string;\n /** Trust a debug profile. Its image is readable by the operator: testing only. */\n allowDebugProfile?: boolean;\n /**\n * Where the release's signed measurements come from: `'github'` (the release\n * assets, what core's Rust client reads; no CORS, so not in browsers), the\n * base URL of a mirror (default {@link DEFAULT_RELEASE_MIRROR}), or a function.\n * Untrusted either way: the Sigstore signature is checked here.\n */\n releaseSource?: 'github' | string | ((version: string) => Promise<SignedNodeRelease>);\n /** DCAP verification; defaults to `verify` from `@phala/dcap-qvl`, loaded on first use. */\n dcapVerify?: DcapVerify;\n /**\n * Intel's collateral for a quote. Defaults to `@phala/dcap-qvl`'s\n * `getCollateral` from `collateralSource`.\n */\n fetchCollateral?: (quote: Uint8Array) => Promise<DcapCollateral>;\n /**\n * Where the default `fetchCollateral` gets Intel's collateral: a PCCS base\n * URL (default {@link DEFAULT_COLLATERAL_MIRROR}, the cloud's mirror, which a\n * browser on any origin can read), or `'intel'` for Intel's PCS itself (no\n * CORS: not in browsers). Untrusted either way: every item is signed by\n * Intel and verified up to Intel's root CA, which `@phala/dcap-qvl` carries.\n */\n collateralSource?: 'intel' | string;\n /**\n * Refuse collateral whose TCB info Intel issued more than this many days\n * ago. Unset: only Intel's own `nextUpdate` (about 30 days out) bounds how\n * old it may be. A mirror cannot forge collateral, but it can replay an\n * older, still valid copy; this shortens that window. Too small a value\n * refuses every node if Intel is slow to re-sign.\n */\n maxCollateralAgeDays?: number;\n /** Override the release signer (defaults to the mero-tee node release workflow). */\n identity?: string;\n issuer?: string;\n /** The current time in milliseconds; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\nexport interface CloudPolicy {\n /** Accept mock quotes. Development clusters only; never set from the environment. */\n allowMock?: boolean;\n /** Trust real quotes from the signed release the node runs. */\n release?: CloudReleasePolicy;\n /**\n * Verify a real quote yourself instead (e.g. `createQuoteVerifier` with\n * pinned measurements). Takes precedence over `release`.\n */\n verifyQuote?: VerifyTransportQuote;\n /** The app bundle hash (hex) the quote must bind, when talking to one app. */\n appHash?: string;\n}\n\nexport interface AttestationDoc {\n quote: string;\n transportKey: string;\n appHash: string;\n nonce: string;\n release: { version: string; profile: string };\n cluster: string;\n node: number;\n mock: boolean;\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n return diff === 0;\n}\n\ntype DcapModule = {\n verify?: unknown;\n getCollateral?: unknown;\n getCollateralFromPcs?: unknown;\n default?: { verify?: unknown; getCollateral?: unknown; getCollateralFromPcs?: unknown };\n};\nlet dcapModule: Promise<DcapModule> | undefined;\n\n/** A function out of `@phala/dcap-qvl`, whatever shape the bundler gave the (CommonJS) module. */\nasync function dcap<T>(name: 'verify' | 'getCollateral' | 'getCollateralFromPcs'): Promise<T> {\n dcapModule ??= import('@phala/dcap-qvl') as Promise<DcapModule>;\n const ns = await dcapModule;\n const f = typeof ns[name] === 'function' ? ns[name] : ns.default?.[name];\n if (typeof f !== 'function') throw new TypeError(`@phala/dcap-qvl loaded without ${name}`);\n return f as T;\n}\n\n/**\n * The release a node names, checked against the floor before anything is\n * fetched. Accepts `2.3.109` and the tag form `mero-tee-v2.3.109`.\n */\nexport function claimedRelease(doc: Pick<AttestationDoc, 'release'>, minReleaseVersion: string): string {\n const floor = releaseVersion(minReleaseVersion, 'minReleaseVersion');\n const raw = String(doc.release?.version ?? '').trim().replace(/^mero-tee-v/, '').replace(/^v/, '');\n const version = releaseVersion(raw, 'The release the node names');\n if (compareReleaseVersions(version, floor) < 0) {\n throw new Error(`mero-tee release ${version} is older than the minimum ${floor}`);\n }\n return version;\n}\n\nasync function releaseFor(version: string, policy: CloudReleasePolicy, fetchImpl: typeof fetch) {\n const source = policy.releaseSource;\n if (typeof source === 'function') return source(version);\n if (source === 'github') return fetchGithubNodeRelease(version, { fetch: fetchImpl });\n return fetchNodeRelease(cloudNodeReleaseUrl(source ?? DEFAULT_RELEASE_MIRROR, version), { fetch: fetchImpl });\n}\n\n/** The collateral fetch a policy gets unless it brings its own: `@phala/dcap-qvl` against `collateralSource`. */\nfunction defaultCollateral(policy: CloudReleasePolicy): (quote: Uint8Array) => Promise<DcapCollateral> {\n const source = policy.collateralSource ?? DEFAULT_COLLATERAL_MIRROR;\n if (source === 'intel') {\n return async (quote) => (await dcap<(q: Uint8Array) => Promise<DcapCollateral>>('getCollateralFromPcs'))(quote);\n }\n return async (quote) =>\n (await dcap<(url: string, q: Uint8Array) => Promise<DcapCollateral>>('getCollateral'))(source, quote);\n}\n\n/** `fetch`, refusing collateral older than `policy.maxCollateralAgeDays` (by its TCB info's `issueDate`). */\nexport function freshCollateral(\n fetch: (quote: Uint8Array) => Promise<DcapCollateral>,\n policy: Pick<CloudReleasePolicy, 'maxCollateralAgeDays' | 'now'>,\n): (quote: Uint8Array) => Promise<DcapCollateral> {\n const maxDays = policy.maxCollateralAgeDays;\n if (maxDays === undefined) return fetch;\n return async (quote) => {\n const collateral = await fetch(quote);\n let issued: number;\n try {\n issued = Date.parse((JSON.parse(collateral.tcb_info) as { issueDate?: string }).issueDate ?? '');\n } catch {\n issued = Number.NaN;\n }\n if (!Number.isFinite(issued)) throw new Error(\"The quote's collateral names no TCB info issue date\");\n const ageDays = ((policy.now ?? Date.now)() - issued) / 86_400_000;\n if (ageDays > maxDays) {\n throw new Error(\n `The quote's collateral was issued ${Math.floor(ageDays)} days ago, more than the ${maxDays} this client accepts`,\n );\n }\n return collateral;\n };\n}\n\n/** Judge a real quote as core's `Measurements::Release` does. */\nasync function verifyRelease(\n doc: AttestationDoc,\n args: Parameters<VerifyTransportQuote>[0],\n policy: CloudReleasePolicy,\n fetchImpl: typeof fetch,\n): Promise<boolean> {\n // Refuse what no release could admit before reaching for the network.\n const version = claimedRelease(doc, policy.minReleaseVersion);\n const trusted = await trustSignedRelease({\n release: await releaseFor(version, policy, fetchImpl),\n profile: policy.profile ?? PRODUCTION_PROFILE,\n allowDebugProfile: policy.allowDebugProfile,\n minReleaseVersion: policy.minReleaseVersion,\n identity: policy.identity,\n issuer: policy.issuer,\n });\n const fetchCollateral = freshCollateral(policy.fetchCollateral ?? defaultCollateral(policy), policy);\n const verifier = createQuoteVerifier({\n dcapVerify: policy.dcapVerify ?? (await dcap<DcapVerify>('verify')),\n fetchCollateral,\n now: policy.now,\n ...trusted,\n });\n return verifier(args);\n}\n\n/** Fetch the node's attestation and return its transport key once it checks out. */\nexport async function fetchAttestedKey(\n baseUrl: string,\n policy: CloudPolicy,\n fetchImpl: typeof fetch = (input, init) => fetch(input, init),\n): Promise<Uint8Array> {\n const nonce = hex(crypto.getRandomValues(new Uint8Array(32)));\n const url = new URL(`${baseUrl.replace(/\\/+$/, '')}/attestation`);\n url.searchParams.set('nonce', nonce);\n if (policy.appHash) url.searchParams.set('appHash', policy.appHash);\n const response = await fetchImpl(url.toString());\n if (!response.ok) throw new Error(`The node refused to attest: HTTP ${response.status}`);\n const doc = (await response.json()) as AttestationDoc;\n const transportKey = fromHex(doc.transportKey, 'transportKey', 32);\n const inner = policy.appHash ? fromHex(policy.appHash, 'appHash', 32) : new Uint8Array(32);\n const suffix = await transportKeyBinding(inner, transportKey);\n const quote = base64ToBytes(doc.quote);\n const header = new TextEncoder().encode(MOCK_QUOTE_HEADER);\n if (equal(quote.slice(0, header.length), header)) {\n if (!policy.allowMock) {\n throw new Error('mock quote refused: this client only trusts real TEEs');\n }\n const report = quote.slice(header.length, header.length + 64);\n if (!equal(report.slice(0, 32), fromHex(nonce, 'nonce', 32)) || !equal(report.slice(32), suffix)) {\n throw new Error('the quote does not bind this transport key, app and nonce');\n }\n return transportKey;\n }\n const args = { quoteB64: doc.quote, nonce, reportDataSuffix: hex(suffix) };\n let ok: boolean;\n if (policy.verifyQuote) {\n ok = await policy.verifyQuote(args);\n } else if (policy.release) {\n ok = await verifyRelease(doc, args, policy.release, fetchImpl);\n } else {\n throw new Error('real quote refused: this client trusts no TD image (set policy.release)');\n }\n if (!ok) throw new Error('The attestation did not verify, so its transport key is not trusted');\n return transportKey;\n}\n", "/**\n * The Calimero Cloud node directory: which nodes of a cluster take traffic now,\n * and in what order this client tries them.\n *\n * `GET {directory}/{cluster}` (no auth) answers\n * `{ cluster, nodes: [{ id, url, zone, weight }], refreshAfterSeconds }`. The\n * directory is not trusted for security: it only picks which nodes to try.\n * Every node is attested under the caller's own policy before anything is sent\n * to it, so a bad list can only make connecting fail.\n */\n\n/** The Calimero Cloud control plane's public node directory. */\nexport const DEFAULT_DIRECTORY = 'https://manager.cloud.calimero.network/api/v2/directory';\n\n/** How long a listing stands when the directory does not say. */\nconst DEFAULT_REFRESH_SECONDS = 60;\n\n/** Why {@link DirectoryError} was thrown. */\nexport type DirectoryFailure = 'unreachable' | 'not-found' | 'bad-response' | 'empty';\n\n/**\n * The directory could not name a node to try: it could not be reached or\n * answered an error (`unreachable`), does not know the cluster (`not-found`,\n * a 404), answered something that is not a listing (`bad-response`), or listed\n * no usable node (`empty`).\n */\nexport class DirectoryError extends Error {\n constructor(\n readonly cluster: string,\n readonly reason: DirectoryFailure,\n message: string,\n readonly status?: number,\n readonly cause?: unknown,\n ) {\n super(`directory for cluster ${cluster}: ${message}`);\n this.name = 'DirectoryError';\n }\n}\n\n/** One usable node of a listing. */\nexport interface DirectoryNode {\n url: string;\n zone?: string;\n weight: number;\n}\n\nexport interface DirectoryListing {\n nodes: DirectoryNode[];\n refreshAfterSeconds: number;\n}\n\n/** The URL of `cluster`'s listing in `directory`. */\nexport function directoryUrl(directory: string, cluster: string): string {\n return `${directory.replace(/\\/+$/, '')}/${encodeURIComponent(cluster)}`;\n}\n\n/**\n * Read `cluster`'s listing, keeping only the entries with an http(s) URL and a\n * positive integer weight (the first of a repeated URL).\n */\nexport async function readDirectory(directory: string, cluster: string, fetcher: typeof fetch): Promise<DirectoryListing> {\n let response: Response;\n try {\n response = await fetcher(directoryUrl(directory, cluster), { method: 'GET', headers: { accept: 'application/json' } });\n } catch (error) {\n throw new DirectoryError(cluster, 'unreachable', `could not be reached: ${String(error)}`, undefined, error);\n }\n if (response.status === 404) throw new DirectoryError(cluster, 'not-found', 'unknown cluster', 404);\n if (!response.ok) throw new DirectoryError(cluster, 'unreachable', `answered ${response.status}`, response.status);\n let body: unknown;\n try {\n body = await response.json();\n } catch (error) {\n throw new DirectoryError(cluster, 'bad-response', 'answered something other than JSON', response.status, error);\n }\n const listing = body as { nodes?: unknown; refreshAfterSeconds?: unknown } | null;\n if (!listing || typeof listing !== 'object' || !Array.isArray(listing.nodes)) {\n throw new DirectoryError(cluster, 'bad-response', 'answered no node list', response.status);\n }\n const nodes: DirectoryNode[] = [];\n const seen = new Set<string>();\n for (const entry of listing.nodes) {\n const node = usable(entry);\n if (node && !seen.has(node.url)) {\n seen.add(node.url);\n nodes.push(node);\n }\n }\n if (nodes.length === 0) throw new DirectoryError(cluster, 'empty', 'lists no usable node', response.status);\n const after = listing.refreshAfterSeconds;\n const refreshAfterSeconds =\n typeof after === 'number' && Number.isFinite(after) && after >= 1 ? after : DEFAULT_REFRESH_SECONDS;\n return { nodes, refreshAfterSeconds };\n}\n\nfunction usable(entry: unknown): DirectoryNode | undefined {\n if (!entry || typeof entry !== 'object') return undefined;\n const { url, zone, weight } = entry as Record<string, unknown>;\n if (typeof url !== 'string' || typeof weight !== 'number' || !Number.isInteger(weight) || weight < 1) return undefined;\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return undefined;\n }\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') return undefined;\n return { url: url.replace(/\\/+$/, ''), zone: typeof zone === 'string' ? zone : undefined, weight };\n}\n\n/**\n * The order to try `nodes` in: those in `zone` first (when given), each group\n * in weighted-random order, a node's weight its relative chance to come next.\n * `random` answers in [0, 1), as `Math.random` does.\n */\nexport function orderNodes(nodes: DirectoryNode[], zone: string | undefined, random: () => number): string[] {\n const near = zone === undefined ? [] : nodes.filter((node) => node.zone === zone);\n const far = zone === undefined ? nodes : nodes.filter((node) => node.zone !== zone);\n return [...weightedOrder(near, random), ...weightedOrder(far, random)];\n}\n\nfunction weightedOrder(nodes: DirectoryNode[], random: () => number): string[] {\n const left = [...nodes];\n const order: string[] = [];\n while (left.length > 0) {\n let roll = random() * left.reduce((sum, node) => sum + node.weight, 0);\n let pick = 0;\n while (pick < left.length - 1 && roll >= left[pick].weight) roll -= left[pick++].weight;\n order.push(left.splice(pick, 1)[0].url);\n }\n return order;\n}\n", "/**\n * What the cloud node's refusals mean to a caller (spec D64, D70).\n *\n * The node answers an error as `{ error: CODE, message, details }` with an HTTP\n * status. {@link errorFrom} is the one place the client turns that into an\n * error a caller can switch on; every call, view and event stream goes through\n * it. It matches the status and the code together, never the status alone: the\n * node sends other 409s (`CONFLICT`, `NOT_INSTALLED`) that are not an\n * idempotency mismatch, and other 413s (`TOO_LARGE` from the sealed transport)\n * that are not oversized call arguments. Anything it does not recognise stays a\n * plain {@link CalimeroError} carrying both.\n *\n * Every typed error extends {@link CalimeroError}, so `instanceof CalimeroError`\n * and its `status` and `code` (the node's code) keep working for all of them.\n */\n\nexport class CalimeroError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n readonly details: Record<string, unknown> = {},\n ) {\n super(`${status} ${code}: ${message}`);\n this.name = 'CalimeroError';\n }\n}\n\n/**\n * `401 UNAUTHENTICATED` that refreshing could not answer: sign in (again) and\n * repeat the request.\n *\n * A session token is signed by the node that issued it, and other nodes take\n * it only while they can vouch for that node's signing key: a `401` often\n * means only that the issuer was replaced or cannot be reached, not that the\n * user signed out. The client answers that itself when it holds a refresh\n * token: it refreshes once (any node takes the refresh) and repeats the\n * request. This error reaches a caller when there is no refresh token (an API\n * key, say), or the refresh was refused.\n */\nexport class LoginRequired extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(401, 'UNAUTHENTICATED', message, details);\n this.name = 'LoginRequired';\n }\n}\n\n/**\n * `421 WRONG_NODE`: this node runs a mero-tee release the account's owners have\n * not approved, so it neither issues nor takes the account's sessions. Use\n * another node of the cluster; refreshing here would not help.\n *\n * The client moves to the next node it was given (`nodes`) and repeats the\n * request once by itself (a refresh: once per node). This error reaches a\n * caller when it knows no other node, when the next one refused too (for a\n * refresh, every node), or after a sign-in (which needs the passkey again:\n * repeat it, and it goes to the next node).\n */\nexport class WrongNode extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(421, 'WRONG_NODE', message, details);\n this.name = 'WrongNode';\n }\n}\n\n/**\n * `404 NOT_FOUND`: what the request names does not exist for this caller. For\n * an app this does not say whether it exists: an account the app does not\n * admit gets the same answer as a missing app.\n */\nexport class NotFound extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(404, 'NOT_FOUND', message, details);\n this.name = 'NotFound';\n }\n}\n\n/**\n * `412 CONFIRM_REQUIRED`: the call needs the account holder's passkey over a\n * challenge in `details`. The `*Confirmed` methods answer it themselves; it\n * reaches a caller only from a method that was given no passkey.\n */\nexport class ConfirmRequired extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(412, 'CONFIRM_REQUIRED', message, details);\n this.name = 'ConfirmRequired';\n }\n}\n\n/** The user declined the passkey prompt a confirmation asked for. Nothing was sent. */\nexport class ConfirmCancelled extends Error {\n constructor(readonly cause?: unknown) {\n super('the passkey confirmation was cancelled');\n this.name = 'ConfirmCancelled';\n }\n}\n\n/** `413 ARGS_TOO_LARGE`: the call's arguments are over the node's limit; it did not run. */\nexport class ArgsTooLarge extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(413, 'ARGS_TOO_LARGE', message, details);\n this.name = 'ArgsTooLarge';\n }\n}\n\n/** `409 IDEMPOTENCY_MISMATCH`: the idempotency key was used before with different arguments. */\nexport class IdempotencyMismatch extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(409, 'IDEMPOTENCY_MISMATCH', message, details);\n this.name = 'IdempotencyMismatch';\n }\n}\n\n/**\n * `409 RELEASE_DEADLINE`: a mero-tee release's deadline has passed and the\n * set that governs this work (the app's publisher's, or its owner's) has not\n * approved it or a newer one, so new work (creating an app, installing a\n * release, upgrading an app) is refused. Apps already running keep running.\n * Approving `release` lifts it at once.\n */\nexport class ReleaseDeadlineError extends CalimeroError {\n /** The release to approve. */\n readonly release: string;\n /** Its deadline, RFC 3339 (`''` when the node did not say). */\n readonly after: string;\n\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(409, 'RELEASE_DEADLINE', message, details);\n this.name = 'ReleaseDeadlineError';\n this.release = typeof details.release === 'string' ? details.release : '';\n this.after = typeof details.after === 'string' ? details.after : '';\n }\n}\n\n/**\n * `409 CONSENT_STALE`: what a consent page showed (the app's bundle, the\n * target release, the release's measurements) changed before the person\n * approved. Nothing was approved; ask for a new consent request so they see\n * the new facts.\n */\nexport class ConsentStale extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(409, 'CONSENT_STALE', message, details);\n this.name = 'ConsentStale';\n }\n}\n\n/**\n * `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared\n * error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was\n * logged, so its idempotency key is spent.\n */\nexport class AppError extends CalimeroError {\n readonly appCode: string;\n readonly fields: Record<string, unknown>;\n\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(422, 'APP_ERROR', message, details);\n this.name = 'AppError';\n const { appCode, fields } = appErrorOf(details);\n this.appCode = appCode;\n this.fields = fields;\n }\n}\n\n/** `422 TRAP`: the run trapped (`OutOfFuel`, `OutOfMemory`, ...). The call was logged. */\nexport class TrapError extends CalimeroError {\n readonly kind: string;\n\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(422, 'TRAP', message, details);\n this.name = 'TrapError';\n this.kind = typeof details.kind === 'string' ? details.kind : '';\n }\n}\n\n/**\n * Whether a call the node answered 503 may have committed: `false` when the\n * node says it did not (`TIMEOUT`, `MIGRATING`), `\"unknown\"` otherwise (a call\n * that raced a leader change). Never a plain boolean: `\"unknown\"` must not read\n * as \"no\".\n */\nexport type Committed = false | 'unknown';\n\n/**\n * Any `503`, or a connection that failed, after the client's retries with the\n * same idempotency key ran out. `reason` is the node's code in lower case\n * (`timeout`, `migrating`, `unavailable`, ...), or `network` when the node gave\n * no answer at all (code `NETWORK`, `cause` the `fetch` failure); such a call\n * may have committed, so its `committed` is `'unknown'`.\n */\nexport class UnavailableError extends CalimeroError {\n readonly reason: string;\n readonly committed: Committed;\n /** Seconds the node asked to wait, when it said. */\n readonly retryAfter: number | undefined;\n /** What failed, when the node gave no answer. */\n readonly cause: unknown;\n\n constructor(code: string, message: string, details: Record<string, unknown> = {}, retryAfter?: number, cause?: unknown) {\n super(503, code, message, details);\n this.name = 'UnavailableError';\n this.reason = code.toLowerCase();\n this.committed = code === 'TIMEOUT' || code === 'MIGRATING' ? false : 'unknown';\n this.retryAfter = retryAfter;\n this.cause = cause;\n }\n}\n\nfunction record(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n}\n\n/**\n * The app's code and named fields. The node puts them in `details` as\n * `{ code, fields }`; an older node nests the app's error under `details.error`.\n * Positional payloads (`\"0\"`, `\"1\"`) are never read as fields (D63).\n */\nfunction appErrorOf(details: Record<string, unknown>): { appCode: string; fields: Record<string, unknown> } {\n const source = typeof details.code === 'string' ? details : record(details.error);\n const appCode = typeof source.code === 'string' ? source.code : '';\n return { appCode, fields: { ...record(source.fields) } };\n}\n\nfunction retryAfterOf(details: Record<string, unknown>, header?: string | null): number | undefined {\n for (const candidate of [details.retryAfter, header == null ? undefined : Number(header)]) {\n if (typeof candidate === 'number' && Number.isFinite(candidate) && candidate >= 0) return candidate;\n }\n return undefined;\n}\n\n/**\n * The error for a refusal the node answered with `status` and `body` (its JSON\n * `{ error, message, details }`, or whatever it sent). The one place statuses\n * become typed errors.\n */\nexport function errorFrom(status: number, body: unknown, retryAfterHeader?: string | null): CalimeroError {\n const value = record(body);\n const code = typeof value.error === 'string' ? value.error : 'ERROR';\n const message = typeof value.message === 'string' ? value.message : '';\n const details = record(value.details);\n if (status === 503) return new UnavailableError(code, message, details, retryAfterOf(details, retryAfterHeader));\n switch (`${status} ${code}`) {\n case '401 UNAUTHENTICATED':\n return new LoginRequired(message, details);\n case '421 WRONG_NODE':\n return new WrongNode(message, details);\n case '404 NOT_FOUND':\n return new NotFound(message, details);\n case '409 IDEMPOTENCY_MISMATCH':\n return new IdempotencyMismatch(message, details);\n case '409 RELEASE_DEADLINE':\n return new ReleaseDeadlineError(message, details);\n case '409 CONSENT_STALE':\n return new ConsentStale(message, details);\n case '412 CONFIRM_REQUIRED':\n return new ConfirmRequired(message, details);\n case '413 ARGS_TOO_LARGE':\n return new ArgsTooLarge(message, details);\n case '422 APP_ERROR':\n return new AppError(message, details);\n case '422 TRAP':\n return new TrapError(message, details);\n default:\n return new CalimeroError(status, code, message, details);\n }\n}\n", "/**\n * Passkeys: the browser's WebAuthn API, or anything that answers like it.\n *\n * Every binary field crosses the wire as base64url, matching\n * `calimero-identity`'s `Registration` and `Assertion`.\n */\n\nexport interface RegistrationJSON {\n attestationObject: string;\n clientDataJson: string;\n}\n\nexport interface AssertionJSON {\n credentialId: string;\n authenticatorData: string;\n clientDataJson: string;\n signature: string;\n}\n\n/** Something that holds a passkey. */\nexport interface PasskeyProvider {\n /** Answer `navigator.credentials.create` for the node's options. */\n create(options: Record<string, unknown>): Promise<RegistrationJSON>;\n /** Sign `challenge` (an assertion), optionally limited to `allowCredentials`. */\n get(challenge: Uint8Array, rpId: string, allowCredentials?: string[]): Promise<AssertionJSON>;\n}\n\nexport function b64url(bytes: Uint8Array): string {\n let bin = '';\n for (const b of bytes) bin += String.fromCharCode(b);\n return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nexport function fromB64url(s: string): Uint8Array {\n const pad = s.replace(/-/g, '+').replace(/_/g, '/') + '==='.slice((s.length + 3) % 4);\n const bin = atob(pad);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nconst buf = (b: Uint8Array): ArrayBuffer => b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength) as ArrayBuffer;\n\n/** A dismissed prompt, named as WebAuthn names one (`NotAllowedError`), so a confirmation reads it as declined. */\nfunction cancelled(message: string): Error {\n const error = new Error(message);\n error.name = 'NotAllowedError';\n return error;\n}\n\n/** The platform authenticator (Touch ID, Face ID, Windows Hello, a security key, a synced passkey). */\nexport function browserPasskey(): PasskeyProvider {\n return {\n async create(options) {\n const o = options as {\n challenge: string;\n rp: { id: string; name: string };\n user: { id: string; name: string; displayName: string };\n pubKeyCredParams: Array<{ type: 'public-key'; alg: number }>;\n excludeCredentials?: Array<{ type: 'public-key'; id: string }>;\n authenticatorSelection?: AuthenticatorSelectionCriteria;\n timeout?: number;\n };\n const cred = (await navigator.credentials.create({\n publicKey: {\n challenge: buf(fromB64url(o.challenge)),\n rp: o.rp,\n user: { ...o.user, id: buf(fromB64url(o.user.id)) },\n pubKeyCredParams: o.pubKeyCredParams,\n excludeCredentials: (o.excludeCredentials ?? []).map((c) => ({ type: c.type, id: buf(fromB64url(c.id)) })),\n authenticatorSelection: o.authenticatorSelection,\n attestation: 'none',\n timeout: o.timeout,\n },\n })) as PublicKeyCredential | null;\n if (!cred) throw cancelled('passkey creation was cancelled');\n const r = cred.response as AuthenticatorAttestationResponse;\n return {\n attestationObject: b64url(new Uint8Array(r.attestationObject)),\n clientDataJson: b64url(new Uint8Array(r.clientDataJSON)),\n };\n },\n async get(challenge, rpId, allowCredentials) {\n const cred = (await navigator.credentials.get({\n publicKey: {\n challenge: buf(challenge),\n rpId,\n userVerification: 'preferred',\n allowCredentials: (allowCredentials ?? []).map((id) => ({ type: 'public-key', id: buf(fromB64url(id)) })),\n },\n })) as PublicKeyCredential | null;\n if (!cred) throw cancelled('passkey sign-in was cancelled');\n const r = cred.response as AuthenticatorAssertionResponse;\n return {\n credentialId: b64url(new Uint8Array(cred.rawId)),\n authenticatorData: b64url(new Uint8Array(r.authenticatorData)),\n clientDataJson: b64url(new Uint8Array(r.clientDataJSON)),\n signature: b64url(new Uint8Array(r.signature)),\n };\n },\n };\n}\n", "/**\n * Release and upgrade approvals as core's node reports them, and the consent\n * page an app sends its user to when one is theirs to make.\n *\n * An app never approves in its own page. A passkey assertion is blind (the\n * authenticator shows a site name, never what the challenge commits to), so\n * the page that runs the ceremony decides what the person believes they\n * approve. The node therefore refuses every approval route to a session\n * opened on an app's frontend, and serves its own **consent page** instead:\n * the app asks for a request (`POST /consent/requests`), sends the person to\n * the page's `url` on the node's own origin, and reads the decision when the\n * page sends them back (`returnTo?request_id=\u2026&result=\u2026`) or from\n * `GET /consent/{id}/result`. See core's\n * [consent page](https://calimero-network.github.io/core/protocol/consent-page/)\n * and [governance](https://calimero-network.github.io/core/protocol/governance/).\n */\n\nimport { compareReleaseVersions } from '../sealed/release.js';\n\n// ---------------------------------------------------------------- governance\n\n/**\n * Who holds one decision on a cluster (core's `Authority`), fixed at genesis\n * and attested by every replica. `owner`: the parties around each app, with a\n * passkey (for release approvals the app's publisher, for upgrades whoever\n * its package's manifest names); `operator`: the operator, for every app.\n */\nexport type Authority = 'owner' | 'operator';\n\n/** Core's `Governance`: which side holds each decision on this cluster. */\nexport interface Governance {\n releases: Authority;\n appUpgrades: Authority;\n outbound: Authority;\n}\n\n/**\n * Who upgrades a package's instances, as its signed manifest declares\n * (`upgrades`; absent means `owner`), where the cluster leaves app upgrades to\n * owners. `owner`: each instance's owner (an organization's\n * `MANAGE_APPLICATION` holders); `publisher`: the `MANAGE_APPLICATION`\n * holders of the organization the package's signing key is bound to, for\n * every instance ({@link CalimeroClient.upgradePublished}). A package may move\n * from `publisher` to `owner` in a later release, never back.\n */\nexport type UpgradeAuthority = 'owner' | 'publisher';\n\n// ---------------------------------------------------------------- reports\n\n/** Whose approvals a report covers: an organization's, or the account's own apps. */\nexport type ReportScope = { kind: 'account' } | { kind: 'org'; org: string };\n\n/** A package release as a report names it. */\nexport interface ReportedRelease {\n package: string;\n version: string;\n /** The service, for a multi-service bundle (account reports only). */\n service?: string | null;\n}\n\n/** A bundle as a report names it: its digest, and its release where the reader may see it. */\nexport interface ReportedBundle {\n bundle: string;\n package?: string;\n version?: string;\n}\n\n/** Who made an upgrade, by kind. */\nexport type ActorKind = 'owner' | 'member' | 'operator';\n\n/** An app's last upgrade. `actor`, `error` and `run` are left out of the operator's report. */\nexport interface LastUpgrade {\n from: ReportedBundle;\n to: ReportedBundle;\n /** Unix seconds. */\n at: number;\n ok: boolean;\n actorKind: ActorKind;\n actor?: string;\n error?: unknown;\n run?: string;\n}\n\n/** One replica of an app: its node, the node's attested release, and whether the app's set approves it. */\nexport interface ReportedReplica {\n node: number;\n /** `null` while the node's release is not known yet (it then holds nothing). */\n release: string | null;\n approved: boolean;\n}\n\n/** One app in a report. `name`, `team` and `availableVersions` are in members' and accounts' reports only. */\nexport interface ReportedApp {\n app: string;\n group: number;\n scope: ReportScope;\n /** `hex(SHA-256)` of the WASM it runs. */\n bundle: string;\n package: ReportedRelease | null;\n /** The package's pinned signer (`did:key`). */\n publisher: { signer: string } | null;\n upgradesHeldBy: Authority;\n lastUpgrade: LastUpgrade | null;\n /** The releases approved to hold this app (its publisher's set, or its scope's); `null`: unrestricted. */\n approvedReleases: string[] | null;\n replicas: ReportedReplica[];\n name?: string;\n team?: string;\n /** Newer releases of its package it may be upgraded to, oldest first (at most 16, the newest). */\n availableVersions?: string[];\n}\n\n/** A mero-tee release the cluster's nodes run, with how many and whether the scope approved it. */\nexport interface ClusterRelease {\n release: string;\n nodes: number;\n approved: boolean;\n}\n\n/** `GET /auth/apps` or `GET /orgs/{org}/apps`: one page. */\nexport interface AppsReport {\n scope: ReportScope;\n governance: Governance;\n /** The scope's own approved set, newest last; `null`: none ever recorded (unrestricted). */\n approvedReleases: string[] | null;\n clusterReleases: ClusterRelease[];\n apps: ReportedApp[];\n /** Pass as `after` for the next page; `null` on the last. */\n next: string | null;\n}\n\n/** `GET /ops/apps`: one page, for the operator. */\nexport interface OpsAppsReport {\n /** This node had caught up with the system leader. */\n fresh: boolean;\n governance: Governance;\n apps: ReportedApp[];\n next: string | null;\n}\n\n/** `GET /ops/orgs`: one page, for the operator. */\nexport interface OpsOrgsReport {\n fresh: boolean;\n governance: Governance;\n orgs: Array<{ org: string; approvedReleases: string[] | null }>;\n next: string | null;\n}\n\n/** A page of a report: entries after the id `after`, at most `limit` (1 to {@link MAX_REPORT_PAGE}). */\nexport interface PageOptions {\n after?: string;\n limit?: number;\n}\n\n/** The most entries one page of a report answers (core's `MAX_REPORT_PAGE`). */\nexport const MAX_REPORT_PAGE = 100;\n\n/** `?after=&limit=` for a report route; `limit` outside 1 to 100 is refused before sending. */\nexport function pageQuery(page: PageOptions = {}): string {\n const q = new URLSearchParams();\n if (page.after !== undefined) q.set('after', page.after);\n if (page.limit !== undefined) {\n if (!Number.isInteger(page.limit) || page.limit < 1 || page.limit > MAX_REPORT_PAGE) {\n throw new RangeError(`limit is 1 to ${MAX_REPORT_PAGE}`);\n }\n q.set('limit', String(page.limit));\n }\n const s = q.toString();\n return s ? `?${s}` : '';\n}\n\n// ---------------------------------------------------------------- deadlines\n\n/** A release's end-of-new-work deadline. */\nexport interface ReleaseDeadline {\n version: string;\n /** RFC 3339. */\n after: string;\n /** Unix seconds. */\n afterSecs: number;\n}\n\n/** `GET /releases`: the cluster's release rules, public inside the sealed channel. */\nexport interface ReleaseRules {\n governance: Governance;\n /** Oldest release first. */\n deadlines: ReleaseDeadline[];\n}\n\n/** Semver order (core's `compare_versions`); text order for versions that are not semver. */\nexport function compareVersions(a: string, b: string): number {\n try {\n return compareReleaseVersions(a, b);\n } catch {\n return a < b ? -1 : a > b ? 1 : 0;\n }\n}\n\n/**\n * Whether a scope whose approved set is `approved` has lost new work at `now`\n * (Unix seconds), as core's `SystemState::stalled` judges it: a release's\n * deadline has passed and the newest approved release is older. Names the\n * newest such release, since approving it lifts every one. `null` approved\n * (unrestricted) is never stalled.\n */\nexport function stalledBy(\n approved: string[] | null,\n deadlines: ReleaseDeadline[],\n now: number = Date.now() / 1000,\n): ReleaseDeadline | null {\n if (approved === null || approved.length === 0) return null;\n const newest = approved.reduce((a, b) => (compareVersions(a, b) >= 0 ? a : b));\n let stall: ReleaseDeadline | null = null;\n for (const d of deadlines) {\n if (d.afterSecs <= now && compareVersions(newest, d.version) < 0) {\n if (stall === null || compareVersions(d.version, stall.version) > 0) stall = d;\n }\n }\n return stall;\n}\n\n// ---------------------------------------------------------------- publishers\n\n/** `GET /publishers/{signerId}`: what a key signs to bind it here next. */\nexport interface PublisherBindingInfo {\n signerId: string;\n /** The cluster's name, as the binding message names it. */\n cluster: string;\n /** How many bindings the key has had here: a signature binds once. */\n generation: number;\n bound: boolean;\n}\n\n/**\n * The text a package signing key signs to bind it to `org` as its publisher\n * (core's `system::publisher_binding_message`). Take `cluster` and\n * `generation` from {@link CalimeroClient.publisherBinding}; sign the UTF-8\n * bytes with the key's Ed25519 secret and send\n * {@link CalimeroClient.bindPublisher}.\n */\nexport function publisherBindingMessage(cluster: string, org: string, signerId: string, generation: number): string {\n return `calimero-publisher-binding/v1\\n${cluster}\\n${org}\\n${signerId}\\n${generation}`;\n}\n\n/** {@link publisherBindingMessage} as the bytes to sign. */\nexport function publisherBindingBytes(cluster: string, org: string, signerId: string, generation: number): Uint8Array {\n return new TextEncoder().encode(publisherBindingMessage(cluster, org, signerId, generation));\n}\n\n/** `POST /orgs/{org}/publishers`: the key's proof, base64url without padding. */\nexport interface PublisherProof {\n signerId: string;\n /** The Ed25519 public key the `did:key` names. */\n publicKey: string;\n /** Its signature over {@link publisherBindingMessage}. */\n signature: string;\n}\n\n// ---------------------------------------------------------------- consent page\n\n/** Whose approval a release or outbound request is for. */\nexport type ConsentScope = 'account' | { org: string };\n\n/** What the app asks its user to approve (`POST /consent/requests`). Unknown fields are refused. */\nexport type ConsentRequest =\n | {\n kind: 'release';\n scope: ConsentScope;\n /** `withdraw: true` asks to withdraw the release's approval instead of approving it. */\n subject: { version: string; withdraw?: boolean };\n /** Where the page sends the person back: the package's frontend origin, or one its manifest names. */\n returnTo: string;\n }\n | {\n kind: 'upgrade';\n subject: { app: string; toVersion: string };\n returnTo: string;\n }\n | {\n kind: 'outbound';\n scope: ConsentScope;\n /** `package`: a package-bound session's own when left out; `prefixes`: every one the latest release declares. */\n subject: { package?: string; prefixes?: string[] };\n returnTo: string;\n };\n\n/** The node's answer to a consent request: send the person to `url`. */\nexport interface ConsentStarted {\n requestId: string;\n /** The consent page, on the node's own origin. */\n url: string;\n /** Unix seconds; a request lives 10 minutes. */\n expiresAt: number;\n /**\n * The confirmation code the consent page shows, `XXX-XXX`\n * ({@link confirmationCode} of `requestId`). Show it to the person before\n * sending them to `url`: the page they land on should show the same code,\n * which tells them it is the page their request opened. Not a secret.\n * Nodes older than the code leave it out.\n */\n code?: string;\n}\n\n/** How {@link CalimeroClient.openConsentPage} sends the person to the page. */\nexport interface OpenConsentOptions {\n /** Sends the browser to the page's `url`; by default `window.location.assign`. */\n navigate?: (url: string) => void;\n /**\n * Runs after the node answers and before navigating, with the answer: show\n * the person `started.code` here so they can check the page shows the same.\n * Answer `false` and the page is not opened (the request stays on the node\n * until it expires).\n */\n confirm?: (started: ConsentStarted) => boolean | Promise<boolean>;\n}\n\nconst CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\n\n/**\n * The confirmation code the node's consent page shows for `requestId`: the\n * first 30 bits of SHA-256 of its UTF-8 bytes, big-endian, as six Crockford\n * base32 characters written `XXX-XXX` (core's consent page). Compare it with\n * {@link ConsentStarted.code} to check the node's answer.\n */\nexport async function confirmationCode(requestId: string): Promise<string> {\n const h = new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(requestId)));\n const word = ((h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3]) >>> 0;\n let code = '';\n for (let i = 0; i < 6; i++) {\n if (i === 3) code += '-';\n code += CROCKFORD[(word >>> (27 - 5 * i)) & 31];\n }\n return code;\n}\n\nexport type ConsentStatus = 'pending' | 'approved' | 'declined';\n\n/** `GET /consent/{id}/result`. */\nexport interface ConsentResult {\n requestId: string;\n kind: ConsentRequest['kind'];\n status: ConsentStatus;\n /** Unix seconds, once decided. */\n decidedAt: number | null;\n}\n\n/**\n * What the consent page put on `returnTo` when it sent the person back, or\n * `null` when `href` carries none. A hint only (anyone can type a URL): confirm\n * with {@link CalimeroClient.consentResult} before acting on it.\n */\nexport function consentReturn(href: string | URL): { requestId: string; result: 'approved' | 'declined' } | null {\n const url = typeof href === 'string' ? new URL(href) : href;\n const requestId = url.searchParams.get('request_id');\n const result = url.searchParams.get('result');\n if (!requestId || (result !== 'approved' && result !== 'declined')) return null;\n return { requestId, result };\n}\n\n// ---------------------------------------------------------------- pending\n\n/** The public verifier for mero-tee releases (`attestation-verifier`). */\nexport const RELEASE_VERIFIER = 'https://mero-tee.vercel.app';\n\n/** A mero-tee release's notes on GitHub. */\nexport function releaseNotesUrl(version: string): string {\n return `https://github.com/calimero-network/mero-tee/releases/tag/mero-tee-v${encodeURIComponent(version)}`;\n}\n\n/** The public verifier's page for a mero-tee release. */\nexport function verifyReleaseUrl(version: string): string {\n return `${RELEASE_VERIFIER}/mero-tee?release_tag=${encodeURIComponent(`mero-tee-v${version}`)}`;\n}\n\n/** A mero-tee release the cluster's nodes run that the scope has not approved. */\nexport interface PendingRelease {\n version: string;\n /** How many of the cluster's nodes run it. */\n nodes: number;\n /** Whether the scope's side holds release approvals (else the operator does). */\n actionable: boolean;\n releaseNotesUrl: string;\n verifyUrl: string;\n /** Its deadline, when it carries one. */\n deadline: ReleaseDeadline | null;\n}\n\n/** An app with newer releases of its package. */\nexport interface PendingUpgrade {\n app: string;\n name: string | null;\n package: string;\n from: string;\n /** The newest it may move to. */\n to: string;\n /** Every newer release it may move to, oldest first. */\n available: string[];\n /** Whether owners hold app upgrades on this cluster; the node checks the package's own `upgrades` when asked. */\n actionable: boolean;\n}\n\n/** What {@link CalimeroClient.pendingApprovals} answers. */\nexport interface PendingApprovals {\n scope: ReportScope;\n governance: Governance;\n approvedReleases: string[] | null;\n releases: PendingRelease[];\n upgrades: PendingUpgrade[];\n /** A passed deadline has stopped new work for the scope: approve `stalledBy.version` (or newer) to lift it. */\n stalledBy: ReleaseDeadline | null;\n /** Whether anything here is the user's to approve. */\n actionable: boolean;\n}\n\n/**\n * The pending list from a scope's report pages (every page's apps\n * concatenated into `report.apps`) and the cluster's release rules.\n */\nexport function pendingApprovalsFrom(report: AppsReport, rules: ReleaseRules, now: number = Date.now() / 1000): PendingApprovals {\n const deadlineOf = (v: string) => rules.deadlines.find((d) => d.version === v) ?? null;\n const releasesActionable = report.governance.releases === 'owner';\n const upgradesActionable = report.governance.appUpgrades === 'owner';\n const releases: PendingRelease[] = report.clusterReleases\n .filter((r) => !r.approved)\n .sort((a, b) => compareVersions(b.release, a.release))\n .map((r) => ({\n version: r.release,\n nodes: r.nodes,\n actionable: releasesActionable,\n releaseNotesUrl: releaseNotesUrl(r.release),\n verifyUrl: verifyReleaseUrl(r.release),\n deadline: deadlineOf(r.release),\n }));\n const upgrades: PendingUpgrade[] = [];\n for (const a of report.apps) {\n const available = a.availableVersions ?? [];\n if (a.package === null || available.length === 0) continue;\n upgrades.push({\n app: a.app,\n name: a.name ?? null,\n package: a.package.package,\n from: a.package.version,\n to: available[available.length - 1],\n available,\n actionable: upgradesActionable,\n });\n }\n return {\n scope: report.scope,\n governance: report.governance,\n approvedReleases: report.approvedReleases,\n releases,\n upgrades,\n stalledBy: stalledBy(report.approvedReleases, rules.deadlines, now),\n actionable: releases.some((r) => r.actionable) || upgrades.some((u) => u.actionable),\n };\n}\n\n/**\n * The consent request that approves `version` for `scope`, or with\n * `{ withdraw: true }` withdraws its approval ({@link withdrawConsent}).\n */\nexport function releaseConsent(\n scope: ReportScope,\n version: string,\n returnTo: string,\n options: { withdraw?: boolean } = {},\n): ConsentRequest {\n return {\n kind: 'release',\n scope: scope.kind === 'org' ? { org: scope.org } : 'account',\n subject: options.withdraw ? { version, withdraw: true } : { version },\n returnTo,\n };\n}\n\n/**\n * The consent request that withdraws `version`'s approval for `scope`: nodes\n * on it are then sent none of the scope's apps' data (nothing already there\n * moves). The page fetches no measurements for it. Withdrawing the scope's\n * last approved release is refused on the page (`400 REJECTED`, the request\n * stays pending), and the page warns before.\n */\nexport function withdrawConsent(scope: ReportScope, version: string, returnTo: string): ConsentRequest {\n return releaseConsent(scope, version, returnTo, { withdraw: true });\n}\n\n/**\n * The `release` part of a release request's model, as the consent page reads\n * it (`GET /consent/{id}/model`, on the node's origin; the app never needs\n * it). An approval carries the release's signed measurements; a withdrawal\n * carries none, and says whether the release is approved now and whether it\n * is the scope's last approved release (which cannot be withdrawn).\n */\nexport type ConsentReleaseModel =\n | {\n version: string;\n change: 'approve';\n alreadyApproved: boolean;\n approved: unknown;\n nodes: unknown;\n profile: string | null;\n measurements: Record<string, unknown>;\n }\n | {\n version: string;\n change: 'withdraw';\n currentlyApproved: boolean;\n lastApproved: boolean;\n approved: unknown;\n nodes: unknown;\n profile: string | null;\n };\n\n/** The consent request that upgrades `app` to `toVersion`. */\nexport function upgradeConsent(app: string, toVersion: string, returnTo: string): ConsentRequest {\n return { kind: 'upgrade', subject: { app, toVersion }, returnTo };\n}\n", "/**\n * Client for Calimero 1.0, the confidential cloud: one app = one replicated log on\n * attested nodes; this client verifies the node, seals every request to it,\n * signs people in with passkeys and machines with API keys.\n *\n * ```ts\n * const cloud = new CalimeroClient({ baseUrl, policy: { release: { minReleaseVersion: '2.3.109' } } });\n * await cloud.signIn(browserPasskey());\n * const { result } = await cloud.call(appId, 'set', { key: 'a', value: '1' });\n * ```\n */\n\nimport { SealedTransportError, createSealedFetch } from '../sealed/sealed.js';\nimport { fetchAttestedKey, type AttestationDoc, type CloudPolicy } from './attestation.js';\nimport { DEFAULT_DIRECTORY, orderNodes, readDirectory } from './directory.js';\nimport {\n CalimeroError,\n ConfirmCancelled,\n ConfirmRequired,\n LoginRequired,\n UnavailableError,\n WrongNode,\n errorFrom,\n} from './errors.js';\nimport { b64url, fromB64url, type PasskeyProvider } from './passkey.js';\nimport {\n confirmationCode,\n pageQuery,\n pendingApprovalsFrom,\n type AppsReport,\n type ConsentRequest,\n type ConsentResult,\n type ConsentStarted,\n type OpenConsentOptions,\n type OpsAppsReport,\n type OpsOrgsReport,\n type PageOptions,\n type PendingApprovals,\n type PublisherBindingInfo,\n type PublisherProof,\n type ReleaseRules,\n type ReportedApp,\n} from './approvals.js';\n\nexport {\n AppError,\n ArgsTooLarge,\n CalimeroError,\n ConfirmCancelled,\n ConfirmRequired,\n IdempotencyMismatch,\n LoginRequired,\n ConsentStale,\n NotFound,\n ReleaseDeadlineError,\n TrapError,\n UnavailableError,\n WrongNode,\n errorFrom,\n} from './errors.js';\nexport type { Committed } from './errors.js';\n\nexport interface CalimeroSession {\n accountId: string;\n sessionToken: string;\n expiresAt: number;\n refreshToken: string;\n}\n\nexport interface CallResult {\n index: number;\n result: unknown;\n events: Array<{ kind: string; data: unknown }>;\n}\n\nexport interface ViewResult {\n index: number;\n result: unknown;\n}\n\nexport interface CloudEvent {\n id: string;\n kind: string;\n data: unknown;\n}\n\n/** What installing a package release answers. */\nexport interface PackageInstalled {\n package: string;\n version: string;\n signerId: string;\n /** Service name (`''` for a single-service bundle) -> the bundle hash it runs as. */\n services: Record<string, string>;\n}\n\n/** An installed package and its releases. */\nexport interface PackageInfo {\n package: string;\n signerId: string;\n owner: string;\n latest: string | null;\n versions: Array<{\n version: string;\n mpk: string;\n size: number;\n source: 'registry' | 'upload';\n services: Record<string, string>;\n metadata: unknown;\n outbound: string[];\n installedBy: string;\n installedAt: number;\n }>;\n}\n\n/** One app instance as `listApps` answers it. */\nexport interface AppInfo {\n appId: string;\n name: string;\n owner: string;\n org: string | null;\n bundle: string;\n package: string | null;\n version: string | null;\n}\n\n/**\n * An organization-wide upgrade run, as `upgradeOrg`, `upgradeRun` and\n * `retryUpgradeRun` answer it (core's `UpgradeRun`).\n */\nexport interface UpgradeRun {\n runId: string;\n package: string;\n version: string;\n team?: string;\n cascade: boolean;\n /** The account that started it, or `operator`. */\n by: string;\n startedAt: number;\n apps: string[];\n done: string[];\n /** App id -> why its upgrade failed. */\n failed: Record<string, unknown>;\n finished: boolean;\n}\n\n/** One of an app's blobs: `blobId` base58 (what apps print), `id` hex. */\nexport interface BlobInfo {\n blobId: string;\n id: string;\n size: number;\n}\n\n/** One device present in an app (`publishPresence`); `state` hex, `null` once retracted. */\nexport interface PresenceEntry {\n account: string;\n device: string;\n state: string | null;\n}\n\n/** What an organization-wide upgrade targets. */\nexport interface OrgUpgradeTarget {\n package: string;\n version: string;\n /** Only this team's apps (and, with `cascade`, those of the teams below it). */\n team?: string;\n cascade?: boolean;\n migrate?: string;\n}\n\n/**\n * `GET /orgs/{org}`: the organization as the caller sees it. Besides its\n * members, teams and metadata, who may approve its releases, the package\n * signing keys it publishes, and whether a passed release deadline has\n * stopped new work on its own set.\n */\nexport interface OrgInfo extends Record<string, unknown> {\n /** Accounts holding `APPROVE_RELEASES` there (owner and admins included). */\n releaseApprovers: string[];\n /** The signer ids (`did:key`) bound to it as publisher. */\n publishes: string[];\n /** `null` unless a deadline stopped new work: approve `release` (or newer) to lift it. */\n newWorkStopped: { release: string; after: string } | null;\n}\n\n/** One URL path segment, so an id cannot reach another route. */\nfunction seg(value: string): string {\n return encodeURIComponent(value);\n}\n\n/**\n * The node refuses an envelope past its 64 MiB sealed cap with `413` in the\n * clear, before opening it, so the refusal arrives as the transport's. To the\n * caller it is the API's `TOO_LARGE`, as the Rust client reports it.\n */\nfunction sealedError(error: unknown): unknown {\n if (error instanceof SealedTransportError && error.status === 413) {\n return errorFrom(413, {\n error: 'TOO_LARGE',\n message: error.message.replace(/^Sealed request refused: /, ''),\n });\n }\n return error;\n}\n\n/** Read a refused response's body and map it ({@link errorFrom}). */\nasync function refusal(response: Response): Promise<CalimeroError> {\n const text = await response.text().catch(() => '');\n let body: unknown = {};\n try {\n body = text ? JSON.parse(text) : {};\n } catch {\n body = { message: text };\n }\n return errorFrom(response.status, body, response.headers.get('retry-after'));\n}\n\n/** Server-sent event frames from a response body: `{ id, kind, data }` each, `data` parsed as JSON when it is. */\nasync function* sseFrames(body: ReadableStream<Uint8Array>): AsyncGenerator<CloudEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n for (;;) {\n const { value, done } = await reader.read();\n if (done) return;\n buffer += decoder.decode(value, { stream: true });\n let cut: number;\n while ((cut = buffer.indexOf('\\n\\n')) >= 0) {\n const frame = buffer.slice(0, cut);\n buffer = buffer.slice(cut + 2);\n let id = '';\n let kind = '';\n let data = '';\n for (const line of frame.split('\\n')) {\n if (line.startsWith('id:')) id = line.slice(3).trim();\n else if (line.startsWith('event:')) kind = line.slice(6).trim();\n else if (line.startsWith('data:')) data += line.slice(5).trim();\n }\n if (!kind && !data) continue;\n let parsed: unknown = data;\n try {\n parsed = JSON.parse(data);\n } catch {\n /* plain text */\n }\n yield { id, kind, data: parsed };\n }\n }\n}\n\n/** Bytes as lower-case hex. */\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * A key for a call the caller gave none, made once so every retry shares it:\n * `node:c-` and 16 random bytes in base64url without padding, as the Rust\n * client mints it. It only has to outlive this client's own retries, so it\n * takes the node's short-lived class: a key starting `node:` is kept 10\n * minutes, a caller's own key 24 hours.\n * `getRandomValues`, not `randomUUID`, which a page outside a secure context lacks.\n */\nfunction newIdempotencyKey(): string {\n return `node:c-${b64url(crypto.getRandomValues(new Uint8Array(16)))}`;\n}\n\n/**\n * How a call or a view is sent again while the node is unavailable (D70): with\n * the same key, after a backoff that starts at `baseDelayMs` and doubles up to\n * `maxDelayMs`, no jitter, at most `retries` times. The defaults are the Rust\n * client's: 6 retries, 200 ms doubling, at most 2 s (about 9 s in all, past a\n * leader election).\n */\nexport interface CloudRetryOptions {\n /** Retries after the first attempt. Default 6. */\n retries?: number;\n /** The first backoff; each retry doubles it. Default 200 ms. */\n baseDelayMs?: number;\n /** The longest backoff. Default 2 s. */\n maxDelayMs?: number;\n}\n\nexport const DEFAULT_RETRY = { retries: 6, baseDelayMs: 200, maxDelayMs: 2000 } as const;\n\n/** The backoff before retry `retry` (0 for the first): `baseDelayMs` doubling, at most `maxDelayMs`. */\nexport function retryDelayMs(retry: number, options: { baseDelayMs: number; maxDelayMs: number }): number {\n return Math.min(options.baseDelayMs * 2 ** retry, options.maxDelayMs);\n}\n\nexport interface CalimeroClientOptions {\n /** One node of the cluster: the one the client talks to first. */\n baseUrl: string;\n /**\n * Other nodes of the same cluster, in the order to move to them when a node\n * answers `421 WRONG_NODE` (its release may not serve this account), or stays\n * unavailable to a call or a view through all its retries. Each is attested\n * under the same `policy` before anything is sent to it. Without them a `421`\n * reaches the caller as {@link WrongNode}.\n */\n nodes?: string[];\n policy: CloudPolicy;\n /** Fetch that carries attestation and envelopes. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /** How calls and views retry a 503 or a failed connection. */\n retry?: CloudRetryOptions;\n}\n\n/** How {@link CalimeroClient.connect} reaches a Calimero Cloud cluster by name. */\nexport interface CalimeroConnectOptions {\n /** The cluster's name, e.g. `eu-shared-1`. */\n cluster: string;\n /** What every node must attest to before anything is sent to it. */\n policy: CloudPolicy;\n /** The node directory to ask. Default {@link DEFAULT_DIRECTORY}. */\n directory?: string;\n /** Try the nodes in this zone (e.g. `europe-west4-a`) first. */\n zone?: string;\n /** Fetch for the directory, attestation and envelopes. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /** How calls and views retry a 503 or a failed connection. */\n retry?: CloudRetryOptions;\n /** Randomness for the weighted node order, in [0, 1). Defaults to `Math.random`. */\n random?: () => number;\n}\n\n/** Where a client made by {@link CalimeroClient.connect} re-reads its node list. */\ninterface DirectorySource {\n directory: string;\n cluster: string;\n zone: string | undefined;\n random: () => number;\n /** When the listing is due to be read again (ms since the epoch). */\n due: number;\n /** The re-read under way, if any. */\n reading?: Promise<void>;\n}\n\n/**\n * The ceremonies that mint a session, which {@link CalimeroClient.send} never\n * repeats by itself: a sign-in or sign-up is started again by its caller (with\n * the passkey), and a refresh moves through the nodes in\n * {@link CalimeroClient.exchangeRefresh}. A node answers them `421 WRONG_NODE`\n * before it spends the challenge or the refresh token (core #4774).\n */\nfunction ceremony(path: string): boolean {\n return path === 'auth/refresh' || path.startsWith('auth/passkey/');\n}\n\nexport class CalimeroClient {\n /** Every node this client may use, `baseUrl` first (or as the directory last ordered them). */\n private nodeUrls: string[];\n /** The one in use: an index into {@link nodeUrls}. */\n private at = 0;\n /** A sealed fetch per node, each attesting its own node on first use. */\n private readonly channels = new Map<string, typeof fetch>();\n private readonly policy: CloudPolicy;\n /** The unsealed fetch, for the one route served in the clear (`/attestation`). */\n private readonly raw: typeof fetch;\n private auth: string | undefined;\n private current: CalimeroSession | undefined;\n /** The refresh under way, which every request that needs one shares. */\n private refreshing: Promise<CalimeroSession> | undefined;\n private readonly retry: Required<CloudRetryOptions>;\n /** Rejections of the underlying `fetch` itself: the node could not be reached or dropped the connection. */\n private readonly networkFailures = new WeakSet<object>();\n /** The directory the node list came from, for a client made by {@link connect}. */\n private source: DirectorySource | undefined;\n\n /**\n * A client for the Calimero Cloud cluster named `cluster`: its node list read\n * from the public node directory, those in `zone` first, each group in\n * weighted-random order. The directory only picks which nodes to try: each is\n * attested under `policy` before anything is sent to it. Throws\n * {@link DirectoryError} when the directory names no usable node.\n *\n * The list is read again in the background after a failover, and at the\n * first request once the directory's `refreshAfterSeconds` has passed.\n */\n static async connect(options: CalimeroConnectOptions): Promise<CalimeroClient> {\n const directory = options.directory ?? DEFAULT_DIRECTORY;\n const random = options.random ?? Math.random;\n const fetcher = options.fetch ?? ((input, init) => fetch(input, init));\n const listing = await readDirectory(directory, options.cluster, fetcher);\n const [baseUrl, ...nodes] = orderNodes(listing.nodes, options.zone, random);\n const client = new CalimeroClient({ baseUrl, nodes, policy: options.policy, fetch: options.fetch, retry: options.retry });\n client.source = {\n directory,\n cluster: options.cluster,\n zone: options.zone,\n random,\n due: Date.now() + listing.refreshAfterSeconds * 1000,\n };\n return client;\n }\n\n constructor(options: CalimeroClientOptions) {\n const trim = (url: string) => url.replace(/\\/+$/, '');\n this.nodeUrls = [...new Set([options.baseUrl, ...(options.nodes ?? [])].map(trim))];\n this.policy = options.policy;\n this.retry = { ...DEFAULT_RETRY, ...options.retry };\n const given = options.fetch ?? ((input, init) => fetch(input, init));\n // `fetch` rejects with a `TypeError` when it gets no answer: the connection\n // was refused, reset or dropped before the response. The sealed fetch passes\n // that rejection on unchanged, so it is recognised here, at its source, and\n // not by its type alone (a bad URL is a `TypeError` too, and is not retried).\n const raw: typeof fetch = async (input, init) => {\n try {\n return await given(input, init);\n } catch (error) {\n if (error instanceof TypeError) this.networkFailures.add(error);\n throw error;\n }\n };\n this.raw = raw;\n }\n\n /** The node requests go to now: `baseUrl`, until a `421 WRONG_NODE` or a failover moved the client on. */\n get nodeUrl(): string {\n return this.nodeUrls[this.at];\n }\n\n /** Every node this client may use, in the order it moves through them. */\n get nodes(): string[] {\n return [...this.nodeUrls];\n }\n\n /** The sealed channel to `url`, attested under the client's policy before its first request. */\n private channel(url: string): typeof fetch {\n let sealed = this.channels.get(url);\n if (!sealed) {\n sealed = createSealedFetch({\n baseUrl: url,\n transportPublicKey: () => fetchAttestedKey(url, this.policy, this.raw),\n fetch: this.raw,\n });\n this.channels.set(url, sealed);\n }\n return sealed;\n }\n\n /**\n * Move on from node `from` (the one that answered `421 WRONG_NODE`) to the\n * next one. False when there is no other. A request that saw the same node\n * refuse after another request moved on already does not move again.\n */\n private moveOn(from: string): boolean {\n if (this.nodeUrls.length < 2) return false;\n if (this.nodeUrl === from) this.at = (this.at + 1) % this.nodeUrls.length;\n return true;\n }\n\n /**\n * Fail over from node `from`, where a request's retries ran out, to the next\n * node it has not `tried`. False when it has tried them all. A request whose\n * node another request moved away from already goes to that node, if untried.\n */\n private failOver(from: string, tried: Set<string>): boolean {\n if (this.nodeUrl !== from && !tried.has(this.nodeUrl)) return true;\n const count = this.nodeUrls.length;\n for (let step = 1; step < count; step++) {\n const next = (this.at + step) % count;\n if (!tried.has(this.nodeUrls[next])) {\n this.at = next;\n this.reread();\n return true;\n }\n }\n return false;\n }\n\n /**\n * Read the node list again from the directory, in the background, for a\n * client made by {@link connect}: the node in use stays first, then the\n * directory's order; a node no longer listed is dropped. A failed read is\n * ignored. One read at a time.\n */\n private reread(): void {\n const source = this.source;\n if (!source || source.reading) return;\n source.reading = readDirectory(source.directory, source.cluster, this.raw)\n .then((listing) => {\n const current = this.nodeUrl;\n const listed = orderNodes(listing.nodes, source.zone, source.random);\n this.nodeUrls = [current, ...listed.filter((url) => url !== current)];\n this.at = 0;\n source.due = Date.now() + listing.refreshAfterSeconds * 1000;\n })\n .catch(() => undefined)\n .finally(() => {\n source.reading = undefined;\n });\n }\n\n /** Authenticate every request with an API key. */\n useApiKey(key: string): void {\n this.auth = key;\n this.current = undefined;\n }\n\n useSession(session: CalimeroSession): void {\n this.auth = session.sessionToken;\n this.current = session;\n }\n\n get session(): CalimeroSession | undefined {\n return this.current;\n }\n\n /**\n * Send one request to the node in use, with the credential held now, and\n * answer the response, whatever its status. {@link send} judges it.\n */\n private async request(\n method: string,\n path: string,\n body?: unknown,\n raw?: Uint8Array,\n contentType = 'application/wasm',\n signal?: AbortSignal,\n ): Promise<Response> {\n const headers: Record<string, string> = {};\n if (this.auth) headers.authorization = `Bearer ${this.auth}`;\n let payload: BodyInit | undefined;\n if (raw) {\n headers['content-type'] = contentType;\n payload = raw as unknown as BodyInit;\n } else if (body !== undefined) {\n headers['content-type'] = 'application/json';\n payload = JSON.stringify(body);\n }\n if (this.source && Date.now() >= this.source.due) this.reread();\n const url = this.nodeUrl;\n try {\n return await this.channel(url)(`${url}/${path}`, { method, headers, body: payload, signal });\n } catch (error) {\n throw sealedError(error);\n }\n }\n\n /**\n * {@link request}, answering what a lost issuing node or a node on the\n * wrong release does to a session: a successful response, or the refusal as a\n * typed error ({@link errorFrom}).\n *\n * - `401 UNAUTHENTICATED` to a request that carried a session: the node that\n * signed the session may be gone, replaced, or out of reach of the node\n * asked, which any node of the cluster answers with a refresh. The client\n * refreshes once, shared by every request that needs it at the same time\n * ({@link refresh}), and repeats the request once. A refresh that is\n * refused surfaces as {@link LoginRequired}.\n * - `421 WRONG_NODE`: this node's release may not serve the account. The\n * client moves to the next node it knows and repeats the request once; with\n * none, the {@link WrongNode} reaches the caller.\n *\n * Repeating is safe even for a request that is not idempotent: the node\n * answers `401` and `421` when it judges the credential, before it reads what\n * the request asks, so the first attempt ran nothing. The exceptions are the\n * ceremonies that mint a session ({@link ceremony}), never repeated here.\n */\n private async send(\n method: string,\n path: string,\n body?: unknown,\n raw?: Uint8Array,\n contentType?: string,\n signal?: AbortSignal,\n ): Promise<Response> {\n let refreshed = false;\n let moved = false;\n for (;;) {\n const [token, at] = [this.auth, this.nodeUrl];\n const response = await this.request(method, path, body, raw, contentType, signal);\n if (response.ok) return response;\n const error = await refusal(response);\n if (error instanceof WrongNode && !moved) {\n moved = true;\n if (this.moveOn(at) && !ceremony(path)) continue;\n } else if (error instanceof LoginRequired && !refreshed && this.mayRefresh(token, path)) {\n refreshed = true;\n await this.renew(token as string);\n continue;\n }\n throw error;\n }\n }\n\n /** Whether a `401` to a request sent with `token` is one a refresh may answer. */\n private mayRefresh(token: string | undefined, path: string): boolean {\n return token !== undefined && this.current !== undefined && !ceremony(path);\n }\n\n /**\n * A fresh session in place of the one `token` belonged to: by the refresh\n * another request already made, or by one this request starts.\n */\n private async renew(token: string): Promise<void> {\n if (this.auth !== token) return;\n await this.refresh();\n }\n\n private async json<T>(\n method: string,\n path: string,\n body?: unknown,\n raw?: Uint8Array,\n contentType?: string,\n ): Promise<T> {\n const response = await this.send(method, path, body, raw, contentType);\n const text = await response.text();\n return (text ? JSON.parse(text) : {}) as T;\n }\n\n /**\n * {@link json} for a call or a view (D70): while the node answers 503 or\n * cannot be reached, the same request, with the same idempotency key, is sent\n * again after {@link retryDelayMs} (or the pause the node asked for, if\n * longer), at most `retries` times. Every other answer is final.\n *\n * When a node's retries run out, the request fails over to the next node the\n * client knows and its retries start again there, with the same key: the\n * key is kept in the app's replicated log, so the cluster answers it once\n * whichever node it reaches. Each node is tried once per request. The last\n * failure surfaces as {@link UnavailableError}: the node's 503, or reason\n * `network` for a connection that failed, whose `committed` is `'unknown'`.\n *\n * `once` sends the request exactly once, to the node in use (the confirmed\n * attempt of {@link callConfirmed}, whose challenge is single-use).\n */\n private async retried<T>(method: string, path: string, body: Record<string, unknown>, once = false): Promise<T> {\n const retries = once ? 0 : this.retry.retries;\n const tried = new Set<string>();\n for (;;) {\n let unavailable: UnavailableError | undefined;\n let node = this.nodeUrl;\n for (let attempt = 0; ; attempt++) {\n node = this.nodeUrl;\n tried.add(node);\n try {\n return await this.json<T>(method, path, body);\n } catch (error) {\n if (error instanceof UnavailableError) unavailable = error;\n else if (error instanceof TypeError && this.networkFailures.has(error)) {\n unavailable = new UnavailableError('NETWORK', `the node could not be reached: ${error.message}`, {}, undefined, error);\n } else throw error;\n }\n if (attempt >= retries) break;\n const backoff = retryDelayMs(attempt, this.retry);\n await new Promise((resolve) => setTimeout(resolve, Math.max(backoff, (unavailable.retryAfter ?? 0) * 1000)));\n }\n if (once || !this.failOver(node, tried)) throw unavailable;\n }\n }\n\n post<T = Record<string, unknown>>(path: string, body: unknown = {}): Promise<T> {\n return this.json<T>('POST', path, body);\n }\n\n get<T = Record<string, unknown>>(path: string): Promise<T> {\n return this.json<T>('GET', path);\n }\n\n put<T = Record<string, unknown>>(path: string, body: unknown = {}): Promise<T> {\n return this.json<T>('PUT', path, body);\n }\n\n delete<T = Record<string, unknown>>(path: string, body?: unknown): Promise<T> {\n return this.json<T>('DELETE', path, body);\n }\n\n // ---------------------------------------------------------------- identity\n\n /** Create an account with a new passkey, and sign in. */\n async signUp(passkey: PasskeyProvider, name: string): Promise<CalimeroSession> {\n const begin = await this.post<{ challengeId: string; options: Record<string, unknown> }>(\n 'auth/passkey/register/begin',\n { name },\n );\n const registration = await passkey.create(begin.options);\n const session = await this.post<CalimeroSession>('auth/passkey/register/finish', {\n challengeId: begin.challengeId,\n registration,\n });\n this.useSession(session);\n return session;\n }\n\n /** Sign in with an existing passkey. */\n async signIn(passkey: PasskeyProvider): Promise<CalimeroSession> {\n const begin = await this.post<{ challengeId: string; options: { challenge: string; rpId: string } }>(\n 'auth/passkey/login/begin',\n );\n const assertion = await passkey.get(fromB64url(begin.options.challenge), begin.options.rpId);\n const session = await this.post<CalimeroSession>('auth/passkey/login/finish', {\n challengeId: begin.challengeId,\n assertion,\n });\n this.useSession(session);\n return session;\n }\n\n /**\n * Swap the refresh token for a new session, on whichever node the client\n * uses: any node of the cluster takes it. A refresh token is used once, so\n * calls made while one refresh is under way share it rather than sending the\n * same token again (which would revoke the session).\n */\n refresh(): Promise<CalimeroSession> {\n if (!this.refreshing) {\n const pending = this.exchangeRefresh();\n this.refreshing = pending;\n const clear = () => {\n if (this.refreshing === pending) this.refreshing = undefined;\n };\n pending.then(clear, clear);\n }\n return this.refreshing;\n }\n\n private async exchangeRefresh(): Promise<CalimeroSession> {\n const current = this.current;\n if (!current) throw new Error('no session to refresh');\n let session: CalimeroSession | undefined;\n // A node that may not serve the account answers `421 WRONG_NODE` before it\n // spends the refresh token (core #4774), so the same token goes to the next\n // node (`send` moved there already): once per node, at most.\n for (let tried = 1; session === undefined; tried++) {\n try {\n session = await this.post<CalimeroSession>('auth/refresh', { refreshToken: current.refreshToken });\n } catch (error) {\n if (!(error instanceof WrongNode) || tried >= this.nodeUrls.length) throw error;\n }\n }\n // A sign-in or another session taken while this one was refreshing wins.\n if (this.current === current) this.useSession(session);\n return session;\n }\n\n async signOut(): Promise<void> {\n await this.post('auth/logout');\n this.auth = undefined;\n this.current = undefined;\n }\n\n /** End every session of the signed-in account, on every device, this one too. */\n async signOutEverywhere(): Promise<void> {\n await this.post('auth/logout-all');\n this.auth = undefined;\n this.current = undefined;\n }\n\n me(): Promise<Record<string, unknown>> {\n return this.get('auth/me');\n }\n\n /**\n * Add another passkey (another device, `passkey`) to the signed-in account;\n * answers its credential id. The node asks for the approval of a passkey\n * the account already has (`412 CONFIRM_REQUIRED`, never the new one),\n * which `approver` gives.\n */\n async addPasskey(passkey: PasskeyProvider, approver: PasskeyProvider): Promise<string> {\n const begin = await this.post<{ challengeId: string; options: Record<string, unknown> }>('auth/passkeys/add/begin');\n const registration = await passkey.create(begin.options);\n const { credentialId } = await this.postConfirmed<{ credentialId: string }>(\n 'auth/passkeys/add/finish',\n { challengeId: begin.challengeId, registration },\n approver,\n );\n return credentialId;\n }\n\n /** Remove one of the account's passkeys (not the last), approved with `passkey` (one it has). */\n async removePasskey(credentialId: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`auth/passkeys/${seg(credentialId)}`, passkey);\n }\n\n /** Name one of the account's passkeys (a device label); `''` clears the name. */\n async labelPasskey(credentialId: string, label: string): Promise<void> {\n await this.post(`auth/passkeys/${seg(credentialId)}`, { label });\n }\n\n /** What this account uses (apps, bundle bytes, API keys, owned orgs), with the cluster's quotas. */\n usage(): Promise<Record<string, unknown>> {\n return this.get('auth/usage');\n }\n\n /**\n * The node's attestation document, unverified: for display only. Every\n * request this client sends is sealed to a key it verified itself first.\n */\n async attestation(): Promise<AttestationDoc> {\n const nonce = toHex(crypto.getRandomValues(new Uint8Array(32)));\n const response = await this.raw(`${this.nodeUrl}/attestation?nonce=${nonce}`);\n if (!response.ok) throw await refusal(response);\n return (await response.json()) as AttestationDoc;\n }\n\n /** The account's API keys (never the keys themselves). */\n async listApiKeys(): Promise<Array<Record<string, unknown>>> {\n const { keys } = await this.get<{ keys: Array<Record<string, unknown>> }>('auth/apikeys');\n return keys;\n }\n\n async revokeApiKey(keyId: string): Promise<void> {\n await this.delete(`auth/apikeys/${seg(keyId)}`);\n }\n\n /**\n * Create an API key for an agent or server, approved with the account's\n * `passkey` (`412 CONFIRM_REQUIRED`); needs a passkey session (an API key\n * is refused `403`). The key is returned once.\n */\n createApiKey(\n options: {\n label?: string;\n apps?: string[];\n methods?: string[];\n readOnly?: boolean;\n allowConfirm?: boolean;\n ttlSecs?: number;\n },\n passkey: PasskeyProvider,\n ): Promise<{ keyId: string; key: string }> {\n return this.postConfirmed('auth/apikeys', { ...options }, passkey);\n }\n\n // ---------------------------------------------------------------- apps\n\n /** Upload a raw WASM bundle (development clusters only); answers its hash. */\n async uploadBundle(wasm: Uint8Array): Promise<string> {\n const { hash } = await this.json<{ hash: string }>('POST', 'bundles', undefined, wasm);\n return hash;\n }\n\n /** Upload a blob for `app`: `blobId` is base58 (what apps print), `id` hex. */\n uploadBlob(app: string, data: Uint8Array): Promise<{ blobId: string; id: string; size: number }> {\n return this.json('POST', `apps/${seg(app)}/blobs`, undefined, data);\n }\n\n /** One of `app`'s blobs, by id (base58 or hex). */\n async downloadBlob(app: string, id: string): Promise<Uint8Array> {\n const response = await this.send('GET', `apps/${seg(app)}/blobs/${seg(id)}`);\n return new Uint8Array(await response.arrayBuffer());\n }\n\n /** `app`'s blobs. */\n async listBlobs(app: string): Promise<BlobInfo[]> {\n const { blobs } = await this.get<{ blobs: BlobInfo[] }>(`apps/${seg(app)}/blobs`);\n return blobs;\n }\n\n /** One of `app`'s blobs' id and size; `NotFound` if the app has no such blob. */\n blobInfo(app: string, id: string): Promise<BlobInfo> {\n return this.get(`apps/${seg(app)}/blobs/${seg(id)}/info`);\n }\n\n /** Delete one of `app`'s blobs (its owner, or an admin of its organization). */\n async deleteBlob(app: string, id: string): Promise<void> {\n await this.delete(`apps/${seg(app)}/blobs/${seg(id)}`);\n }\n\n // ---------------------------------------------------------------- packages\n\n /** Install a signed `.mpk` package file. */\n uploadPackage(mpk: Uint8Array): Promise<PackageInstalled> {\n return this.json('POST', 'packages', undefined, mpk, 'application/octet-stream');\n }\n\n /** Install `package@version` from the cluster's registry; every node that runs it verifies it. */\n installPackage(pkg: string, version: string): Promise<PackageInstalled> {\n return this.post('packages/install', { package: pkg, version });\n }\n\n /** Installed packages and their versions. */\n async packages(): Promise<PackageInfo[]> {\n const { packages } = await this.get<{ packages: PackageInfo[] }>('packages');\n return packages;\n }\n\n /** One installed package and its versions. */\n package(pkg: string): Promise<PackageInfo> {\n return this.get(`packages/${seg(pkg)}`);\n }\n\n /** Uninstall one version, or the whole package. Refused while an app runs it. */\n uninstallPackage(pkg: string, version?: string): Promise<Record<string, unknown>> {\n return this.delete(version === undefined ? `packages/${seg(pkg)}` : `packages/${seg(pkg)}/${seg(version)}`);\n }\n\n // ---------------------------------------------------------------- app instances\n\n /** Apps this caller reaches, optionally only those of one package or bundle. */\n async listApps(filter: { package?: string; bundle?: string } = {}): Promise<AppInfo[]> {\n const q = new URLSearchParams();\n if (filter.package) q.set('package', filter.package);\n if (filter.bundle) q.set('bundle', filter.bundle);\n const query = q.toString();\n const { apps } = await this.get<{ apps: AppInfo[] }>(query ? `apps?${query}` : 'apps');\n return apps;\n }\n\n getApp(app: string): Promise<Record<string, unknown>> {\n return this.get(`apps/${seg(app)}`);\n }\n\n /** Delete an app instance (its owner, or an admin of its organization). */\n async deleteApp(app: string): Promise<void> {\n await this.delete(`apps/${seg(app)}`);\n }\n\n /** Who may reach the app: `{ kind: 'owner' | 'org' | 'public' | 'accounts' | 'team', ... }`. */\n async setAccess(app: string, access: Record<string, unknown>): Promise<void> {\n await this.post(`apps/${seg(app)}/access`, { access });\n }\n\n /** Set the app instance's metadata (its owner, or an admin of its organization); at most 16 KiB. */\n async setAppMetadata(app: string, metadata: unknown): Promise<void> {\n await this.post(`apps/${seg(app)}/metadata`, { metadata });\n }\n\n /** What the app's storage holds: `{ keys, bytes, blobs, blobBytes }`. */\n appStorage(app: string): Promise<Record<string, unknown>> {\n return this.get(`apps/${seg(app)}/storage`);\n }\n\n /** The ABI the app's bundle embeds: `{ bundle, abi }`. */\n appAbi(app: string): Promise<Record<string, unknown>> {\n return this.get(`apps/${seg(app)}/abi`);\n }\n\n /**\n * Hand the app to another account (an organization's app only to one of its\n * members). The owner approves with `passkey`.\n */\n async transferApp(app: string, to: string, passkey: PasskeyProvider): Promise<void> {\n await this.postConfirmed(`apps/${seg(app)}/transfer`, { to }, passkey);\n }\n\n /**\n * Move an app to another release of its package (`{ version }`), another\n * package, or a bundle hash, running its migration. Answers the upgrade's\n * entry; a failed migration rejects with code `UPGRADE_FAILED` (422).\n * Where owners hold app upgrades, the node asks for the approval of\n * whoever the package's manifest names (`412 CONFIRM_REQUIRED`), which\n * `passkey` gives. Refused (`403`) to a session opened on an app's\n * frontend: an app asks its user with {@link requestConsent} instead. Past\n * a release deadline its approver has not met: {@link ReleaseDeadlineError}.\n */\n upgradeApp(\n app: string,\n target: { version?: string; package?: string; service?: string; bundle?: string; migrate?: string },\n passkey?: PasskeyProvider,\n ): Promise<{ index: number; status: string; error: unknown }> {\n const path = `apps/${seg(app)}/upgrade`;\n return passkey ? this.postConfirmed(path, target, passkey) : this.post(path, target);\n }\n\n /**\n * POST `body` to `path`, answering a `412 CONFIRM_REQUIRED` with `passkey`'s\n * assertion over the node's challenge (deleting an org, approving a release,\n * adding a member, ...): the same body again, with `confirm`. Without a\n * passkey (a caller in plain JavaScript passing none) the `412` reaches the\n * caller as {@link ConfirmRequired}, carrying the challenge.\n */\n postConfirmed<T>(path: string, body: Record<string, unknown>, passkey: PasskeyProvider): Promise<T> {\n return this.confirmed<T>('POST', path, body, passkey);\n }\n\n /**\n * {@link postConfirmed} for a DELETE (deleting an organization, removing a\n * member or a passkey): `body` (`{}` by default) goes as JSON, and the\n * confirmed retry carries `confirm` beside it.\n */\n deleteConfirmed<T>(path: string, passkey: PasskeyProvider, body: Record<string, unknown> = {}): Promise<T> {\n return this.confirmed<T>('DELETE', path, body, passkey);\n }\n\n private async confirmed<T>(\n method: 'POST' | 'DELETE',\n path: string,\n body: Record<string, unknown>,\n passkey: PasskeyProvider | undefined,\n send: (body: Record<string, unknown>) => Promise<T> = (b) => this.json<T>(method, path, b),\n ): Promise<T> {\n try {\n return await send(body);\n } catch (error) {\n if (!(error instanceof ConfirmRequired) || !passkey) throw error;\n const d = error.details as { challengeId: string; challenge: string; rpId: string; allowCredentials?: string[] };\n let assertion: Awaited<ReturnType<PasskeyProvider['get']>>;\n try {\n assertion = await passkey.get(fromB64url(d.challenge), d.rpId, d.allowCredentials);\n } catch (declined) {\n // WebAuthn rejects a prompt the user dismissed with `NotAllowedError`\n // (`AbortError` when it was aborted); anything else is a real failure.\n const name = (declined as { name?: unknown } | null)?.name;\n if (name === 'NotAllowedError' || name === 'AbortError') throw new ConfirmCancelled(declined);\n throw declined;\n }\n return send({ ...body, confirm: { challengeId: d.challengeId, assertion } });\n }\n }\n\n /**\n * Create an app instance from a bundle hash, or from a package release\n * (`{ package, version?, service? }`, installed from the registry first if\n * the cluster lacks it).\n */\n async createApp(\n name: string,\n bundle: string | { package: string; version?: string; service?: string },\n options: {\n org?: string;\n access?: Record<string, unknown>;\n confirmMethods?: string[];\n /** Arguments for the app's `init`. A failed init rejects with code `INIT_FAILED`. */\n initArgs?: unknown;\n } = {},\n ): Promise<string> {\n const target = typeof bundle === 'string' ? { bundle } : bundle;\n const { appId } = await this.post<{ appId: string }>('apps', { name, ...target, ...options });\n return appId;\n }\n\n /**\n * Call a method. A retry with the same `idempotencyKey` is answered once.\n * Without one, the client makes one, so its own retries of a 503 share it.\n */\n call(app: string, method: string, args: unknown = {}, idempotencyKey?: string): Promise<CallResult> {\n const key = idempotencyKey ?? newIdempotencyKey();\n return this.retried('POST', `apps/${seg(app)}/intents`, { method, args, idempotencyKey: key });\n }\n\n /**\n * Call a method that needs the account holder's approval: the node returns a\n * challenge over this exact call, which `passkey` signs. A declined prompt\n * rejects with {@link ConfirmCancelled}.\n */\n async callConfirmed(\n app: string,\n method: string,\n args: unknown,\n passkey: PasskeyProvider,\n idempotencyKey?: string,\n ): Promise<CallResult> {\n const path = `apps/${seg(app)}/intents`;\n const key = idempotencyKey ?? newIdempotencyKey();\n // The confirmed attempt goes out exactly once: its challenge is single-use,\n // so a resend would be refused on the challenge, not answered from the key.\n return this.confirmed<CallResult>('POST', path, { method, args, idempotencyKey: key }, passkey, (body) =>\n this.retried<CallResult>('POST', path, body, body.confirm !== undefined),\n );\n }\n\n /** Run a read-only method: strong by default, or stale from any replica. */\n view(app: string, method: string, args: unknown = {}, options: { stale?: boolean; minIndex?: number } = {}): Promise<ViewResult> {\n return this.retried('POST', `apps/${seg(app)}/views`, {\n method,\n args,\n consistency: options.stale ? 'stale' : 'strong',\n minIndex: options.minIndex ?? 0,\n });\n }\n\n /** Committed events from index `from`, then live, until `signal` aborts. */\n events(app: string, from = 0, signal?: AbortSignal): AsyncGenerator<CloudEvent> {\n return this.stream(`apps/${seg(app)}/events?from=${from}`, signal);\n }\n\n /** A server-sent event stream on `path`, sealed like every other answer. */\n private async *stream(path: string, signal?: AbortSignal): AsyncGenerator<CloudEvent> {\n const response = await this.send('GET', path, undefined, undefined, undefined, signal);\n if (!response.body) throw new CalimeroError(response.status, 'EVENTS', 'the event stream has no body');\n yield* sseFrames(response.body);\n }\n\n // ---------------------------------------------------------------- presence\n\n /**\n * Publish this device's presence in `app`: `state` (at most 4 KiB) or `null`\n * to retract it. The newest `seq` wins; send the same `seq` and state again\n * as a heartbeat, since an entry not refreshed within 7 s is gone.\n */\n async publishPresence(app: string, seq: number, state: Uint8Array | null): Promise<void> {\n await this.post(`apps/${seg(app)}/presence`, { seq, state: state === null ? null : toHex(state) });\n }\n\n /** Who is present in `app` now. */\n async presence(app: string): Promise<PresenceEntry[]> {\n const { present } = await this.get<{ present: PresenceEntry[] }>(`apps/${seg(app)}/presence`);\n return present;\n }\n\n /**\n * Presence as a stream until `signal` aborts: a `snapshot` event (`data` the\n * entries present), then a `presence` event (`data` one entry) per change.\n */\n presenceStream(app: string, signal?: AbortSignal): AsyncGenerator<CloudEvent> {\n return this.stream(`apps/${seg(app)}/presence/stream`, signal);\n }\n\n // ---------------------------------------------------------------- aliases\n\n /** Name an app (its id or context id) for this account. */\n async setAlias(alias: string, app: string): Promise<void> {\n await this.put(`auth/aliases/${seg(alias)}`, { app });\n }\n\n /** This account's aliases, alias \u2192 app id. */\n async aliases(): Promise<Record<string, string>> {\n const { aliases } = await this.get<{ aliases: Record<string, string> }>('auth/aliases');\n return aliases;\n }\n\n /** The app an alias names. */\n async alias(alias: string): Promise<string> {\n const { appId } = await this.get<{ appId: string }>(`auth/aliases/${seg(alias)}`);\n return appId;\n }\n\n async deleteAlias(alias: string): Promise<void> {\n await this.delete(`auth/aliases/${seg(alias)}`);\n }\n\n // ---------------------------------------------------------------- organizations\n\n async createOrg(name: string): Promise<string> {\n const { orgId } = await this.post<{ orgId: string }>('orgs', { name });\n return orgId;\n }\n\n /** The organization, with the teams this caller reaches or manages. */\n getOrg(org: string): Promise<OrgInfo> {\n return this.get(`orgs/${seg(org)}`);\n }\n\n /**\n * Delete an organization with its teams, invites and apps (its owner only).\n * The node asks for the owner's passkey (`412 CONFIRM_REQUIRED`), which `passkey` gives.\n */\n async deleteOrg(org: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`orgs/${seg(org)}`, passkey);\n }\n\n /** Set the organization's metadata (an admin, or a holder of `MANAGE_METADATA`); at most 16 KiB. */\n async setOrgMetadata(org: string, metadata: unknown): Promise<void> {\n await this.post(`orgs/${seg(org)}/metadata`, { metadata });\n }\n\n /** Set a member's metadata (theirs, or an admin's); `null` clears it. */\n async setMemberMetadata(org: string, account: string, metadata: unknown): Promise<void> {\n await this.post(`orgs/${seg(org)}/members/${seg(account)}/metadata`, { metadata });\n }\n\n /**\n * Upgrade every app of `org` that runs `target.package` to `target.version`\n * (optionally one team's, with `cascade` the teams below it). The org's owner,\n * or a holder of `MANAGE_APPLICATION`, approves the whole run with `passkey`.\n * Answers the run; {@link upgradeRun} follows it.\n */\n upgradeOrg(org: string, target: OrgUpgradeTarget, passkey: PasskeyProvider): Promise<UpgradeRun> {\n return this.postConfirmed(`orgs/${seg(org)}/upgrade`, { ...target }, passkey);\n }\n\n /** An organization-wide upgrade run: its apps, those done and those that failed. */\n upgradeRun(org: string, run: string): Promise<UpgradeRun> {\n return this.get(`orgs/${seg(org)}/upgrades/${seg(run)}`);\n }\n\n /** Run the apps that failed in `run` again, as a new run, approved with `passkey`. */\n retryUpgradeRun(org: string, run: string, passkey: PasskeyProvider): Promise<UpgradeRun> {\n return this.postConfirmed(`orgs/${seg(org)}/upgrades/${seg(run)}/retry`, {}, passkey);\n }\n\n /**\n * Approve a mero-tee release to hold the apps of `org`, or of this account\n * outside any organization (`org` `null`); `approved: false` withdraws it.\n * Until then, nodes on that release get none of those apps' data. For an\n * organization, a member holding `APPROVE_RELEASES` approves with `passkey`;\n * the node binds the release's measurements itself. Refused (`403`) to a\n * session opened on an app's frontend: an app asks its user with\n * {@link requestConsent} instead.\n */\n async approveRelease(\n org: string | null,\n version: string,\n passkey: PasskeyProvider,\n approved = true,\n ): Promise<Record<string, unknown>> {\n const path = org === null ? 'auth/releases' : `orgs/${seg(org)}/releases`;\n return this.postConfirmed(path, { version, approved }, passkey);\n }\n\n /**\n * Approve the URL prefixes apps from `pkg`'s publisher may call out to, for\n * `org`'s apps or this account's own (`org` `null`). `prefixes` `'manifest'`\n * (the default) approves every prefix the package's latest release declares;\n * `replace` sets exactly `prefixes`, which is how one is revoked. Approved\n * with `passkey`. Refused (`403`) to a session opened on an app's frontend:\n * an app asks with {@link requestConsent} (`kind: 'outbound'`) instead.\n */\n async approveOutbound(\n org: string | null,\n pkg: string,\n passkey: PasskeyProvider,\n options: { prefixes?: string[] | 'manifest'; replace?: boolean } = {},\n ): Promise<Record<string, unknown>> {\n const path = org === null ? 'auth/outbound' : `orgs/${seg(org)}/outbound`;\n return this.postConfirmed(\n path,\n { package: pkg, prefixes: options.prefixes ?? 'manifest', replace: options.replace ?? false },\n passkey,\n );\n }\n\n // ---------------------------------------------------------------- approvals\n\n /**\n * One page of the report of a scope's apps: an organization's (any member;\n * `404` to anyone else) or, with `org` `null`, the account's own outside any\n * organization (a session bound to an app's frontend: that package's apps).\n * The governance, the scope's approved releases, the releases the cluster's\n * nodes run and whether each is approved, and per app its release, newer\n * releases it may move to, last upgrade and replicas.\n */\n appsReport(org: string | null, page: PageOptions = {}): Promise<AppsReport> {\n const path = org === null ? 'auth/apps' : `orgs/${seg(org)}/apps`;\n return this.get(`${path}${pageQuery(page)}`);\n }\n\n /** {@link appsReport}, every page, with the apps of all of them in `apps`. */\n async appsReportAll(org: string | null): Promise<AppsReport> {\n const first = await this.appsReport(org);\n const apps: ReportedApp[] = [...first.apps];\n let next = first.next;\n while (next !== null) {\n const page = await this.appsReport(org, { after: next });\n apps.push(...page.apps);\n next = page.next;\n }\n return { ...first, apps, next: null };\n }\n\n /** `GET /releases`: the cluster's governance and every release deadline. Public. */\n releaseRules(): Promise<ReleaseRules> {\n return this.get('releases');\n }\n\n /**\n * What waits for a decision in a scope (`org`, or the account's own apps\n * with `null`): mero-tee releases the cluster's nodes run that the scope has\n * not approved, apps with newer releases of their package, and whether a\n * passed deadline stops new work. Read over the sealed channel; act on an\n * item by sending the user to the consent page ({@link requestConsent},\n * `releaseConsent`, `upgradeConsent`).\n */\n async pendingApprovals(org: string | null = null): Promise<PendingApprovals> {\n const [report, rules] = await Promise.all([this.appsReportAll(org), this.releaseRules()]);\n return pendingApprovalsFrom(report, rules);\n }\n\n /**\n * Ask the node to ask the user: a release, upgrade or outbound approval\n * that only the account holder may make, decided on the node's own consent\n * page, never in the app. Needs a passkey session (a session bound to the\n * app's frontend is fine). Send the person to the answer's `url`; the page\n * sends them back to `returnTo?request_id=\u2026&result=approved|declined`\n * (`consentReturn`), and {@link consentResult} confirms the decision.\n */\n requestConsent(request: ConsentRequest): Promise<ConsentStarted> {\n return this.post('consent/requests', request);\n }\n\n /**\n * {@link requestConsent}, then send the browser to the consent page\n * (`navigate`, by default `window.location.assign`). Pass `navigate` itself\n * or {@link OpenConsentOptions}, whose `confirm` runs first with the node's\n * answer so the app can show the person its `code`; when it answers `false`\n * the page is not opened. When the node sends a `code` that is not\n * {@link confirmationCode} of `requestId`, it throws `CalimeroError`\n * (`CONSENT_CODE_MISMATCH`) and does not navigate. Answers the request\n * once `navigate` returns (or `confirm` declines): with a popup\n * (`url => window.open(url)`), poll it with {@link waitForConsent}.\n */\n async openConsentPage(\n request: ConsentRequest,\n navigateOrOptions: ((url: string) => void) | OpenConsentOptions = {},\n ): Promise<ConsentStarted> {\n const options = typeof navigateOrOptions === 'function' ? { navigate: navigateOrOptions } : navigateOrOptions;\n const navigate =\n options.navigate ??\n ((url: string) => {\n const w = (globalThis as { window?: { location: { assign(url: string): void } } }).window;\n if (!w) throw new Error('no window to open the consent page in; pass `navigate`');\n w.location.assign(url);\n });\n const started = await this.requestConsent(request);\n if (started.code !== undefined) {\n const expected = await confirmationCode(started.requestId);\n if (started.code !== expected) {\n throw new CalimeroError(200, 'CONSENT_CODE_MISMATCH', 'the consent page code does not match the request', {\n requestId: started.requestId,\n code: started.code,\n expected,\n });\n }\n }\n if (options.confirm && !(await options.confirm(started))) return started;\n navigate(started.url);\n return started;\n }\n\n /** The decision on a consent request (any node answers, for the account that asked). */\n consentResult(requestId: string): Promise<ConsentResult> {\n return this.get(`consent/${seg(requestId)}/result`);\n }\n\n /**\n * Poll {@link consentResult} until the request is decided, every\n * `intervalMs` (2 s), until `signal` aborts or `expiresAt` (Unix seconds)\n * passes, when it answers the last `pending` result.\n */\n async waitForConsent(\n requestId: string,\n options: { intervalMs?: number; signal?: AbortSignal; expiresAt?: number } = {},\n ): Promise<ConsentResult> {\n const interval = options.intervalMs ?? 2000;\n for (;;) {\n const result = await this.consentResult(requestId);\n if (result.status !== 'pending') return result;\n if (options.signal?.aborted) return result;\n if (options.expiresAt !== undefined && Date.now() / 1000 >= options.expiresAt) return result;\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n }\n\n /** `GET /publishers/{signerId}`: the cluster name and binding generation a key signs to bind it next. */\n publisherBinding(signerId: string): Promise<PublisherBindingInfo> {\n return this.get(`publishers/${seg(signerId)}`);\n }\n\n /**\n * Bind a package signing key to `org`, which then approves the node images\n * every instance of the key's packages runs on, and upgrades those whose\n * package declares `upgrades: publisher`. `proof` is the key's signature\n * over `publisherBindingMessage(cluster, org, signerId, generation)`; a\n * member holding `APPROVE_RELEASES` sends it with `passkey`.\n */\n bindPublisher(org: string, proof: PublisherProof, passkey: PasskeyProvider): Promise<Record<string, unknown>> {\n return this.postConfirmed(`orgs/${seg(org)}/publishers`, { ...proof }, passkey);\n }\n\n /**\n * Upgrade every instance of `pkg` whose release declares `upgrades:\n * publisher`, whoever owns it, as its publisher `org` (a\n * `MANAGE_APPLICATION` holder there), with one passkey approval. Answers\n * the run, kept on the publisher.\n */\n upgradePublished(\n org: string,\n pkg: string,\n target: { version: string; migrate?: string },\n passkey: PasskeyProvider,\n ): Promise<UpgradeRun> {\n return this.postConfirmed(`orgs/${seg(org)}/packages/${seg(pkg)}/upgrade`, { ...target }, passkey);\n }\n\n // ---------------------------------------------------------------- operator\n\n /** `GET /ops/apps`: what every app runs, without names or accounts. Operator token (`useApiKey`). */\n opsApps(page: PageOptions = {}): Promise<OpsAppsReport> {\n return this.get(`ops/apps${pageQuery(page)}`);\n }\n\n /** `GET /ops/orgs`: each organization's approved releases. Operator token. */\n opsOrgs(page: PageOptions = {}): Promise<OpsOrgsReport> {\n return this.get(`ops/orgs${pageQuery(page)}`);\n }\n\n /**\n * Announce when work on images older than `version` ends: from `after` on,\n * a scope that has not approved it (or newer) starts no new work. Operator\n * token.\n */\n async setReleaseDeadline(version: string, after: Date | string): Promise<void> {\n const at = typeof after === 'string' ? after : after.toISOString();\n await this.post(`ops/releases/${seg(version)}/deadline`, { after: at });\n }\n\n /** Lift a release's deadline. Operator token. */\n async liftReleaseDeadline(version: string): Promise<void> {\n await this.delete(`ops/releases/${seg(version)}/deadline`);\n }\n\n /** Add a member, or change their role, approved with the caller's `passkey`. */\n async setMember(\n org: string,\n account: string,\n role: 'guest' | 'member' | 'admin' | 'owner',\n passkey: PasskeyProvider,\n ): Promise<void> {\n await this.postConfirmed(`orgs/${seg(org)}/members`, { account, role }, passkey);\n }\n\n /**\n * Remove a member, or leave (`account` the caller's own), approved with the\n * caller's `passkey`.\n */\n removeMember(org: string, account: string, passkey: PasskeyProvider): Promise<Record<string, unknown>> {\n return this.deleteConfirmed(`orgs/${seg(org)}/members/${seg(account)}`, passkey);\n }\n\n /**\n * Set capability bits ({@link ORG_CAPABILITIES}): for a member (`account`),\n * for a member of one team (`account` and `team`), or the organization's\n * default (neither). Approved with the caller's `passkey`.\n */\n async setCapabilities(\n org: string,\n capabilities: number,\n passkey: PasskeyProvider,\n at: { account?: string; team?: string } = {},\n ): Promise<void> {\n await this.postConfirmed(`orgs/${seg(org)}/capabilities`, { capabilities, ...at }, passkey);\n }\n\n async createTeam(org: string, name: string, join: 'everyone' | 'invite', parent?: string): Promise<string> {\n const { teamId } = await this.post<{ teamId: string }>(`orgs/${seg(org)}/teams`, { name, join, parent });\n return teamId;\n }\n\n getTeam(org: string, team: string): Promise<Record<string, unknown>> {\n return this.get(`orgs/${seg(org)}/teams/${seg(team)}`);\n }\n\n /**\n * Rename, change who may join, set the app's metadata, or move the team:\n * `parent: null` moves it to the top, an absent `parent` leaves it.\n */\n async updateTeam(\n org: string,\n team: string,\n update: { name?: string; join?: 'everyone' | 'invite'; parent?: string | null; metadata?: unknown },\n ): Promise<void> {\n await this.post(`orgs/${seg(org)}/teams/${seg(team)}`, update);\n }\n\n /** Delete a team, the teams below it and their apps. */\n async deleteTeam(org: string, team: string): Promise<void> {\n await this.delete(`orgs/${seg(org)}/teams/${seg(team)}`);\n }\n\n /**\n * Add a member to a team, or change their row: role, lead, capability bits.\n * Approved with the caller's `passkey`.\n */\n async setTeamMember(\n org: string,\n team: string,\n account: string,\n passkey: PasskeyProvider,\n row: { role?: 'lead' | 'member' | 'readOnly'; lead?: boolean; capabilities?: number } = {},\n ): Promise<void> {\n await this.postConfirmed(`orgs/${seg(org)}/teams/${seg(team)}/members`, { account, ...row }, passkey);\n }\n\n /** Remove a member from a team, approved with the caller's `passkey`. */\n async removeTeamMember(org: string, team: string, account: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`orgs/${seg(org)}/teams/${seg(team)}/members/${seg(account)}`, passkey);\n }\n\n /**\n * Make an invite into `org` (and `teams`), approved with the caller's\n * `passkey`; answers its token, which {@link redeemInvite} takes (no\n * approval there).\n */\n async invite(\n org: string,\n role: 'guest' | 'member' | 'admin',\n passkey: PasskeyProvider,\n teams: string[] = [],\n options: { ttlSecs?: number; uses?: number } = {},\n ): Promise<string> {\n const { token } = await this.postConfirmed<{ token: string }>(\n `orgs/${seg(org)}/invites`,\n { role, teams, ...options },\n passkey,\n );\n return token;\n }\n\n redeemInvite(token: string): Promise<Record<string, unknown>> {\n return this.post(`invites/${seg(token)}/redeem`);\n }\n}\n", "/**\n * What a member may do in an organization beyond their role, as core's\n * `caps` bits (`setCapabilities`, `setTeamMember`'s `capabilities`). A team's\n * lead and an organization's admin hold them all.\n */\nexport const ORG_CAPABILITIES = {\n /** Create an app in the organization (on its team, or org-wide). */\n CREATE_APP: 1 << 0,\n /** Mint invites (org-wide, or on each team the invite names). */\n INVITE_MEMBERS: 1 << 1,\n /** Inherited into open teams; denying it keeps a member out of them. */\n JOIN_OPEN_TEAMS: 1 << 2,\n /** Add and remove a team's members. */\n MANAGE_MEMBERS: 1 << 3,\n /** Upgrade the organization's apps (and, as a publisher, every instance of its `publisher` packages), start org upgrade runs, approve outbound hosts (org-wide). */\n MANAGE_APPLICATION: 1 << 4,\n /** Create a top-level team without being an admin. */\n CREATE_TEAM: 1 << 5,\n /** Delete a team, and what it holds, without being an admin. */\n DELETE_TEAM: 1 << 6,\n /** Change who may join a team (open or invite-only). */\n MANAGE_VISIBILITY: 1 << 7,\n /** Set the organization's and its teams' metadata. */\n MANAGE_METADATA: 1 << 8,\n /**\n * Approve (or withdraw) the mero-tee releases that hold the apps the\n * organization governs (those of the packages it publishes, and its own of\n * unbound packages), and bind a package signing key to it\n * (`bindPublisher`). Organization-wide only. Bit 9 is left unused.\n */\n APPROVE_RELEASES: 1 << 10,\n} as const;\n\nexport type OrgCapability = keyof typeof ORG_CAPABILITIES;\n\n/** What a member holds unless an admin says otherwise. */\nexport const DEFAULT_ORG_CAPABILITIES = ORG_CAPABILITIES.JOIN_OPEN_TEAMS;\n\n/** The bitmask of `names`. */\nexport function orgCapabilities(...names: OrgCapability[]): number {\n return names.reduce((mask, name) => mask | ORG_CAPABILITIES[name], 0);\n}\n", "/**\n * ChaCha20-Poly1305 (RFC 8439), the AEAD mero-agent-gate's HPKE suite uses.\n * WebCrypto has no ChaCha20, and the SDK takes no runtime dependencies, so it\n * is written here from the RFC. Its tests check it against the RFC's vectors\n * and against Node's own implementation.\n *\n * Only for sealing a provisioning bundle once: short messages, one key per\n * message. Not constant-time in Poly1305's arithmetic (BigInt), which leaks\n * nothing here: the one-time Poly1305 key is never reused.\n */\n\nconst KEY_LEN = 32;\nconst NONCE_LEN = 12;\nconst TAG_LEN = 16;\n\nfunction rotl(value: number, shift: number): number {\n return ((value << shift) | (value >>> (32 - shift))) >>> 0;\n}\n\nfunction quarterRound(s: Uint32Array, a: number, b: number, c: number, d: number): void {\n s[a] = (s[a] + s[b]) >>> 0;\n s[d] = rotl(s[d] ^ s[a], 16);\n s[c] = (s[c] + s[d]) >>> 0;\n s[b] = rotl(s[b] ^ s[c], 12);\n s[a] = (s[a] + s[b]) >>> 0;\n s[d] = rotl(s[d] ^ s[a], 8);\n s[c] = (s[c] + s[d]) >>> 0;\n s[b] = rotl(s[b] ^ s[c], 7);\n}\n\nfunction u32le(bytes: Uint8Array, offset: number): number {\n return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)) >>> 0;\n}\n\n/** One 64-byte ChaCha20 block (RFC 8439 \u00A72.3). */\nexport function chacha20Block(key: Uint8Array, counter: number, nonce: Uint8Array): Uint8Array {\n const state = new Uint32Array(16);\n state[0] = 0x61707865;\n state[1] = 0x3320646e;\n state[2] = 0x79622d32;\n state[3] = 0x6b206574;\n for (let i = 0; i < 8; i += 1) state[4 + i] = u32le(key, i * 4);\n state[12] = counter >>> 0;\n for (let i = 0; i < 3; i += 1) state[13 + i] = u32le(nonce, i * 4);\n const working = state.slice();\n for (let round = 0; round < 10; round += 1) {\n quarterRound(working, 0, 4, 8, 12);\n quarterRound(working, 1, 5, 9, 13);\n quarterRound(working, 2, 6, 10, 14);\n quarterRound(working, 3, 7, 11, 15);\n quarterRound(working, 0, 5, 10, 15);\n quarterRound(working, 1, 6, 11, 12);\n quarterRound(working, 2, 7, 8, 13);\n quarterRound(working, 3, 4, 9, 14);\n }\n const out = new Uint8Array(64);\n for (let i = 0; i < 16; i += 1) {\n const word = (working[i] + state[i]) >>> 0;\n out[i * 4] = word & 0xff;\n out[i * 4 + 1] = (word >>> 8) & 0xff;\n out[i * 4 + 2] = (word >>> 16) & 0xff;\n out[i * 4 + 3] = (word >>> 24) & 0xff;\n }\n return out;\n}\n\n/** ChaCha20 encryption from block `counter` on (RFC 8439 \u00A72.4). */\nexport function chacha20(key: Uint8Array, counter: number, nonce: Uint8Array, data: Uint8Array): Uint8Array {\n const out = new Uint8Array(data.length);\n for (let offset = 0, block = counter; offset < data.length; offset += 64, block += 1) {\n const stream = chacha20Block(key, block, nonce);\n const end = Math.min(offset + 64, data.length);\n for (let i = offset; i < end; i += 1) out[i] = data[i] ^ stream[i - offset];\n }\n return out;\n}\n\nfunction leToBigInt(bytes: Uint8Array): bigint {\n let value = 0n;\n for (let i = bytes.length - 1; i >= 0; i -= 1) value = (value << 8n) | BigInt(bytes[i]);\n return value;\n}\n\nconst P1305 = (1n << 130n) - 5n;\n\n/** Poly1305 over `message` with the one-time `key` (RFC 8439 \u00A72.5). */\nexport function poly1305(key: Uint8Array, message: Uint8Array): Uint8Array {\n const r = leToBigInt(key.subarray(0, 16)) & 0x0ffffffc0ffffffc0ffffffc0fffffffn;\n const s = leToBigInt(key.subarray(16, 32));\n let acc = 0n;\n for (let offset = 0; offset < message.length; offset += 16) {\n const block = message.subarray(offset, Math.min(offset + 16, message.length));\n const n = leToBigInt(block) + (1n << BigInt(8 * block.length));\n acc = ((acc + n) * r) % P1305;\n }\n let tag = (acc + s) & ((1n << 128n) - 1n);\n const out = new Uint8Array(TAG_LEN);\n for (let i = 0; i < TAG_LEN; i += 1) {\n out[i] = Number(tag & 0xffn);\n tag >>= 8n;\n }\n return out;\n}\n\nfunction pad16(length: number): Uint8Array {\n return new Uint8Array((16 - (length % 16)) % 16);\n}\n\nfunction u64le(value: number): Uint8Array {\n const out = new Uint8Array(8);\n new DataView(out.buffer).setBigUint64(0, BigInt(value), true);\n return out;\n}\n\nfunction macData(aad: Uint8Array, ciphertext: Uint8Array): Uint8Array {\n const parts = [aad, pad16(aad.length), ciphertext, pad16(ciphertext.length), u64le(aad.length), u64le(ciphertext.length)];\n const out = new Uint8Array(parts.reduce((n, p) => n + 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\nfunction check(key: Uint8Array, nonce: Uint8Array): void {\n if (key.length !== KEY_LEN) throw new Error('ChaCha20-Poly1305 needs a 32-byte key');\n if (nonce.length !== NONCE_LEN) throw new Error('ChaCha20-Poly1305 needs a 12-byte nonce');\n}\n\n/** Seal: the ciphertext followed by its 16-byte tag (RFC 8439 \u00A72.8). */\nexport function chacha20Poly1305Seal(\n key: Uint8Array,\n nonce: Uint8Array,\n plaintext: Uint8Array,\n aad: Uint8Array = new Uint8Array(0),\n): Uint8Array {\n check(key, nonce);\n const otk = chacha20Block(key, 0, nonce).subarray(0, 32);\n const ciphertext = chacha20(key, 1, nonce, plaintext);\n const tag = poly1305(otk, macData(aad, ciphertext));\n const out = new Uint8Array(ciphertext.length + TAG_LEN);\n out.set(ciphertext);\n out.set(tag, ciphertext.length);\n return out;\n}\n\n/** Open what {@link chacha20Poly1305Seal} made; throws if it was altered. */\nexport function chacha20Poly1305Open(\n key: Uint8Array,\n nonce: Uint8Array,\n sealed: Uint8Array,\n aad: Uint8Array = new Uint8Array(0),\n): Uint8Array {\n check(key, nonce);\n if (sealed.length < TAG_LEN) throw new Error('The sealed message is shorter than its tag');\n const ciphertext = sealed.subarray(0, sealed.length - TAG_LEN);\n const otk = chacha20Block(key, 0, nonce).subarray(0, 32);\n const expected = poly1305(otk, macData(aad, ciphertext));\n let diff = 0;\n for (let i = 0; i < TAG_LEN; i += 1) diff |= expected[i] ^ sealed[ciphertext.length + i];\n if (diff !== 0) throw new Error('The sealed message did not authenticate');\n return chacha20(key, 1, nonce, ciphertext);\n}\n", "/**\n * RFC 9180 HPKE, the one suite and mode mero-agent-gate takes: Auth mode,\n * DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20-Poly1305, single-shot\n * (one message per context, sequence number 0). Auth mode proves the sender:\n * the gate opens a bundle only under the X25519 key it names, so nobody can\n * seal in an owner's name.\n *\n * X25519 and HMAC are WebCrypto; ChaCha20-Poly1305 is ./chacha20poly1305.\n * The tests open what mero-agent-gate (Rust, the `hpke` crate) sealed, and the\n * gate opens what this seals.\n */\n\nimport { concat } from '../crypto/internal.js';\nimport { dh, x25519KeyPair } from '../sealed/noise.js';\nimport { chacha20Poly1305Open, chacha20Poly1305Seal } from './chacha20poly1305.js';\n\nconst KEM_ID = 0x0020; // DHKEM(X25519, HKDF-SHA256)\nconst KDF_ID = 0x0001; // HKDF-SHA256\nconst AEAD_ID = 0x0003; // ChaCha20-Poly1305\nconst MODE_AUTH = 0x02;\nconst N_SECRET = 32;\nconst N_KEY = 32;\nconst N_NONCE = 12;\n\nconst utf8 = (s: string) => new TextEncoder().encode(s);\nconst i2osp2 = (n: number) => new Uint8Array([(n >> 8) & 0xff, n & 0xff]);\n\nconst KEM_SUITE = concat(utf8('KEM'), i2osp2(KEM_ID));\nconst HPKE_SUITE = concat(utf8('HPKE'), i2osp2(KEM_ID), i2osp2(KDF_ID), i2osp2(AEAD_ID));\n\nasync function hmac(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {\n // An empty salt is HashLen zeros (RFC 5869); WebCrypto refuses a zero-length HMAC key.\n const raw = key.length === 0 ? new Uint8Array(32) : key;\n const k = await crypto.subtle.importKey('raw', raw, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n return new Uint8Array(await crypto.subtle.sign('HMAC', k, data));\n}\n\nasync function expand(prk: Uint8Array, info: Uint8Array, length: number): Promise<Uint8Array> {\n const out = new Uint8Array(length);\n let previous = new Uint8Array(0);\n for (let i = 1, offset = 0; offset < length; i += 1) {\n previous = await hmac(prk, concat(previous, info, new Uint8Array([i])));\n out.set(previous.subarray(0, Math.min(previous.length, length - offset)), offset);\n offset += previous.length;\n }\n return out;\n}\n\nfunction labeledExtract(suite: Uint8Array, salt: Uint8Array, label: string, ikm: Uint8Array): Promise<Uint8Array> {\n return hmac(salt, concat(utf8('HPKE-v1'), suite, utf8(label), ikm));\n}\n\nfunction labeledExpand(suite: Uint8Array, prk: Uint8Array, label: string, info: Uint8Array, length: number) {\n return expand(prk, concat(i2osp2(length), utf8('HPKE-v1'), suite, utf8(label), info), length);\n}\n\nasync function extractAndExpand(dhValue: Uint8Array, kemContext: Uint8Array): Promise<Uint8Array> {\n const prk = await labeledExtract(KEM_SUITE, new Uint8Array(0), 'eae_prk', dhValue);\n return labeledExpand(KEM_SUITE, prk, 'shared_secret', kemContext, N_SECRET);\n}\n\nasync function keySchedule(sharedSecret: Uint8Array, info: Uint8Array): Promise<{ key: Uint8Array; nonce: Uint8Array }> {\n const empty = new Uint8Array(0);\n const pskIdHash = await labeledExtract(HPKE_SUITE, empty, 'psk_id_hash', empty);\n const infoHash = await labeledExtract(HPKE_SUITE, empty, 'info_hash', info);\n const context = concat(new Uint8Array([MODE_AUTH]), pskIdHash, infoHash);\n const secret = await labeledExtract(HPKE_SUITE, sharedSecret, 'secret', empty);\n return {\n key: await labeledExpand(HPKE_SUITE, secret, 'key', context, N_KEY),\n nonce: await labeledExpand(HPKE_SUITE, secret, 'base_nonce', context, N_NONCE),\n };\n}\n\nexport interface HpkeSealed {\n /** The encapsulated key: the sender's ephemeral X25519 public key. */\n enc: Uint8Array;\n ciphertext: Uint8Array;\n}\n\n/**\n * Seal `plaintext` to `recipientPublic` in Auth mode as the holder of\n * `senderSecret` (32 raw X25519 bytes). `ephemeralSecret` is for tests.\n */\nexport async function hpkeSealAuth(\n recipientPublic: Uint8Array,\n senderSecret: Uint8Array,\n info: Uint8Array,\n plaintext: Uint8Array,\n aad: Uint8Array = new Uint8Array(0),\n ephemeralSecret?: Uint8Array,\n): Promise<HpkeSealed> {\n if (recipientPublic.length !== 32) throw new Error('The recipient key is not 32 bytes of X25519');\n const ephemeral = await x25519KeyPair(ephemeralSecret);\n const sender = await x25519KeyPair(senderSecret);\n const dhValue = concat(await dh(ephemeral.privateKey, recipientPublic), await dh(sender.privateKey, recipientPublic));\n const shared = await extractAndExpand(dhValue, concat(ephemeral.publicKey, recipientPublic, sender.publicKey));\n const { key, nonce } = await keySchedule(shared, info);\n return { enc: ephemeral.publicKey, ciphertext: chacha20Poly1305Seal(key, nonce, plaintext, aad) };\n}\n\n/** Open what {@link hpkeSealAuth} (or the gate's own sealer) made, as the recipient. */\nexport async function hpkeOpenAuth(\n recipientSecret: Uint8Array,\n senderPublic: Uint8Array,\n info: Uint8Array,\n sealed: HpkeSealed,\n aad: Uint8Array = new Uint8Array(0),\n): Promise<Uint8Array> {\n const recipient = await x25519KeyPair(recipientSecret);\n const dhValue = concat(await dh(recipient.privateKey, sealed.enc), await dh(recipient.privateKey, senderPublic));\n const shared = await extractAndExpand(dhValue, concat(sealed.enc, recipient.publicKey, senderPublic));\n const { key, nonce } = await keySchedule(shared, info);\n return chacha20Poly1305Open(key, nonce, sealed.ciphertext, aad);\n}\n", "/**\n * A client for mero-agent-gate, the gate in a private agent TD (mero-tee,\n * `mero-agent-gate/`): attest an agent, claim it with your key, give it its\n * secrets sealed to the TD, and release it. It runs where the owner is (a\n * browser, a CLI), so whoever carries the requests, mdma included, sees only\n * quotes and ciphertext.\n *\n * One agent TD hosts several owners' agents, each named by an agent id. For\n * an agent the gate's quote binds, in its report data:\n *\n * `nonce \u2016 SHA-256(\"mero-agent-gate/attest/v3\" \u2016 provisioning_pub \u2016 len(id) \u2016 id \u2016 signing_pub \u2016 owner_pub)`\n *\n * (signing and owner keys 32 zero bytes while unclaimed). {@link attestAgent}\n * checks that and the quote itself before returning anything; every function\n * that sends refuses an agent whose quote names another owner.\n *\n * ```ts\n * import { verify as dcapVerify, getCollateral } from '@phala/dcap-qvl';\n *\n * const policy = await verifySignedAgentPolicy(policyJson, bundleJson, { profile: 'locked-read-only' });\n * const verifier = agentQuoteVerifier(policy, { dcapVerify, fetchCollateral: (q) => getCollateral(PCCS, q) });\n * const owner = await generateOwnerKey(); // keep owner.secret: it is the only key that can change the agent\n * const agent = await attestAgent({ gateUrl, agentId: 'a-1f2e', verifier });\n * await provisionAgent({ gateUrl, agent, ownerSecret: owner.secret, verifier, secrets: { NEAR_AI_API_KEY: key } });\n * ```\n */\n\nimport { concat, hex } from '../crypto/internal.js';\nimport { x25519KeyPair } from '../sealed/noise.js';\nimport type { VerifyTransportQuote } from '../sealed/sealed.js';\nimport { hpkeSealAuth } from './hpke.js';\n\nexport const AGENT_ATTEST_DOMAIN = 'mero-agent-gate/attest/v3';\nexport const AGENT_PROVISION_INFO_DOMAIN = 'mero-agent-gate/provision/v2';\n\nconst AGENT_ID = /^[a-z0-9][a-z0-9-]{0,62}$/;\nconst SECRET_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;\nconst MAX_SECRETS = 64;\nconst MAX_SECRET_LEN = 64 * 1024;\n\n/** A gate's refusal, with its `error` code (`not_the_owner`, `no_free_slot`, \u2026) when it gave one. */\nexport class AgentGateError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n readonly code?: string,\n ) {\n super(message);\n this.name = 'AgentGateError';\n }\n}\n\n/** An agent's keys, once its quote passed {@link attestAgent}'s checks. */\nexport interface VerifiedAgent {\n agentId: string;\n /** Base64; secrets are sealed to it. Valid until the gate restarts. */\n provisioningPublicKey: string;\n /** Base64 Ed25519 key the agent signs with; absent while unclaimed. */\n signingPublicKey?: string;\n /** Base64 X25519 key of the owner that claimed it; absent while unclaimed. */\n ownerPublicKey?: string;\n}\n\nexport interface OwnerKey {\n /** 32 raw X25519 bytes. The only key that can provision or release the agent: keep it. */\n secret: Uint8Array;\n /** Base64 of the public half: what the gate's quote names as owner. */\n publicKey: string;\n}\n\ntype Fetch = typeof fetch;\n\nexport function validateAgentId(agentId: string): void {\n if (!AGENT_ID.test(agentId)) {\n throw new Error(`Agent id ${JSON.stringify(agentId)} must match [a-z0-9][a-z0-9-]{0,62}`);\n }\n}\n\nfunction utf8(value: string): Uint8Array {\n return new TextEncoder().encode(value);\n}\n\nfunction lengthPrefixed(agentId: string): Uint8Array {\n const id = utf8(agentId);\n return concat(new Uint8Array([id.length]), id);\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nfunction fromBase64(value: string, label: string, length?: number): Uint8Array {\n let bytes: Uint8Array;\n try {\n bytes = Uint8Array.from(atob(value.trim()), (c) => c.charCodeAt(0));\n } catch {\n throw new Error(`${label} is not base64`);\n }\n if (length !== undefined && bytes.length !== length) throw new Error(`${label} is not ${length} bytes`);\n return bytes;\n}\n\n/** The 32 bytes after the nonce in a gate's quote for `agentId` (empty: the TD alone). */\nexport async function agentKeyBinding(\n provisioningPublic: Uint8Array,\n agentId: string,\n signingPublic?: Uint8Array,\n ownerPublic?: Uint8Array,\n): Promise<Uint8Array> {\n const zero = new Uint8Array(32);\n const data = concat(\n utf8(AGENT_ATTEST_DOMAIN),\n provisioningPublic,\n lengthPrefixed(agentId),\n signingPublic ?? zero,\n ownerPublic ?? zero,\n );\n return new Uint8Array(await crypto.subtle.digest('SHA-256', data));\n}\n\n/** HPKE `info` for a message to `agentId` on the gate whose provisioning key is `recipientPublic`. */\nexport function provisionInfo(recipientPublic: Uint8Array, agentId: string): Uint8Array {\n return concat(utf8(AGENT_PROVISION_INFO_DOMAIN), recipientPublic, lengthPrefixed(agentId));\n}\n\n/** A fresh owner key, made here; it never needs to leave the owner. */\nexport async function generateOwnerKey(): Promise<OwnerKey> {\n const secret = crypto.getRandomValues(new Uint8Array(32));\n return { secret, publicKey: await ownerPublicKey(secret) };\n}\n\n/** The base64 public half of an owner's X25519 secret. */\nexport async function ownerPublicKey(secret: Uint8Array): Promise<string> {\n if (secret.length !== 32) throw new Error('An owner key is 32 bytes');\n return toBase64((await x25519KeyPair(secret)).publicKey);\n}\n\nfunction url(gateUrl: string, path: string): string {\n return `${gateUrl.replace(/\\/+$/, '')}${path}`;\n}\n\nasync function postJson(fetchImpl: Fetch, target: string, body: unknown): Promise<unknown> {\n const response = await fetchImpl(target, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n });\n const text = await response.text();\n let parsed: unknown = undefined;\n try {\n parsed = text ? JSON.parse(text) : undefined;\n } catch {\n // Not JSON: reported below with the status.\n }\n if (!response.ok) {\n const error = parsed as { error?: string; details?: string } | undefined;\n throw new AgentGateError(\n `The gate answered ${response.status}${error?.error ? ` ${error.error}` : ''}: ${error?.details ?? text.slice(0, 200)}`,\n response.status,\n error?.error,\n );\n }\n return parsed;\n}\n\nexport interface AttestAgentOptions {\n /** The gate's base URL, or a relay of it (mdma's): only verified quotes are trusted. */\n gateUrl: string;\n /** The agent to attest; omit for the TD alone (no keys, nothing to send to). */\n agentId?: string;\n /** Checks the quote's signature, TCB, image and report data: {@link agentQuoteVerifier}. */\n verifier: VerifyTransportQuote;\n fetch?: Fetch;\n}\n\ninterface AttestResponseBody {\n quoteB64: string;\n provisioningPublicKeyB64: string;\n agentId?: string;\n signingPublicKeyB64?: string;\n ownerPublicKeyB64?: string;\n}\n\n/**\n * Ask the gate for a quote for `agentId` over a fresh nonce and verify it:\n * a genuine quote from a measured agent image, for this nonce, committing to\n * the agent id asked about and to the keys the gate names. Returns those\n * keys only once every check has passed.\n */\nexport async function attestAgent(options: AttestAgentOptions): Promise<VerifiedAgent> {\n const agentId = options.agentId ?? '';\n if (agentId) validateAgentId(agentId);\n const nonce = crypto.getRandomValues(new Uint8Array(32));\n const body = (await postJson(options.fetch ?? fetch, url(options.gateUrl, '/attest'), {\n nonceB64: toBase64(nonce),\n ...(agentId ? { agentId } : {}),\n })) as AttestResponseBody;\n if ((body?.agentId ?? '') !== agentId) {\n throw new Error(`Asked about agent ${JSON.stringify(agentId)}, the gate answered for ${JSON.stringify(body?.agentId)}`);\n }\n const provisioning = fromBase64(body.provisioningPublicKeyB64 ?? '', 'provisioningPublicKeyB64', 32);\n const signing = body.signingPublicKeyB64 ? fromBase64(body.signingPublicKeyB64, 'signingPublicKeyB64', 32) : undefined;\n const owner = body.ownerPublicKeyB64 ? fromBase64(body.ownerPublicKeyB64, 'ownerPublicKeyB64', 32) : undefined;\n if (!signing !== !owner) {\n throw new Error('A claimed agent has both a signing key and an owner; the gate named one');\n }\n // The id asked about, not the one answered: a quote for another agent fails here.\n const binding = await agentKeyBinding(provisioning, agentId, signing, owner);\n await options.verifier({ quoteB64: body.quoteB64, nonce: hex(nonce), reportDataSuffix: hex(binding) });\n return {\n agentId,\n provisioningPublicKey: toBase64(provisioning),\n ...(signing ? { signingPublicKey: toBase64(signing) } : {}),\n ...(owner ? { ownerPublicKey: toBase64(owner) } : {}),\n };\n}\n\n/** The owner key `ownerSecret` may act on `agent`: it is unclaimed, or claimed by that key. */\nexport async function checkOwner(agent: VerifiedAgent, ownerSecret: Uint8Array): Promise<string> {\n const mine = await ownerPublicKey(ownerSecret);\n if (agent.ownerPublicKey && agent.ownerPublicKey !== mine) {\n throw new AgentGateError(\n `This agent is claimed by another key (${agent.ownerPublicKey}); it is not yours. Send it nothing and do not authorize its signing key`,\n undefined,\n 'not_yours',\n );\n }\n return mine;\n}\n\nfunction validateSecrets(secrets: Record<string, string>): void {\n const names = Object.keys(secrets);\n if (names.length === 0) throw new Error('There are no secrets to provision');\n if (names.length > MAX_SECRETS) throw new Error(`At most ${MAX_SECRETS} secrets at once`);\n for (const name of names) {\n if (!SECRET_NAME.test(name)) throw new Error(`Secret name ${JSON.stringify(name)} must match [A-Za-z0-9][A-Za-z0-9_.-]{0,63}`);\n if (typeof secrets[name] !== 'string') throw new Error(`Secret ${name} is not a string`);\n if (utf8(secrets[name]).length > MAX_SECRET_LEN) throw new Error(`Secret ${name} is over ${MAX_SECRET_LEN} bytes`);\n }\n}\n\nasync function sendSealed(\n fetchImpl: Fetch,\n gateUrl: string,\n path: '/provision' | '/release',\n agent: VerifiedAgent,\n ownerSecret: Uint8Array,\n message: unknown,\n): Promise<unknown> {\n if (!agent.agentId) throw new Error('This quote names no agent; attest with the agent id');\n const mine = await checkOwner(agent, ownerSecret);\n const recipient = fromBase64(agent.provisioningPublicKey, 'provisioningPublicKey', 32);\n const sealed = await hpkeSealAuth(\n recipient,\n ownerSecret,\n provisionInfo(recipient, agent.agentId),\n utf8(JSON.stringify(message)),\n );\n return postJson(fetchImpl, url(gateUrl, path), {\n agentId: agent.agentId,\n provisioningPublicKeyB64: agent.provisioningPublicKey,\n senderPublicKeyB64: mine,\n encappedKeyB64: toBase64(sealed.enc),\n ciphertextB64: toBase64(sealed.ciphertext),\n });\n}\n\nexport interface ProvisionAgentOptions {\n gateUrl: string;\n /** What {@link attestAgent} returned for this agent, just now. */\n agent: VerifiedAgent;\n ownerSecret: Uint8Array;\n /** Name to value; a name replaces what was there, others stay. */\n secrets: Record<string, string>;\n /** The verifier `agent` was attested with: the claim is checked by a fresh quote. */\n verifier: VerifyTransportQuote;\n fetch?: Fetch;\n}\n\nexport interface ProvisionedAgent extends Required<VerifiedAgent> {\n written: string[];\n /** Whether this claimed the agent for your key. */\n claimed: boolean;\n}\n\n/**\n * Seal `secrets` to the agent as its owner and send them. The first bundle for\n * an unclaimed agent claims it for `ownerSecret`'s key. The gate's answer is\n * not taken as proof: a fresh quote must name your key as owner, and the\n * agent's signing key must not have changed.\n */\nexport async function provisionAgent(options: ProvisionAgentOptions): Promise<ProvisionedAgent> {\n validateSecrets(options.secrets);\n const fetchImpl = options.fetch ?? fetch;\n const answer = (await sendSealed(fetchImpl, options.gateUrl, '/provision', options.agent, options.ownerSecret, {\n secrets: options.secrets,\n })) as { written?: string[]; claimed?: boolean };\n const after = await attestAgent({ gateUrl: options.gateUrl, agentId: options.agent.agentId, verifier: options.verifier, fetch: fetchImpl });\n const mine = await ownerPublicKey(options.ownerSecret);\n if (after.ownerPublicKey !== mine || !after.signingPublicKey) {\n throw new AgentGateError('The gate accepted the secrets, but its quote does not name your key as owner');\n }\n if (options.agent.signingPublicKey && options.agent.signingPublicKey !== after.signingPublicKey) {\n throw new AgentGateError(\"The agent's signing key changed while provisioning\");\n }\n return {\n agentId: after.agentId,\n provisioningPublicKey: after.provisioningPublicKey,\n signingPublicKey: after.signingPublicKey,\n ownerPublicKey: mine,\n written: answer?.written ?? [],\n claimed: answer?.claimed === true,\n };\n}\n\nexport interface ReleaseAgentOptions {\n gateUrl: string;\n agent: VerifiedAgent;\n ownerSecret: Uint8Array;\n verifier: VerifyTransportQuote;\n fetch?: Fetch;\n}\n\n/**\n * Release the agent as its owner: the gate stops it and erases its claim,\n * keys, secrets and state. Checked by a fresh quote that names no owner.\n */\nexport async function releaseAgent(options: ReleaseAgentOptions): Promise<void> {\n if (!options.agent.ownerPublicKey) throw new Error('This agent is not claimed; there is nothing to release');\n const fetchImpl = options.fetch ?? fetch;\n await sendSealed(fetchImpl, options.gateUrl, '/release', options.agent, options.ownerSecret, { release: true });\n const after = await attestAgent({ gateUrl: options.gateUrl, agentId: options.agent.agentId, verifier: options.verifier, fetch: fetchImpl });\n if (after.ownerPublicKey) {\n throw new AgentGateError('The gate says it released the agent, but its quote still names an owner');\n }\n}\n", "/**\n * Which agent images to trust: a mero-kms release's signed agent allowlist,\n * `kms-agent-attestation-policy.<profile>.json`, and a quote verifier built\n * from it.\n *\n * The KMS release workflow measures the release's agent image and signs its\n * allowlist with cosign keyless, beside the rest of the release. The allowlist\n * can therefore come from anywhere (a release asset, mdma's mirror, a file in\n * the app): {@link verifySignedAgentPolicy} checks the signature here, against\n * the Sigstore trust root embedded in this package, and refuses anything else.\n */\n\nimport { verifyCosignBundle, type SignerIdentity } from '../sealed/sigstore.js';\nimport {\n PRODUCTION_PROFILE,\n createQuoteVerifier,\n type DcapCollateral,\n type DcapVerify,\n type QuoteVerifier,\n} from '../sealed/verify.js';\n\n/** The workflow that signs every mero-kms release, agent allowlists included. */\nexport const KMS_RELEASE_SIGNER: Readonly<SignerIdentity> = Object.freeze({\n identity: 'https://github.com/calimero-network/mero-tee/.github/workflows/release-kms.yaml@refs/heads/master',\n issuer: 'https://token.actions.githubusercontent.com',\n});\n\n/** An agent allowlist, as the KMS release publishes it. Every list must be non-empty. */\nexport interface AgentPolicy {\n schema_version?: number;\n role?: string;\n profile?: string;\n /** The mero-kms release it belongs to. */\n version?: string;\n allowed_tcb_statuses: string[];\n allowed_mrtd: string[];\n allowed_rtmr0: string[];\n allowed_rtmr1: string[];\n allowed_rtmr2: string[];\n allowed_rtmr3: string[];\n}\n\nconst LISTS = [\n 'allowed_tcb_statuses',\n 'allowed_mrtd',\n 'allowed_rtmr0',\n 'allowed_rtmr1',\n 'allowed_rtmr2',\n 'allowed_rtmr3',\n] as const;\n\nexport interface VerifySignedAgentPolicyOptions {\n /** Require this profile; defaults to `locked-read-only`, the only one whose host cannot reach in. */\n profile?: string;\n /** Require the file's `version` to be this mero-kms release. */\n expectedVersion?: string;\n /** The certificate identity required. Defaults to {@link KMS_RELEASE_SIGNER}'s. */\n identity?: string;\n /** The OIDC issuer required. Defaults to {@link KMS_RELEASE_SIGNER}'s. */\n issuer?: string;\n /**\n * The image role the allowlist must be for: `agent` (the default), or\n * `inference`, the release's `kms-inference-attestation-policy.<profile>.json`\n * for its private inference image. Both have the same shape and signer.\n */\n role?: 'agent' | 'inference';\n}\n\n/**\n * Verify an agent allowlist against its cosign bundle, as `cosign verify-blob`\n * would, and return it parsed. Rejects unless it was signed by the KMS release\n * workflow, it is an allowlist for `options.role` (default `agent`) and the profile asked\n * for, every list in it is non-empty, and `expectedVersion`, when given, is its\n * `version`.\n */\nexport async function verifySignedAgentPolicy(\n policy: string | Uint8Array,\n bundle: string | object,\n options: VerifySignedAgentPolicyOptions = {},\n): Promise<AgentPolicy> {\n const body = typeof policy === 'string' ? new TextEncoder().encode(policy) : policy;\n await verifyCosignBundle(body, bundle, {\n identity: options.identity ?? KMS_RELEASE_SIGNER.identity,\n issuer: options.issuer ?? KMS_RELEASE_SIGNER.issuer,\n });\n let parsed: AgentPolicy;\n try {\n parsed = JSON.parse(new TextDecoder().decode(body));\n } catch {\n throw new Error('The signed agent policy is not JSON');\n }\n const role = options.role ?? 'agent';\n if (parsed?.role !== role) {\n throw new Error(`The signed file is a ${JSON.stringify(parsed?.role)} policy, not an ${role} one`);\n }\n const profile = options.profile ?? PRODUCTION_PROFILE;\n if (parsed.profile !== profile) {\n throw new Error(`The signed agent policy is for the ${JSON.stringify(parsed.profile)} profile, not ${profile}`);\n }\n if (options.expectedVersion !== undefined && parsed.version !== options.expectedVersion) {\n throw new Error(`The signed agent policy is release ${JSON.stringify(parsed.version)}, not ${options.expectedVersion}`);\n }\n checkLists(parsed);\n return parsed;\n}\n\nfunction checkLists(policy: AgentPolicy): void {\n for (const list of LISTS) {\n if (!Array.isArray(policy?.[list]) || policy[list].length === 0) {\n // As the gate's own verifier: an empty list accepts nothing.\n throw new Error(`The agent policy's ${list} is empty, so no agent would be accepted`);\n }\n }\n}\n\n/** DCAP's spelling of each TCB status; the policy may use any case. */\nconst TCB_STATUSES = [\n 'UpToDate',\n 'SWHardeningNeeded',\n 'ConfigurationNeeded',\n 'ConfigurationAndSWHardeningNeeded',\n 'OutOfDate',\n 'OutOfDateConfigurationNeeded',\n];\n\nfunction tcbStatus(value: string): string {\n const found = TCB_STATUSES.find((status) => status.toLowerCase() === value.trim().toLowerCase());\n if (!found) throw new Error(`The agent policy allows an unknown TCB status ${JSON.stringify(value)}`);\n return found;\n}\n\nconst register = (value: string) => value.trim().replace(/^0x/i, '');\n\nexport interface AgentQuoteVerifierOptions {\n /** `verify` from `@phala/dcap-qvl`, or anything that verifies a quote the same way. */\n dcapVerify: DcapVerify;\n /**\n * The gate sends no collateral: fetch it, e.g.\n * `(quote) => getCollateral(PHALA_PCCS_URL, quote)` from `@phala/dcap-qvl`.\n */\n fetchCollateral: (quote: Uint8Array) => Promise<DcapCollateral>;\n /** The current time in milliseconds; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\n/**\n * A verifier for {@link attestAgent} that accepts a quote only from an agent\n * image in `policy`: its signature and collateral verify, its TCB status is\n * one the policy allows (never `Revoked`), it is not a debug TD, and each of\n * MRTD and RTMR0-3 is in the policy's list. Mock quotes never pass.\n */\nexport function agentQuoteVerifier(policy: AgentPolicy, options: AgentQuoteVerifierOptions): QuoteVerifier {\n checkLists(policy);\n return createQuoteVerifier({\n dcapVerify: options.dcapVerify,\n fetchCollateral: options.fetchCollateral,\n now: options.now,\n allowedTcbStatuses: policy.allowed_tcb_statuses.map(tcbStatus),\n allowedMrtd: policy.allowed_mrtd.map(register),\n allowedRtmr0: policy.allowed_rtmr0.map(register),\n allowedRtmr1: policy.allowed_rtmr1.map(register),\n allowedRtmr2: policy.allowed_rtmr2.map(register),\n allowedRtmr3: policy.allowed_rtmr3.map(register),\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Mero.js: the JavaScript client for Calimero 1.0, the confidential cloud.\n//\n// `CalimeroClient` verifies a node's TDX attestation, seals every request to\n// it, and signs people in with passkeys and machines with API keys. Everything\n// below it is the pieces it is built from, exported for callers who need one\n// on its own.\n\n// The client, its errors and its types\nexport * from './cloud-v2/index.js';\n\n// Sealed transport: requests encrypted end to end to a TEE node's attested key,\n// and the checks that decide whether a quote is trusted.\nexport * from './sealed/index.js';\n\n// Private agents (mero-tee's agent gate): attest one, claim it with your key,\n// give it its secrets sealed to its TD.\nexport * from './agent-gate/index.js';\n", "/**\n * Byte-level primitives shared by the sealed transport, the attestation check\n * and the agent gate: hex handling, fixed-width integers and concatenation.\n * Internal \u2014 not exported from the package root.\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\n/**\n * Decode hex of an unknown length.\n *\n * The sized {@link fromHex} is the right default \u2014 every key and digest here\n * has a fixed width, and checking it catches a truncated paste at the edge\n * rather than deep inside a signature check. This one exists for the already-\n * encoded structures whose length is genuinely variable: a device certificate,\n * a login statement, a request signature. It still rejects odd-length and\n * non-hex input, so the only check it gives up is the one that cannot apply.\n */\nexport function fromHexUnsized(value: string, label: string): Uint8Array {\n const clean = value.trim();\n if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {\n throw new Error(`${label} must be an even number of hex characters`);\n }\n const bytes = new Uint8Array(clean.length / 2);\n for (let i = 0; i < bytes.length; 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 * The Noise NK handshake (`Noise_NK_25519_AESGCM_SHA256`) that opens a sealed\n * session, written against WebCrypto from the Noise specification\n * (revision 34, http://www.noiseprotocol.org/noise.html). The node runs the\n * other side with `snow`; core's published vectors check the two against each\n * other.\n *\n * NK: the initiator knows the responder's static key in advance \u2014 here the\n * transport key the node's quote commits to \u2014 and sends nothing but an\n * ephemeral key before both ephemerals are mixed in, so everything after the\n * handshake has forward secrecy.\n */\n\nimport { concat } from '../crypto/internal.js';\n\nconst PROTOCOL_NAME = 'Noise_NK_25519_AESGCM_SHA256';\nconst DH_LEN = 32;\nconst TAG_LEN = 16;\n/** PKCS#8 wrapping of a raw X25519 private key (RFC 8410). */\nconst PKCS8_X25519_PREFIX = new Uint8Array([\n 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x04,\n 0x22, 0x04, 0x20,\n]);\n\n/** Noise's `SymmetricState`: the chaining key, the handshake hash and the cipher key. */\nexport class SymmetricState {\n private ck: Uint8Array;\n private h: Uint8Array;\n private k: CryptoKey | null = null;\n private n = 0;\n\n private constructor(h: Uint8Array) {\n this.ck = h;\n this.h = h;\n }\n\n static async initialize(): Promise<SymmetricState> {\n // A name of 32 bytes or fewer is used as the hash, zero-padded.\n const name = new TextEncoder().encode(PROTOCOL_NAME);\n const h = new Uint8Array(32);\n h.set(name);\n return new SymmetricState(h);\n }\n\n async mixHash(data: Uint8Array): Promise<void> {\n this.h = await sha256(concat(this.h, data));\n }\n\n async mixKey(inputKeyMaterial: Uint8Array): Promise<void> {\n const [ck, key] = await hkdf2(this.ck, inputKeyMaterial);\n this.ck = ck;\n this.k = await crypto.subtle.importKey('raw', key, 'AES-GCM', false, ['encrypt', 'decrypt']);\n this.n = 0;\n }\n\n async encryptAndHash(plaintext: Uint8Array): Promise<Uint8Array> {\n if (!this.k) throw new Error('Noise: no cipher key yet');\n const ciphertext = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: noiseNonce(this.n), additionalData: this.h },\n this.k,\n plaintext,\n ),\n );\n this.n += 1;\n await this.mixHash(ciphertext);\n return ciphertext;\n }\n\n async decryptAndHash(ciphertext: Uint8Array): Promise<Uint8Array> {\n if (!this.k) throw new Error('Noise: no cipher key yet');\n const plaintext = new Uint8Array(\n await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: noiseNonce(this.n), additionalData: this.h },\n this.k,\n ciphertext,\n ),\n );\n this.n += 1;\n await this.mixHash(ciphertext);\n return plaintext;\n }\n\n /** The initiator-to-responder key, then the responder-to-initiator key. */\n split(): Promise<[Uint8Array, Uint8Array]> {\n return hkdf2(this.ck, new Uint8Array());\n }\n}\n\nexport interface X25519KeyPair {\n privateKey: CryptoKey;\n publicKey: Uint8Array;\n}\n\n/**\n * Start an NK handshake to `remoteStatic`. `fixedEphemeral` pins the\n * ephemeral secret, for the published test vectors only; leave it out.\n */\nexport async function initiate(\n remoteStatic: Uint8Array,\n prologue: Uint8Array,\n fixedEphemeral?: Uint8Array,\n): Promise<{\n message1: Uint8Array;\n finish(message2: Uint8Array): Promise<{ payload: Uint8Array; split: [Uint8Array, Uint8Array] }>;\n}> {\n const state = await SymmetricState.initialize();\n await state.mixHash(prologue);\n // <- s (known in advance)\n await state.mixHash(remoteStatic);\n // -> e, es\n const ephemeral = await x25519KeyPair(fixedEphemeral);\n await state.mixHash(ephemeral.publicKey);\n await state.mixKey(await dh(ephemeral.privateKey, remoteStatic));\n const message1 = concat(ephemeral.publicKey, await state.encryptAndHash(new Uint8Array()));\n\n return {\n message1,\n async finish(message2) {\n if (message2.length < DH_LEN + TAG_LEN) throw new Error('Noise: message 2 is too short');\n // <- e, ee\n const remoteEphemeral = message2.slice(0, DH_LEN);\n await state.mixHash(remoteEphemeral);\n await state.mixKey(await dh(ephemeral.privateKey, remoteEphemeral));\n const payload = await state.decryptAndHash(message2.slice(DH_LEN));\n return { payload, split: await state.split() };\n },\n };\n}\n\nexport async function x25519KeyPair(secret?: Uint8Array): Promise<X25519KeyPair> {\n if (!secret) {\n let pair: CryptoKeyPair;\n try {\n pair = (await crypto.subtle.generateKey({ name: 'X25519' }, true, [\n 'deriveBits',\n ])) as CryptoKeyPair;\n } catch (error) {\n throw new Error(\n 'Sealed transport needs WebCrypto with X25519, which this runtime lacks ' +\n `(${(error as Error)?.name ?? 'no crypto.subtle'}). Current browsers and Node have ` +\n 'it; in React Native, install react-native-quick-crypto as the global crypto.',\n );\n }\n const publicKey = new Uint8Array(await crypto.subtle.exportKey('raw', pair.publicKey));\n return { privateKey: pair.privateKey, publicKey };\n }\n const privateKey = await crypto.subtle.importKey(\n 'pkcs8',\n concat(PKCS8_X25519_PREFIX, secret),\n { name: 'X25519' },\n true,\n ['deriveBits'],\n );\n const jwk = await crypto.subtle.exportKey('jwk', privateKey);\n return { privateKey, publicKey: base64UrlDecode(jwk.x as string) };\n}\n\nexport async function dh(privateKey: CryptoKey, publicKey: Uint8Array): Promise<Uint8Array> {\n const peer = await crypto.subtle.importKey('raw', publicKey, { name: 'X25519' }, false, []);\n return new Uint8Array(\n await crypto.subtle.deriveBits({ name: 'X25519', public: peer } as EcdhKeyDeriveParams, privateKey, 256),\n );\n}\n\n/** Noise's AESGCM nonce: 32 zero bits, then the counter as a big-endian u64. */\nfunction noiseNonce(n: number): Uint8Array {\n const nonce = new Uint8Array(12);\n new DataView(nonce.buffer).setBigUint64(4, BigInt(n), false);\n return nonce;\n}\n\nasync function sha256(data: Uint8Array): Promise<Uint8Array> {\n return new Uint8Array(await crypto.subtle.digest('SHA-256', data));\n}\n\nasync function hmacSha256(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {\n const hmacKey = await crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, [\n 'sign',\n ]);\n return new Uint8Array(await crypto.subtle.sign('HMAC', hmacKey, data));\n}\n\n/** Noise's `HKDF` with two outputs. */\nasync function hkdf2(chainingKey: Uint8Array, inputKeyMaterial: Uint8Array): Promise<[Uint8Array, Uint8Array]> {\n const temp = await hmacSha256(chainingKey, inputKeyMaterial);\n const first = await hmacSha256(temp, new Uint8Array([1]));\n const second = await hmacSha256(temp, concat(first, new Uint8Array([2])));\n return [first, second];\n}\n\nfunction base64UrlDecode(value: string): Uint8Array {\n const base64 = value.replace(/-/g, '+').replace(/_/g, '/');\n const binary = atob(base64 + '='.repeat((4 - (base64.length % 4)) % 4));\n return Uint8Array.from(binary, (char) => char.charCodeAt(0));\n}\n", "/**\n * Sealed transport: requests encrypted end to end to a TEE node's attested key.\n *\n * A node speaks plain HTTP and any TLS in front of it ends outside the enclave,\n * at whatever proxy or relay the operator runs, so everything crossing that hop\n * (the bearer token, JSON-RPC arguments, results) is readable there. Sealing\n * encrypts it so that only the attested TD can read it, and only the TD can\n * produce a response the client accepts.\n *\n * The client opens a session with a Noise NK handshake to the X25519 transport\n * key the node's quote commits to (`fetchAttestedKey`, `GET /attestation`). The\n * transport key only authenticates the node: the session keys come from both\n * sides' ephemeral keys, so once a session is gone (an hour at most) what was\n * sent in it cannot be opened, not even with the transport key. Each request\n * is sealed under the session; each response streams back in sealed frames, so\n * server-sent events are sealed too. WebSockets cannot be, and the node\n * refuses one inside the envelope with a 501.\n *\n * The node's side, and the wire format this implements byte for byte, are in\n * core's `crates/sealed` (`calimero-sealed`):\n *\n * ```text\n * handshake Noise_NK_25519_AESGCM_SHA256, prologue \"calimero/sealed-http/v2\"\n * request POST /sealed/v2/handshake 0x02 || transport_pk || Noise message 1\n * response 0x02 || Noise message 2 (payload = session_id(16) || lifetime secs, u32 BE)\n * keys (req key, resp key) = Split()\n * exchange POST /sealed/v2\n * header 0x02 || session_id(16) || request_id (u64 BE; from 1, each used once)\n * request header || AES-256-GCM(req key, nonce = request_id || 0u32, aad = header, inner)\n * response frames, each u32 BE length || AES-256-GCM(resp key,\n * nonce = request_id || frame index (u32 BE, from 0), aad = header, kind || data)\n * kind 0 = head (JSON), 1 = body bytes, 2 = end; no end frame = cut short\n * inner u32 BE head length || head (JSON) || body\n * ```\n *\n * `CalimeroClient` seals every request this way; {@link createSealedFetch} is\n * the same channel as a plain `fetch`.\n */\n\nimport { concat } from '../crypto/internal.js';\nimport { initiate } from './noise.js';\nimport type { DcapCollateral } from './verify.js';\n\n/** Where a session is opened, relative to the node's base URL. */\nexport const HANDSHAKE_PATH = '/sealed/v2/handshake';\n/** Where sealed requests are posted, relative to the node's base URL. */\nexport const SEALED_PATH = '/sealed/v2';\n/** Content type of every sealed body. */\nexport const SEALED_CONTENT_TYPE = 'application/vnd.calimero.sealed';\n\nconst VERSION = 2;\nconst PROLOGUE = new TextEncoder().encode('calimero/sealed-http/v2');\nconst SESSION_ID_LEN = 16;\nconst HEADER_LEN = 1 + SESSION_ID_LEN + 8;\nconst FRAME_HEAD = 0;\nconst FRAME_DATA = 1;\nconst FRAME_END = 2;\n/**\n * The largest frame the node sends: a kind byte, at most 64 KiB of data, a tag.\n * Anything larger is refused before it is buffered, so a proxy cannot make the\n * client hold an unbounded frame it has yet to authenticate.\n */\nconst MAX_FRAME_LEN = 1 + 64 * 1024 + 16;\n/** Far more than a handshake reply (69 bytes) ever is. */\nconst MAX_HANDSHAKE_REPLY = 1024;\n/** Open a new session this long before the node would drop the current one. */\nconst RENEW_BEFORE_MS = 60_000;\nconst TRANSPORT_BINDING_DOMAIN = 'calimero.tee-attest.transport-key.v1';\nconst NULL_BODY_STATUSES = [101, 204, 205, 304];\n\nconst utf8 = new TextEncoder();\n\n/** The node no longer holds the transport key this client attested (it restarted). */\nexport class StaleTransportKeyError extends Error {\n name = 'StaleTransportKeyError';\n\n constructor() {\n super('The node no longer holds the attested transport key; attest again for the current one');\n }\n}\n\n/** The node refused the envelope itself, before anything inside it ran. */\nexport class SealedTransportError extends Error {\n name = 'SealedTransportError';\n\n constructor(\n public status: number,\n public code: string | undefined,\n message: string,\n /** How long the node asked to wait before retrying (`Retry-After`), if it did. */\n public retryAfterMs?: number,\n ) {\n super(message);\n }\n}\n\n/**\n * What the attest endpoint puts in report data bytes `32..64` when asked to\n * bind its transport key. `inner` is what would have been there otherwise: the\n * expected application hash, or 32 zero bytes when none was asked for.\n * Mirrors core's `attest_transport_binding`.\n */\nexport async function transportKeyBinding(\n inner: Uint8Array,\n transportKey: Uint8Array,\n): Promise<Uint8Array> {\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n concat(utf8.encode(TRANSPORT_BINDING_DOMAIN), inner, transportKey),\n );\n return new Uint8Array(digest);\n}\n\nexport interface VerifyTransportQuote {\n /**\n * Verify `quoteB64` \u2014 never by asking the node being attested \u2014 and check\n * that its report data is `nonce || reportDataSuffix` (both hex). Resolve\n * true only when the quote is genuine, its measurements are ones you accept,\n * and the report data matches. {@link createQuoteVerifier} does all of this\n * in the page. `collateral` is what the node sent with the quote, when the\n * verifier asked for it.\n */\n (args: {\n quoteB64: string;\n nonce: string;\n reportDataSuffix: string;\n collateral?: DcapCollateral;\n }): Promise<boolean>;\n /**\n * Set by the verifiers this package builds. A Calimero 1.0 node sends no\n * collateral with its quote; the verifier fetches it itself.\n */\n readonly includeCollateral?: boolean;\n}\n\nexport interface SealedFetchOptions {\n /** The node's base URL. */\n baseUrl: string;\n /**\n * The node's attested transport key, or a function that attests and returns\n * it \u2014 typically `() => fetchAttestedKey(baseUrl, policy)`. Given a\n * function, a restarted node is handled: the key is attested again, through\n * your verifier, and the request retried once. Given bytes, a restart\n * surfaces as {@link StaleTransportKeyError}.\n */\n transportPublicKey: Uint8Array | (() => Promise<Uint8Array>);\n /** Fetch that carries the sealed envelope. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\n/**\n * A `fetch` that seals every request to the node's attested transport key.\n *\n * A request for any URL outside `baseUrl` is refused rather than sent in the\n * clear: falling back to plaintext would silently undo the point of sealing.\n */\nexport function createSealedFetch(options: SealedFetchOptions): typeof fetch {\n const base = new URL(options.baseUrl);\n const basePath = base.pathname.replace(/\\/+$/, '');\n const nodeUrl = `${base.origin}${basePath}`;\n const baseFetch = options.fetch ?? ((input, init) => fetch(input, init));\n const attest =\n typeof options.transportPublicKey === 'function' ? options.transportPublicKey : undefined;\n let transportKey: Promise<Uint8Array> = attest\n ? Promise.resolve().then(attest)\n : Promise.resolve(options.transportPublicKey as Uint8Array);\n // Attesting starts now, before any request awaits it. A node that fails to\n // attest must surface on the request that needed the key, not earlier as an\n // unhandled rejection; the failure is still thrown to every awaiter.\n transportKey.catch(() => undefined);\n let session: Promise<Session> | undefined;\n\n const openSession = async (): Promise<Session> => {\n try {\n return await handshake(baseFetch, nodeUrl, await checkedKey(transportKey));\n } catch (error) {\n if (!(error instanceof StaleTransportKeyError) || !attest) throw error;\n transportKey = Promise.resolve().then(attest);\n return handshake(baseFetch, nodeUrl, await checkedKey(transportKey));\n }\n };\n /** The session to use now, and the promise it came from, to name it if it turns out stale. */\n const currentSession = async (): Promise<[Session, Promise<Session>]> => {\n const pending = session ?? renew(undefined);\n const open = await pending;\n if (Date.now() < open.renewAt) return [open, pending];\n const renewed = renew(pending);\n return [await renewed, renewed];\n };\n // Replace the session only if it is still the one found stale, so concurrent\n // requests that all find it stale open one new session between them.\n const renew = (stale: Promise<Session> | undefined): Promise<Session> => {\n if (session === stale) {\n const opening = openSession();\n session = opening;\n opening.catch(() => {\n if (session === opening) session = undefined;\n });\n }\n return session as Promise<Session>;\n };\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = new Request(input, init);\n const url = new URL(request.url);\n if (url.origin !== base.origin || !url.pathname.startsWith(`${basePath}/`)) {\n throw new Error(`Refusing to send ${url.href} outside the sealed node at ${options.baseUrl}`);\n }\n const headers: Array<[string, string]> = [];\n request.headers.forEach((value, name) => headers.push([name, value]));\n const head = { method: request.method, path: url.pathname.slice(basePath.length) + url.search, headers };\n const body = new Uint8Array(await request.arrayBuffer());\n // The caller's own signal, not `request.signal`: a Request's signal follows\n // the one it was built from only through a weak reference (undici), so once\n // the Request is garbage collected (it is, while a stream stays open) an\n // abort no longer reaches the fetch, and an event stream never closes.\n const signal = init?.signal ?? (input instanceof Request ? input.signal : undefined);\n\n const send = async (open: Session): Promise<Response> => {\n const { requestId, header, envelope } = await sealRequest(open, head, body);\n const response = await baseFetch(`${nodeUrl}${SEALED_PATH}`, {\n method: 'POST',\n headers: { 'content-type': SEALED_CONTENT_TYPE },\n body: envelope,\n signal,\n });\n if (response.headers.get('content-type') !== SEALED_CONTENT_TYPE) {\n throw await envelopeRefusal(response);\n }\n return openResponse(response, open.responseKey, header, requestId);\n };\n\n const [open, pending] = await currentSession();\n try {\n return await send(open);\n } catch (error) {\n // The node refused the envelope before running anything in it, so the\n // request can be sent again safely under a new session.\n if (!(error instanceof SealedTransportError) || error.code !== 'unknown_session') throw error;\n return send(await renew(pending));\n }\n };\n}\n\nasync function checkedKey(key: Promise<Uint8Array>): Promise<Uint8Array> {\n const bytes = await key;\n if (bytes.length !== 32) throw new Error('transportPublicKey must be 32 bytes');\n return bytes;\n}\n\nexport interface Session {\n requestKey: CryptoKey;\n responseKey: CryptoKey;\n nextRequestId: number;\n renewAt: number;\n header(requestId: number): Uint8Array;\n}\n\nasync function handshake(\n baseFetch: typeof fetch,\n nodeUrl: string,\n transportKey: Uint8Array,\n): Promise<Session> {\n try {\n return await handshakeOnce(baseFetch, nodeUrl, transportKey);\n } catch (error) {\n // The node limits how fast sessions open. A refused handshake opened\n // nothing, so trying once more after the pause it asks for is safe.\n if (!(error instanceof SealedTransportError) || error.code !== 'busy') throw error;\n await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 1000));\n return handshakeOnce(baseFetch, nodeUrl, transportKey);\n }\n}\n\nasync function handshakeOnce(\n baseFetch: typeof fetch,\n nodeUrl: string,\n transportKey: Uint8Array,\n): Promise<Session> {\n const noise = await initiate(transportKey, PROLOGUE);\n const response = await baseFetch(`${nodeUrl}${HANDSHAKE_PATH}`, {\n method: 'POST',\n headers: { 'content-type': SEALED_CONTENT_TYPE },\n body: concat(new Uint8Array([VERSION]), transportKey, noise.message1),\n });\n if (response.headers.get('content-type') !== SEALED_CONTENT_TYPE) {\n throw await envelopeRefusal(response);\n }\n const reply = await readAtMost(response, MAX_HANDSHAKE_REPLY);\n return sessionFrom(noise, reply);\n}\n\n/** Finish the handshake with the node's reply. Exported for the published vectors. */\nexport async function sessionFrom(\n noise: Awaited<ReturnType<typeof initiate>>,\n reply: Uint8Array,\n): Promise<Session> {\n if (reply[0] !== VERSION) throw new Error('The handshake reply is malformed');\n let finished: Awaited<ReturnType<(typeof noise)['finish']>>;\n try {\n finished = await noise.finish(reply.slice(1));\n } catch {\n throw new Error('The handshake reply did not open: it did not come from the attested node');\n }\n const { payload, split } = finished;\n if (payload.length !== SESSION_ID_LEN + 4) throw new Error('The handshake reply is malformed');\n const sessionId = payload.slice(0, SESSION_ID_LEN);\n const lifetimeSecs = new DataView(payload.buffer, payload.byteOffset).getUint32(SESSION_ID_LEN, false);\n const [requestKey, responseKey] = await Promise.all([\n crypto.subtle.importKey('raw', split[0], 'AES-GCM', false, ['encrypt']),\n crypto.subtle.importKey('raw', split[1], 'AES-GCM', false, ['decrypt']),\n ]);\n split[0].fill(0);\n split[1].fill(0);\n return {\n requestKey,\n responseKey,\n nextRequestId: 1,\n renewAt: Date.now() + lifetimeSecs * 1000 - RENEW_BEFORE_MS,\n header(requestId) {\n const header = new Uint8Array(HEADER_LEN);\n header[0] = VERSION;\n header.set(sessionId, 1);\n new DataView(header.buffer).setBigUint64(1 + SESSION_ID_LEN, BigInt(requestId), false);\n return header;\n },\n };\n}\n\n/** Seal one request under the session's next request id. */\nexport async function sealRequest(\n session: Session,\n head: RequestHead,\n body: Uint8Array,\n): Promise<{ requestId: number; header: Uint8Array; envelope: Uint8Array }> {\n const requestId = session.nextRequestId;\n session.nextRequestId += 1;\n const header = session.header(requestId);\n const sealed = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: nonce(requestId, 0), additionalData: header },\n session.requestKey,\n joinInner(head, body),\n );\n return { requestId, header, envelope: concat(header, new Uint8Array(sealed)) };\n}\n\n/** `request_id || index`, as the node numbers them. */\nfunction nonce(requestId: number, index: number): Uint8Array {\n const bytes = new Uint8Array(12);\n const view = new DataView(bytes.buffer);\n view.setBigUint64(0, BigInt(requestId), false);\n view.setUint32(8, index, false);\n return bytes;\n}\n\nexport interface RequestHead {\n method: string;\n path: string;\n headers: Array<[string, string]>;\n}\n\nexport interface ResponseHead {\n status: number;\n headers: Array<[string, string]>;\n}\n\nfunction joinInner(head: RequestHead, body: Uint8Array): Uint8Array {\n const encoded = utf8.encode(JSON.stringify(head));\n const len = new Uint8Array(4);\n new DataView(len.buffer).setUint32(0, encoded.length, false);\n return concat(len, encoded, body);\n}\n\n/**\n * Open a sealed response as it streams: wait for its head, then hand back a\n * `Response` whose body opens each frame as it arrives. A frame that does not\n * open, arrives out of order, or a stream that stops before its end frame\n * errors the body rather than passing anything unauthenticated on.\n */\nexport async function openResponse(\n response: Response,\n responseKey: CryptoKey,\n header: Uint8Array,\n requestId: number,\n): Promise<Response> {\n if (!response.body) throw new Error('The sealed response has no body');\n const frames = frameReader(response.body.getReader());\n let index = 0;\n const next = async (): Promise<{ kind: number; data: Uint8Array } | null> => {\n const sealed = await frames.next();\n if (!sealed) return null;\n let plain: Uint8Array;\n try {\n plain = new Uint8Array(\n await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: nonce(requestId, index), additionalData: header },\n responseKey,\n sealed,\n ),\n );\n } catch {\n throw new Error('A sealed response frame did not open: it was not sealed by the attested node');\n }\n index += 1;\n return { kind: plain[0], data: plain.slice(1) };\n };\n\n const first = await next();\n if (!first || first.kind !== FRAME_HEAD) throw new Error('The sealed response is malformed');\n const head = JSON.parse(new TextDecoder().decode(first.data)) as ResponseHead;\n if (NULL_BODY_STATUSES.includes(head.status)) {\n await frames.cancel();\n return new Response(null, { status: head.status, headers: head.headers });\n }\n\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const frame = await next();\n if (!frame) {\n controller.error(new Error('The sealed response was cut short'));\n } else if (frame.kind === FRAME_DATA) {\n controller.enqueue(frame.data);\n } else if (frame.kind === FRAME_END) {\n controller.close();\n await frames.cancel();\n } else {\n controller.error(new Error('The sealed response is malformed'));\n }\n } catch (error) {\n controller.error(error);\n }\n },\n cancel() {\n return frames.cancel();\n },\n });\n return new Response(body, { status: head.status, headers: head.headers });\n}\n\n/** Split a byte stream into length-prefixed frames. */\nfunction frameReader(reader: ReadableStreamDefaultReader<Uint8Array>): {\n next(): Promise<Uint8Array | null>;\n cancel(): Promise<void>;\n} {\n let buffer = new Uint8Array();\n const fill = async (length: number): Promise<boolean> => {\n while (buffer.length < length) {\n const { done, value } = await reader.read();\n if (done) return false;\n buffer = concat(buffer, value);\n }\n return true;\n };\n return {\n async next() {\n if (!(await fill(4))) return null;\n const length = new DataView(buffer.buffer, buffer.byteOffset).getUint32(0, false);\n if (length > MAX_FRAME_LEN) {\n await reader.cancel();\n throw new Error('The sealed response is malformed: a frame is larger than the node sends');\n }\n if (!(await fill(4 + length))) return null;\n const frame = buffer.slice(4, 4 + length);\n buffer = buffer.slice(4 + length);\n return frame;\n },\n cancel: () => reader.cancel(),\n };\n}\n\n/** Read a body, refusing one longer than `limit` rather than buffering it. */\nasync function readAtMost(response: Response, limit: number): Promise<Uint8Array> {\n if (!response.body) return new Uint8Array();\n const reader = response.body.getReader();\n let bytes = new Uint8Array();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return bytes;\n bytes = concat(bytes, value);\n if (bytes.length > limit) {\n await reader.cancel();\n throw new Error('The handshake reply is malformed: it is too long');\n }\n }\n}\n\nasync function envelopeRefusal(response: Response): Promise<Error> {\n let code: string | undefined;\n let message = `Sealed request refused: HTTP ${response.status}`;\n try {\n const body = (await response.json()) as { error?: { code?: string; message?: string } };\n code = body?.error?.code;\n if (body?.error?.message) message = `Sealed request refused: ${body.error.message}`;\n } catch {\n // Not the node's JSON refusal \u2014 a proxy's page, most likely. The status is\n // all that can honestly be reported.\n }\n if (code === 'stale_transport_key') return new StaleTransportKeyError();\n const retryAfter = Number(response.headers.get('retry-after'));\n const retryAfterMs =\n Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter, 5) * 1000 : undefined;\n return new SealedTransportError(response.status, code, message, retryAfterMs);\n}\n", "/**\n * The parts of the Sigstore public-good trust root that verifying a mero-tee\n * release's cosign bundle needs: the Fulcio certificate authorities that issue\n * the release workflow's short-lived signing certificates, and the Rekor log\n * key that signs the bundle's signed entry timestamp. Each with the window in\n * which the trust root says it was in use.\n *\n * Copied from the `trusted_root.json` that Sigstore publishes through its TUF\n * repository (https://tuf-repo-cdn.sigstore.dev, target `trusted_root.json`),\n * as shipped by the `sigstore` Python client 4.5.0 in\n * `sigstore/_store/https%3A%2F%2Ftuf-repo-cdn.sigstore.dev/trusted_root.json`.\n * Embedded rather than fetched: fetching it at run time would trust whoever\n * serves it, the very thing this check exists to avoid.\n *\n * Left out, because a legacy cosign bundle never uses them: the CT logs (the\n * certificate's SCT is not checked here, as core does not either), the\n * timestamp authority, and the Rekor v2 log `log2025-1.rekor.sigstore.dev`,\n * whose Ed25519 key signs checkpoints rather than signed entry timestamps. A\n * bundle that names any log but those below is refused.\n *\n * To refresh it when Sigstore rotates a key or adds a CA: take the current\n * `trusted_root.json` from a TUF client (`python -m sigstore` or `cosign\n * initialize` both keep one, verified against the TUF root), and copy each\n * `certificateAuthorities[].certChain.certificates[].rawBytes` with its\n * `validFor`, and each ECDSA `tlogs[]` entry's `publicKey.rawBytes`,\n * `publicKey.validFor` and `logId.keyId` (as hex). The tests check each log id\n * is the SHA-256 of its key and each chain verifies.\n */\n\n/** A Fulcio CA: its chain from the certificate that issues leaves up to the root, DER as base64. */\nexport interface FulcioAuthority {\n uri: string;\n /** When the trust root says this CA issued certificates. No `end`: it still does. */\n validFor: { start: string; end?: string };\n certChain: string[];\n}\n\n/** A Rekor log whose signed entry timestamps are accepted. */\nexport interface RekorLog {\n baseUrl: string;\n /** The log id a bundle names it by: the SHA-256 of its public key, hex. */\n logId: string;\n /** Its public key: DER SubjectPublicKeyInfo, base64. ECDSA P-256 with SHA-256. */\n publicKey: string;\n validFor: { start: string; end?: string };\n}\n\nexport const FULCIO_AUTHORITIES: readonly FulcioAuthority[] = [\n {\n uri: 'https://fulcio.sigstore.dev',\n validFor: { start: '2021-03-07T03:20:29Z', end: '2022-12-31T23:59:59.999Z' },\n certChain: [\n 'MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9y' +\n 'ZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIxMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UE' +\n 'ChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSyA7Ii5k+p' +\n 'NO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0JcastaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+' +\n '2Yfswe/QuLolRUCrcOE2+2iA5+tzd6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYD' +\n 'VR0OBBYEFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2uSu1KBtPsMAoGCCqG' +\n 'SM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJxVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjR' +\n 'ay5/aj/jsKKGIkmQatjI8uupHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ==',\n ],\n },\n {\n uri: 'https://fulcio.sigstore.dev',\n validFor: { start: '2022-04-13T20:06:15Z' },\n certChain: [\n 'MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3Rv' +\n 'cmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNV' +\n 'BAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EE' +\n 'ACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798' +\n 'LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAww' +\n 'CgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYD' +\n 'VR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfx' +\n 'Xx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsP' +\n 'mygUY7Ii2zbdCdliiow=',\n 'MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3Rv' +\n 'cmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNV' +\n 'BAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3' +\n 'PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS' +\n '5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud' +\n 'DgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjO' +\n 'PQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9' +\n 'ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ',\n ],\n },\n];\n\nexport const REKOR_LOGS: readonly RekorLog[] = [\n {\n baseUrl: 'https://rekor.sigstore.dev',\n logId: 'c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d',\n publicKey:\n 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwrkBbmLSGtks4L3qX6yYY0zufB' +\n 'nhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==',\n validFor: { start: '2021-01-12T11:53:27Z' },\n },\n];\n", "/**\n * Just enough DER and X.509 to check a Sigstore signing certificate with\n * WebCrypto: read a certificate's signed part, validity, key and extensions,\n * and verify the ECDSA signatures (P-256 and P-384) Sigstore uses.\n *\n * Written here, rather than taken from a library, so the SDK keeps no runtime\n * dependencies and runs wherever WebCrypto does. It parses strictly and throws\n * on anything it does not expect; it is not a general X.509 implementation.\n */\n\nconst SEQUENCE = 0x30;\nconst OID = 0x06;\nconst INTEGER = 0x02;\nconst BIT_STRING = 0x03;\nconst OCTET_STRING = 0x04;\nconst BOOLEAN = 0x01;\nconst UTC_TIME = 0x17;\nconst GENERALIZED_TIME = 0x18;\nconst CONTEXT_0 = 0xa0;\nconst CONTEXT_3 = 0xa3;\n\nconst EC_PUBLIC_KEY = '1.2.840.10045.2.1';\nconst CURVES: Record<string, Curve> = {\n '1.2.840.10045.3.1.7': 'P-256',\n '1.3.132.0.34': 'P-384',\n};\nconst CURVE_SIZE: Record<Curve, number> = { 'P-256': 32, 'P-384': 48 };\n/** The certificate signature algorithms accepted: ECDSA with SHA-256 or SHA-384. */\nconst SIGNATURE_HASHES: Record<string, Hash> = {\n '1.2.840.10045.4.3.2': 'SHA-256',\n '1.2.840.10045.4.3.3': 'SHA-384',\n};\n\nexport type Curve = 'P-256' | 'P-384';\nexport type Hash = 'SHA-256' | 'SHA-384';\n\n/** One DER element: its tag, and where it and its contents lie in `bytes`. */\nexport interface Element {\n tag: number;\n bytes: Uint8Array;\n /** Offset of the element's first (tag) byte. */\n offset: number;\n /** Offset of its contents. */\n start: number;\n /** Offset just past it. */\n end: number;\n}\n\nfunction read(bytes: Uint8Array, offset: number, limit: number): Element {\n if (offset + 2 > limit) throw new Error('it is truncated');\n const tag = bytes[offset];\n if ((tag & 0x1f) === 0x1f) throw new Error('it uses a tag this parser does not read');\n let length = bytes[offset + 1];\n let start = offset + 2;\n if (length & 0x80) {\n const count = length & 0x7f;\n if (count === 0 || count > 4 || start + count > limit) throw new Error('it has a length this parser does not read');\n length = 0;\n for (let i = 0; i < count; i += 1) length = length * 256 + bytes[start + i];\n start += count;\n }\n const end = start + length;\n if (end > limit) throw new Error('it is truncated');\n return { tag, bytes, offset, start, end };\n}\n\n/** Parse one complete DER element, refusing trailing bytes. */\nexport function parseDer(bytes: Uint8Array): Element {\n const element = read(bytes, 0, bytes.length);\n if (element.end !== bytes.length) throw new Error('it has trailing bytes');\n return element;\n}\n\nexport function children(element: Element): Element[] {\n const out: Element[] = [];\n for (let offset = element.start; offset < element.end; ) {\n const child = read(element.bytes, offset, element.end);\n out.push(child);\n offset = child.end;\n }\n return out;\n}\n\n/** `element` if it has `tag`; otherwise throws naming `what`. */\nexport function expectTag(element: Element | undefined, tag: number, what: string): Element {\n if (!element || element.tag !== tag) throw new Error(`${what} is not where it should be`);\n return element;\n}\n\nexport function contents(element: Element): Uint8Array {\n return element.bytes.slice(element.start, element.end);\n}\n\n/** The whole element, header included. */\nfunction whole(element: Element): Uint8Array {\n return element.bytes.slice(element.offset, element.end);\n}\n\nfunction oid(element: Element | undefined): string {\n const value = contents(expectTag(element, OID, 'An object identifier'));\n if (value.length === 0 || value[value.length - 1] & 0x80) throw new Error('it has a malformed object identifier');\n const arcs: number[] = [];\n let arc = 0;\n for (const byte of value) {\n arc = arc * 128 + (byte & 0x7f);\n if (!(byte & 0x80)) {\n arcs.push(arc);\n arc = 0;\n }\n }\n const first = arcs.shift() as number;\n const head = first < 80 ? [Math.floor(first / 40), first % 40] : [2, first - 80];\n return [...head, ...arcs].join('.');\n}\n\nfunction time(element: Element): number {\n const text = new TextDecoder().decode(contents(element));\n const utc = element.tag === UTC_TIME ? /^(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})Z$/.exec(text) : null;\n const generalized =\n element.tag === GENERALIZED_TIME ? /^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})Z$/.exec(text) : null;\n const parts = utc ?? generalized;\n if (!parts) throw new Error(`it holds the time ${JSON.stringify(text)}, which is not one a certificate may hold`);\n let year = Number(parts[1]);\n if (utc) year += year < 50 ? 2000 : 1900;\n const [month, day, hour, minute, second] = parts.slice(2).map(Number);\n return Date.UTC(year, month - 1, day, hour, minute, second);\n}\n\nexport interface Certificate {\n der: Uint8Array;\n /** The signed part, exactly as the issuer signed it. */\n tbs: Uint8Array;\n /** The hash of the ECDSA signature the issuer made over `tbs`. */\n signatureHash: Hash;\n /** That signature, DER. */\n signature: Uint8Array;\n /** The issuer and subject names, DER, to compare byte for byte. */\n issuer: Uint8Array;\n subject: Uint8Array;\n /** Validity, in milliseconds since the epoch, both ends inclusive. */\n notBefore: number;\n notAfter: number;\n /** The subject's key, DER SubjectPublicKeyInfo, and its curve. */\n spki: Uint8Array;\n curve: Curve;\n /** Each extension's value (the contents of its OCTET STRING), by object identifier. */\n extensions: Map<string, Uint8Array>;\n}\n\n/**\n * Parse a DER X.509 certificate with an ECDSA key, signed with ECDSA. Throws\n * naming what is wrong.\n */\nexport function parseCertificate(der: Uint8Array): Certificate {\n try {\n const [tbsElement, algorithm, signature, ...rest] = children(\n expectTag(parseDer(der), SEQUENCE, 'The certificate'),\n );\n if (rest.length > 0) throw new Error('it has fields after its signature');\n const fields = children(expectTag(tbsElement, SEQUENCE, 'The signed part'));\n // `version` is [0] EXPLICIT; everything after it is positional.\n const first = fields[0]?.tag === CONTEXT_0 ? 1 : 0;\n const [serial, innerAlgorithm, issuer, validity, subject, spki, ...optional] = fields.slice(first);\n expectTag(serial, INTEGER, 'The serial number');\n\n const algorithmId = oid(children(expectTag(algorithm, SEQUENCE, 'The signature algorithm'))[0]);\n const innerId = oid(children(expectTag(innerAlgorithm, SEQUENCE, 'The signature algorithm'))[0]);\n if (innerId !== algorithmId) throw new Error('it names two different signature algorithms');\n const signatureHash = SIGNATURE_HASHES[algorithmId];\n if (!signatureHash) throw new Error(`it is signed with ${algorithmId}, not ECDSA with SHA-256 or SHA-384`);\n\n const [notBefore, notAfter] = children(expectTag(validity, SEQUENCE, 'The validity')).map(time);\n if (notAfter === undefined) throw new Error('its validity is incomplete');\n\n const [keyAlgorithm, keyBits] = children(expectTag(spki, SEQUENCE, 'The public key'));\n expectTag(keyBits, BIT_STRING, 'The public key');\n const [keyType, keyCurve] = children(expectTag(keyAlgorithm, SEQUENCE, 'The key algorithm'));\n if (oid(keyType) !== EC_PUBLIC_KEY) throw new Error('its key is not an elliptic-curve key');\n const curve = CURVES[oid(keyCurve)];\n if (!curve) throw new Error('its key is on a curve other than P-256 or P-384');\n\n const extensions = new Map<string, Uint8Array>();\n const extensionsField = optional.find((field) => field.tag === CONTEXT_3);\n if (extensionsField) {\n const [list] = children(extensionsField);\n for (const extension of children(expectTag(list, SEQUENCE, 'The extensions'))) {\n const parts = children(expectTag(extension, SEQUENCE, 'An extension'));\n if (parts.length === 3) expectTag(parts[1], BOOLEAN, 'An extension\\'s critical flag');\n else if (parts.length !== 2) throw new Error('it has a malformed extension');\n const id = oid(parts[0]);\n if (extensions.has(id)) throw new Error(`it has extension ${id} twice`);\n extensions.set(id, contents(expectTag(parts[parts.length - 1], OCTET_STRING, 'An extension value')));\n }\n }\n\n const signatureBits = contents(expectTag(signature, BIT_STRING, 'The signature'));\n if (signatureBits[0] !== 0) throw new Error('its signature is not a whole number of bytes');\n return {\n der,\n tbs: whole(tbsElement),\n signatureHash,\n signature: signatureBits.slice(1),\n issuer: whole(expectTag(issuer, SEQUENCE, 'The issuer')),\n subject: whole(expectTag(subject, SEQUENCE, 'The subject')),\n notBefore,\n notAfter,\n spki: whole(spki),\n curve,\n extensions,\n };\n } catch (error) {\n throw new Error(`The certificate is malformed: ${(error as Error).message}`);\n }\n}\n\n/** The object identifiers in a DER `SEQUENCE OF OBJECT IDENTIFIER` (an extended key usage). */\nexport function objectIdentifiers(der: Uint8Array): string[] {\n return children(expectTag(parseDer(der), SEQUENCE, 'The list')).map(oid);\n}\n\n/**\n * An ECDSA signature as WebCrypto takes it (IEEE P1363: `r || s`, each the\n * curve's size), from the DER `SEQUENCE { r INTEGER, s INTEGER }` X.509 and\n * cosign use.\n */\nexport function ecdsaSignatureToP1363(der: Uint8Array, curve: Curve): Uint8Array {\n const size = CURVE_SIZE[curve];\n const integers = children(expectTag(parseDer(der), SEQUENCE, 'The signature'));\n if (integers.length !== 2) throw new Error('The signature is not an ECDSA signature');\n const out = new Uint8Array(size * 2);\n integers.forEach((integer, index) => {\n let value = contents(expectTag(integer, INTEGER, 'The signature'));\n // r and s are positive: a set top bit with no leading zero is a negative number.\n if (value.length === 0 || value[0] & 0x80) throw new Error('The signature is not an ECDSA signature');\n while (value.length > 1 && value[0] === 0) value = value.subarray(1);\n if (value.length > size) throw new Error('The signature is not an ECDSA signature');\n out.set(value, index * size + size - value.length);\n });\n return out;\n}\n\n/** Verify a DER ECDSA `signature` over `data` with a DER SubjectPublicKeyInfo key. */\nexport async function verifyEcdsa(\n spki: Uint8Array,\n curve: Curve,\n hash: Hash,\n signature: Uint8Array,\n data: Uint8Array,\n): Promise<boolean> {\n let p1363: Uint8Array;\n try {\n p1363 = ecdsaSignatureToP1363(signature, curve);\n } catch {\n return false;\n }\n const key = await crypto.subtle.importKey('spki', spki, { name: 'ECDSA', namedCurve: curve }, false, ['verify']);\n return crypto.subtle.verify({ name: 'ECDSA', hash }, key, p1363, data);\n}\n\n/** Decode base64 (standard alphabet), refusing anything else. */\nexport function fromBase64(value: string, what: string): Uint8Array {\n const clean = value.replace(/\\s+/g, '');\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(clean) || clean.length % 4 !== 0) {\n throw new Error(`${what} is not base64`);\n }\n const binary = atob(clean);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\n/** The DER of the one `CERTIFICATE` block a PEM holds. */\nexport function pemCertificate(pem: string, what: string): Uint8Array {\n const blocks = [...pem.matchAll(/-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g)];\n if (blocks.length !== 1 || pem.replace(blocks[0][0], '').trim() !== '') {\n throw new Error(`${what} is not exactly one PEM certificate`);\n }\n return fromBase64(blocks[0][1], what);\n}\n", "/**\n * Verifying a cosign keyless signature, as `cosign verify-blob --bundle` does,\n * with WebCrypto and the Sigstore trust root embedded in this package.\n *\n * mero-tee signs each release asset with cosign keyless: there is no release\n * key, only a Fulcio certificate that lives ten minutes, issued to one GitHub\n * Actions workflow run, and a Rekor log entry that proves the signature was\n * made while the certificate was valid. So the checks are: the signature over\n * the bytes verifies with the certificate's key; Rekor's signed entry\n * timestamp verifies, and the entry it signs is this signature over these\n * bytes by this certificate; the certificate chains to a Fulcio CA and was\n * valid when Rekor logged it; and the certificate names the workflow expected.\n * The same checks core runs in `crates/tee-release/src/sigstore_verify.rs`.\n *\n * Nothing here reads the clock. Every time is Rekor's `integratedTime`, which\n * its signature covers, so a verification that passes once passes forever,\n * whatever the client's clock says.\n */\n\nimport { hex } from '../crypto/internal.js';\nimport { FULCIO_AUTHORITIES, REKOR_LOGS } from './sigstore-trust-root.js';\nimport {\n children,\n contents,\n expectTag,\n fromBase64,\n objectIdentifiers,\n parseCertificate,\n parseDer,\n pemCertificate,\n verifyEcdsa,\n type Certificate,\n} from './x509.js';\n\nconst SUBJECT_ALT_NAME = '2.5.29.17';\nconst EXTENDED_KEY_USAGE = '2.5.29.37';\nconst CODE_SIGNING = '1.3.6.1.5.5.7.3.3';\n/** Fulcio's OIDC issuer extension, a DER UTF8String. */\nconst FULCIO_ISSUER_V2 = '1.3.6.1.4.1.57264.1.8';\n/** Its deprecated predecessor, the raw issuer bytes; read only when the other is absent. */\nconst FULCIO_ISSUER_V1 = '1.3.6.1.4.1.57264.1.1';\nconst SAN_URI = 0x86;\nconst UTF8_STRING = 0x0c;\nconst SEQUENCE = 0x30;\n\nconst utf8 = new TextEncoder();\n// Not `fatal`: not every runtime's TextDecoder takes options. A malformed byte\n// decodes to U+FFFD, which no pinned identity holds, so it can only fail a match.\nconst fromUtf8 = (bytes: Uint8Array) => new TextDecoder().decode(bytes);\n\n/** Who must have signed: the certificate's SAN URI and its OIDC issuer, each matched exactly. */\nexport interface SignerIdentity {\n identity: string;\n issuer: string;\n}\n\n/** A legacy cosign bundle (`cosign sign-blob --bundle`), as the fields verified here. */\ninterface CosignBundle {\n base64Signature: string;\n cert: string;\n rekorBundle: {\n SignedEntryTimestamp: string;\n Payload: { body: string; integratedTime: number; logIndex: number; logID: string };\n };\n}\n\n/**\n * Verify a cosign keyless `bundle` over `body`, signed by `signer`. Resolves\n * with the time Rekor logged it (seconds); rejects with the reason otherwise.\n * `signature`, when given, is the detached `.sig` published beside the file,\n * and must be the bundle's.\n */\nexport async function verifyCosignBundle(\n body: Uint8Array,\n bundle: unknown,\n signer: SignerIdentity,\n signature?: string,\n): Promise<{ integratedTime: number }> {\n const { base64Signature, cert, rekorBundle } = cosignBundle(bundle);\n const payload = rekorBundle.Payload;\n if (signature !== undefined && signature.trim() !== base64Signature.trim()) {\n throw new Error('The detached signature is not the one in the bundle');\n }\n const sig = fromBase64(base64Signature, 'The bundle signature');\n const leafDer = pemCertificate(fromUtf8(fromBase64(cert, 'The bundle certificate')), 'The bundle certificate');\n const leaf = parseCertificate(leafDer);\n\n // Rekor vouches for the entry and its time: nothing below is trusted before this.\n const log = REKOR_LOGS.find((candidate) => candidate.logId === payload.logID.toLowerCase());\n if (!log) throw new Error(`The bundle names Rekor log ${payload.logID}, which the Sigstore trust root does not know`);\n const canonical = utf8.encode(\n `{\"body\":${JSON.stringify(payload.body)},\"integratedTime\":${payload.integratedTime},` +\n `\"logID\":${JSON.stringify(payload.logID)},\"logIndex\":${payload.logIndex}}`,\n );\n const setVerifies = await verifyEcdsa(\n fromBase64(log.publicKey, 'The Rekor key'),\n 'P-256',\n 'SHA-256',\n fromBase64(rekorBundle.SignedEntryTimestamp, 'The signed entry timestamp'),\n canonical,\n );\n if (!setVerifies) {\n throw new Error(\"Rekor's signed entry timestamp does not verify: the log entry, its time or its index was altered\");\n }\n const at = payload.integratedTime * 1000;\n if (!within(at, log.validFor)) {\n throw new Error(`Rekor log ${log.baseUrl} was not in use at ${iso(at)}, when the entry says it was logged`);\n }\n\n // The entry Rekor signed is this signature, over these bytes, by this certificate.\n const entry = hashedRekord(payload.body);\n const digest = hex(new Uint8Array(await crypto.subtle.digest('SHA-256', body)));\n if (entry.hash !== digest) throw new Error(\"The file's SHA-256 is not the one Rekor logged: the file is not the one signed\");\n if (!equal(fromBase64(entry.signature, 'The logged signature'), sig)) {\n throw new Error(\"The bundle's signature is not the one Rekor logged\");\n }\n const loggedCert = pemCertificate(fromUtf8(fromBase64(entry.publicKey, 'The logged certificate')), 'The logged certificate');\n if (!equal(loggedCert, leafDer)) throw new Error(\"The bundle's certificate is not the one Rekor logged\");\n\n if (leaf.curve !== 'P-256' || !(await verifyEcdsa(leaf.spki, 'P-256', 'SHA-256', sig, body))) {\n throw new Error(\"The signature over the file does not verify with the bundle's certificate\");\n }\n\n await chainsToFulcio(leaf, at);\n checkSigner(leaf, signer);\n return { integratedTime: payload.integratedTime };\n}\n\n/**\n * Check that `leaf` was issued by a Fulcio CA in the trust root, and that it,\n * the CA's certificates and the CA itself (by the trust root's `validFor`)\n * were all valid at `at` (milliseconds): when Rekor logged the signature, not\n * now, since a Fulcio certificate lives ten minutes. Every signature on the\n * way is checked, with the algorithm its certificate names.\n */\nexport async function chainsToFulcio(leaf: Certificate, at: number): Promise<void> {\n if (!validAt(leaf, at)) {\n throw new Error(\n `The signing certificate was valid ${iso(leaf.notBefore)} to ${iso(leaf.notAfter)}, not at ${iso(at)} when Rekor logged it`,\n );\n }\n const reasons: string[] = [];\n for (const authority of FULCIO_AUTHORITIES) {\n const chain = authority.certChain.map((der) => parseCertificate(fromBase64(der, 'A Fulcio certificate')));\n if (!(await issuedBy(leaf, chain[0]))) continue;\n // The issuer is found; from here a failure is this CA's, so say which.\n const reason = await authorityRefusal(chain, authority.validFor, at);\n if (!reason) return;\n reasons.push(`${authority.uri} (valid from ${authority.validFor.start}): ${reason}`);\n }\n throw new Error(\n reasons.length > 0\n ? `The signing certificate's CA is not trusted at ${iso(at)}: ${reasons.join('; ')}`\n : 'The signing certificate was not issued by a Fulcio CA in the Sigstore trust root',\n );\n}\n\nasync function authorityRefusal(\n chain: Certificate[],\n validFor: { start: string; end?: string },\n at: number,\n): Promise<string | undefined> {\n if (!within(at, validFor)) return 'the trust root says it was not issuing certificates then';\n for (const [index, certificate] of chain.entries()) {\n if (!validAt(certificate, at)) return `its certificate ${index} was not valid then`;\n const parent = chain[index + 1] ?? certificate; // the root signs itself\n if (!(await issuedBy(certificate, parent))) return `its certificate ${index} is not signed by the next`;\n }\n return undefined;\n}\n\nasync function issuedBy(child: Certificate, parent: Certificate): Promise<boolean> {\n if (!equal(child.issuer, parent.subject)) return false;\n return verifyEcdsa(parent.spki, parent.curve, child.signatureHash, child.signature, child.tbs);\n}\n\nfunction checkSigner(leaf: Certificate, signer: SignerIdentity): void {\n const san = leaf.extensions.get(SUBJECT_ALT_NAME);\n if (!san) throw new Error('The signing certificate names no identity');\n const names = children(expectTag(parseDer(san), SEQUENCE, 'The subject alternative name'));\n const uris = names.filter((name) => name.tag === SAN_URI).map((name) => fromUtf8(contents(name)));\n if (uris.length !== 1 || names.length !== 1 || uris[0] !== signer.identity) {\n throw new Error(\n `The release was signed by ${JSON.stringify(uris.length === 1 ? uris[0] : uris)}, not by ${signer.identity}`,\n );\n }\n\n const v2 = leaf.extensions.get(FULCIO_ISSUER_V2);\n const v1 = leaf.extensions.get(FULCIO_ISSUER_V1);\n const issuer = v2\n ? fromUtf8(contents(expectTag(parseDer(v2), UTF8_STRING, 'The OIDC issuer')))\n : v1\n ? fromUtf8(v1)\n : undefined;\n if (issuer !== signer.issuer) {\n throw new Error(\n `The signing certificate's OIDC issuer is ${issuer === undefined ? 'missing' : JSON.stringify(issuer)}, not ${signer.issuer}`,\n );\n }\n\n const usage = leaf.extensions.get(EXTENDED_KEY_USAGE);\n if (!usage || !objectIdentifiers(usage).includes(CODE_SIGNING)) {\n throw new Error('The signing certificate is not for code signing');\n }\n}\n\nfunction cosignBundle(value: unknown): CosignBundle {\n let bundle = value;\n if (typeof bundle === 'string') {\n try {\n bundle = JSON.parse(bundle);\n } catch {\n throw new Error('The bundle is not JSON');\n }\n }\n const b = bundle as Partial<CosignBundle> | null;\n const p = b?.rekorBundle?.Payload;\n const ok =\n typeof b?.base64Signature === 'string' &&\n typeof b.cert === 'string' &&\n typeof b.rekorBundle?.SignedEntryTimestamp === 'string' &&\n typeof p?.body === 'string' &&\n typeof p.logID === 'string' &&\n /^[0-9a-fA-F]{64}$/.test(p.logID) &&\n Number.isSafeInteger(p.integratedTime) &&\n p.integratedTime >= 0 &&\n Number.isSafeInteger(p.logIndex) &&\n p.logIndex >= 0;\n if (!ok) throw new Error('The bundle is not a cosign bundle with a Rekor entry');\n return b as CosignBundle;\n}\n\n/** The fields of a logged `hashedrekord` entry that are compared. */\nfunction hashedRekord(body: string): { hash: string; signature: string; publicKey: string } {\n let entry: {\n kind?: unknown;\n spec?: {\n data?: { hash?: { algorithm?: unknown; value?: unknown } };\n signature?: { content?: unknown; publicKey?: { content?: unknown } };\n };\n };\n try {\n entry = JSON.parse(fromUtf8(fromBase64(body, 'The logged entry')));\n } catch {\n throw new Error('The logged entry is not JSON');\n }\n const hash = entry?.spec?.data?.hash;\n const signature = entry?.spec?.signature;\n if (\n entry?.kind !== 'hashedrekord' ||\n hash?.algorithm !== 'sha256' ||\n typeof hash.value !== 'string' ||\n typeof signature?.content !== 'string' ||\n typeof signature.publicKey?.content !== 'string'\n ) {\n throw new Error('The logged entry is not a SHA-256 hashedrekord');\n }\n return { hash: hash.value.toLowerCase(), signature: signature.content, publicKey: signature.publicKey.content };\n}\n\nfunction validAt(certificate: Certificate, at: number): boolean {\n return certificate.notBefore <= at && at <= certificate.notAfter;\n}\n\nfunction within(at: number, window: { start: string; end?: string }): boolean {\n return Date.parse(window.start) <= at && (window.end === undefined || at <= Date.parse(window.end));\n}\n\nfunction iso(ms: number): string {\n return new Date(ms).toISOString();\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n return a.length === b.length && a.every((byte, index) => byte === b[index]);\n}\n", "/**\n * Verifying a TEE node's quote in the page, before trusting the key it binds.\n *\n * A quote proves what runs in a TD only once it has been checked: its\n * signatures against Intel's root, the TCB status of the platform, the\n * measurements of the image, and that its report data is the nonce and the\n * binding this client asked for. {@link createQuoteVerifier} does all of that\n * here. A Calimero 1.0 node sends no collateral: the verifier fetches Intel's\n * (`fetchCollateral`), which the node can neither forge nor choose.\n *\n * The DCAP verification itself \u2014 parsing the quote, checking its signature\n * chain and appraising its TCB level against the collateral \u2014 comes from a\n * library you pass in, normally `verify` from `@phala/dcap-qvl`, a pure\n * JavaScript implementation that runs in browsers, Node and React Native. It\n * is passed in rather than bundled so this SDK keeps no runtime dependencies,\n * and applications that never talk to a TEE node pay nothing for it.\n */\n\nimport { hex } from '../crypto/internal.js';\nimport type { VerifyTransportQuote } from './sealed.js';\n\n/**\n * The collateral a quote is verified against \u2014 TCB info, QE identity, CRLs and\n * their chains \u2014 in dcap-qvl's form: byte fields are hex strings or byte\n * arrays. What `@phala/dcap-qvl`'s `getCollateral` fetches.\n */\nexport interface DcapCollateral {\n pck_crl_issuer_chain: string;\n root_ca_crl: number[] | string;\n pck_crl: number[] | string;\n tcb_info_issuer_chain: string;\n tcb_info: string;\n tcb_info_signature: number[] | string;\n qe_identity_issuer_chain: string;\n qe_identity: string;\n qe_identity_signature: number[] | string;\n}\n\n/** The fields of a TDX report this verifier reads. */\ninterface TdReport {\n mrTd: Uint8Array;\n rtMr0: Uint8Array;\n rtMr1: Uint8Array;\n rtMr2: Uint8Array;\n rtMr3: Uint8Array;\n reportData: Uint8Array;\n tdAttributes?: Uint8Array;\n}\n\n/** What a DCAP verifier returns for a quote whose signature chain verified. */\nexport interface DcapVerifiedReport {\n status: string;\n advisory_ids?: string[];\n report: { type: string; data: unknown };\n}\n\n/**\n * Verify a quote's signature chain against `collateral` as of `nowSecs`, and\n * appraise its TCB level. Throws when it does not verify. `verify` from\n * `@phala/dcap-qvl` has exactly this shape.\n */\nexport type DcapVerify = (\n quote: Uint8Array,\n collateral: DcapCollateral,\n nowSecs: number,\n) => DcapVerifiedReport;\n\n/**\n * One image's measurements, all five registers, hex. A quote matches it only\n * when every register does, so measurements of different images never combine.\n */\nexport interface TrustedMeasurements {\n mrtd: string;\n rtmr0: string;\n rtmr1: string;\n rtmr2: string;\n rtmr3: string;\n}\n\nexport interface QuoteVerifierOptions {\n /** DCAP verification: `verify` from `@phala/dcap-qvl`. */\n dcapVerify: DcapVerify;\n /**\n * The images trusted, each by all of its measurements. The way to say which\n * code may read the traffic: build it with {@link trustedMeasurementsFromReleases}\n * from the `published-mrtds.json` of the releases you trust.\n */\n allowedMeasurements?: TrustedMeasurements[];\n /**\n * MRTDs (hex) accepted. On its own this does not name an image: on GCP the\n * MRTD measures the platform's TD firmware, which every image shares, and\n * the image is in RTMR1\u20133. So a verifier needs either\n * {@link allowedMeasurements}, or this with all of `allowedRtmr1`\u2013`3`.\n */\n allowedMrtd?: string[];\n /** RTMR allowlists (hex); a register is not checked when its list is left out. */\n allowedRtmr0?: string[];\n allowedRtmr1?: string[];\n allowedRtmr2?: string[];\n allowedRtmr3?: string[];\n /**\n * TCB statuses accepted. Defaults to `['UpToDate']`. `Revoked` is refused\n * even when listed.\n */\n allowedTcbStatuses?: string[];\n /**\n * Where to get collateral (a Calimero 1.0 node sends none): for example\n * `(quote) => getCollateral(PHALA_PCCS_URL, quote)` from `@phala/dcap-qvl`.\n * Without it, a quote that came without collateral is refused.\n */\n fetchCollateral?: (quote: Uint8Array) => Promise<DcapCollateral>;\n /** The current time in milliseconds; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\n/** A quote verifier as this package builds one ({@link createQuoteVerifier}). */\nexport type QuoteVerifier = VerifyTransportQuote & { readonly includeCollateral: true };\n\nconst MEASUREMENT_HEX = /^[0-9a-f]{96}$/;\nconst REGISTERS = ['mrtd', 'rtmr0', 'rtmr1', 'rtmr2', 'rtmr3'] as const;\n\n/**\n * A verifier that checks a TEE node's quote here, in the page, and accepts it\n * only when every check passes:\n *\n * - its signatures verify against Intel's root, with collateral that is valid\n * now;\n * - the platform's TCB status is one allowed (`UpToDate` by default), and\n * never `Revoked`;\n * - its measurements are those of a trusted image: one of\n * `allowedMeasurements` in full, and the MRTD and any RTMRs listed;\n * - its report data is the nonce followed by the binding the client computed.\n *\n * Any failure rejects with the reason; nothing is trusted from a quote that\n * does not pass. Mock quotes never pass: they carry no signature.\n *\n * ```ts\n * import { verify as dcapVerify } from '@phala/dcap-qvl';\n *\n * const verifier = createQuoteVerifier({\n * dcapVerify,\n * ...trustedMeasurementsFromReleases([publishedMrtds], { profile: 'locked-read-only' }),\n * });\n * const client = new CalimeroClient({ baseUrl, policy: { verifyQuote: verifier } });\n * ```\n */\nexport function createQuoteVerifier(options: QuoteVerifierOptions): QuoteVerifier {\n const allowedMrtd = measurements(options.allowedMrtd ?? [], 'allowedMrtd');\n const allowedImages = (options.allowedMeasurements ?? []).map((image, index) => {\n const label = `allowedMeasurements[${index}]`;\n return REGISTERS.map((register) => measurements([image?.[register] ?? ''], `${label}.${register}`)[0]).join();\n });\n const allowedRtmr = [\n measurements(options.allowedRtmr0 ?? [], 'allowedRtmr0'),\n measurements(options.allowedRtmr1 ?? [], 'allowedRtmr1'),\n measurements(options.allowedRtmr2 ?? [], 'allowedRtmr2'),\n measurements(options.allowedRtmr3 ?? [], 'allowedRtmr3'),\n ];\n if (options.allowedMeasurements !== undefined && allowedImages.length === 0) {\n throw new Error('allowedMeasurements is empty, so no quote would ever be accepted');\n }\n if (allowedImages.length === 0) {\n if (allowedMrtd.length === 0) {\n throw new Error('No image is trusted: give allowedMeasurements, or allowedMrtd with allowedRtmr1-3');\n }\n if (allowedRtmr.slice(1).some((list) => list.length === 0)) {\n throw new Error(\n 'allowedMrtd alone does not name an image: the MRTD measures the TD firmware, which ' +\n 'images share, and the image is in RTMR1-3. Give allowedMeasurements, or allowedRtmr1-3 too',\n );\n }\n }\n const allowedStatuses = options.allowedTcbStatuses ?? ['UpToDate'];\n const now = options.now ?? Date.now;\n\n const verifier = async ({\n quoteB64,\n nonce,\n reportDataSuffix,\n collateral,\n }: Parameters<VerifyTransportQuote>[0]): Promise<boolean> => {\n const quote = fromBase64(quoteB64);\n const against = collateral ?? (await options.fetchCollateral?.(quote));\n if (!against) {\n throw new Error(\n 'The node sent no collateral for its quote, and no fetchCollateral was given to get it',\n );\n }\n\n let verified: DcapVerifiedReport;\n try {\n verified = options.dcapVerify(quote, against, Math.floor(now() / 1000));\n } catch (error) {\n throw new Error(`The quote did not verify: ${(error as Error)?.message ?? String(error)}`);\n }\n\n if (verified.status === 'Revoked' || !allowedStatuses.includes(verified.status)) {\n throw new Error(`The platform's TCB status is ${verified.status}, which is not accepted`);\n }\n const td = tdReport(verified.report);\n // TUD bit 0. A debug TD's memory and registers are open to the host, so its\n // measurements prove nothing about what runs in it. Checked here, not left\n // to `dcapVerify`, which a caller may swap for one that allows debug; an\n // attribute field that cannot be read counts as debug.\n if (td.tdAttributes?.length !== 8 || (td.tdAttributes[0] & 0x01) !== 0) {\n throw new Error('The quote is from a debug TD, or its TD attributes cannot be read');\n }\n const measured = [td.mrTd, td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3].map((register) => hex(register));\n if (allowedImages.length > 0 && !allowedImages.includes(measured.join())) {\n throw new Error(\n `The measurements (MRTD ${measured[0]}, RTMR0-3 ${measured.slice(1).join(', ')}) are not an image this verifier trusts`,\n );\n }\n if (allowedMrtd.length > 0 && !allowedMrtd.includes(measured[0])) {\n throw new Error(`MRTD ${measured[0]} is not an image this verifier trusts`);\n }\n const registers = [td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3];\n registers.forEach((register, index) => {\n const allowed = allowedRtmr[index];\n if (allowed.length > 0 && !allowed.includes(hex(register))) {\n throw new Error(`RTMR${index} ${hex(register)} is not one this verifier trusts`);\n }\n });\n if (hex(td.reportData) !== `${nonce}${reportDataSuffix}`.toLowerCase()) {\n throw new Error('The quote does not commit to this nonce and binding');\n }\n return true;\n };\n return Object.assign(verifier, { includeCollateral: true as const });\n}\n\nfunction measurements(values: string[], label: string): string[] {\n return values.map((value) => {\n const normalized = value.trim().toLowerCase();\n if (!MEASUREMENT_HEX.test(normalized)) {\n throw new Error(`${label} holds ${JSON.stringify(value)}, which is not a 48-byte hex measurement`);\n }\n return normalized;\n });\n}\n\n/** The TD report of a TDX quote (1.0 or 1.5); anything else is refused. */\nfunction tdReport(report: DcapVerifiedReport['report']): TdReport {\n const data = report.data as (TdReport & { base?: TdReport }) | undefined;\n if (report.type === 'td10' && data) return data;\n if (report.type === 'td15' && data?.base) return data.base;\n throw new Error(`The quote is a ${report.type} quote, not a TDX one`);\n}\n\nfunction fromBase64(value: string): Uint8Array {\n const binary = atob(value);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\n/**\n * A mero-tee node release's `published-mrtds.json`: the measurements the\n * release workflow observed booting each profile of its image on TDX, signed\n * with the release. Only the fields read here are typed.\n */\nexport interface PublishedMrtds {\n role?: string;\n tag?: string;\n profiles: Record<\n string,\n {\n mrtd: string;\n rtmr0: string;\n rtmr1: string;\n rtmr2: string;\n rtmr3: string;\n allowed_tcb_statuses?: string[];\n }\n >;\n}\n\n/** TCB statuses as DCAP reports them; the release lists them in lower case. */\nconst TCB_STATUSES = [\n 'UpToDate',\n 'SWHardeningNeeded',\n 'ConfigurationNeeded',\n 'ConfigurationAndSWHardeningNeeded',\n 'OutOfDate',\n 'OutOfDateConfigurationNeeded',\n];\n\n/**\n * The {@link QuoteVerifierOptions} that trust exactly one profile of the given\n * releases: each release's image by all of its measurements, and only the TCB\n * statuses every one of those releases accepts.\n *\n * Pass every release a node you talk to may run. During a rollout that is the\n * old one and the new one; drop the old one once no node runs it.\n *\n * ```ts\n * import published from './trusted/mero-tee-v2.3.78.published-mrtds.json';\n *\n * const verifier = createQuoteVerifier({\n * dcapVerify,\n * ...trustedMeasurementsFromReleases([published], { profile: 'locked-read-only' }),\n * });\n * ```\n *\n * Where the file comes from is the trust decision. Shipping it with the app\n * (checked out of a release you verified) trusts that release; fetching it at\n * run time trusts whoever serves it.\n */\n/**\n * The one image profile a release publishes for production. The `debug` and\n * `debug-read-only` images are signed and published beside it, but run with\n * SSH and the operator's tooling inside the TD, so trusting one trusts an\n * image the operator can read.\n */\nexport const PRODUCTION_PROFILE = 'locked-read-only';\n\nexport interface TrustedProfileOptions {\n /** The image profile to trust, e.g. `locked-read-only`. */\n profile: string;\n /**\n * Trust a profile other than {@link PRODUCTION_PROFILE}, such as `debug`.\n * Its image is readable by whoever operates the node, so only for testing.\n */\n allowDebugProfile?: boolean;\n}\n\nexport function trustedMeasurementsFromReleases(\n releases: PublishedMrtds[],\n { profile, allowDebugProfile = false }: TrustedProfileOptions,\n): Required<Pick<QuoteVerifierOptions, 'allowedMeasurements' | 'allowedTcbStatuses'>> {\n if (releases.length === 0) {\n throw new Error('No release given, so no image would be trusted');\n }\n let statuses: string[] | undefined;\n const allowedMeasurements = releases.map((release, index) => {\n const name = release?.tag ?? `releases[${index}]`;\n if (release?.role !== undefined && release.role !== 'node') {\n throw new Error(`${name} lists the measurements of a ${release.role}, not of a node image`);\n }\n const image = release?.profiles?.[profile];\n if (!image) {\n const known = Object.keys(release?.profiles ?? {}).join(', ') || 'none';\n throw new Error(`${name} has no profile ${JSON.stringify(profile)} (it has: ${known})`);\n }\n if (profile !== PRODUCTION_PROFILE && !allowDebugProfile) {\n throw new Error(\n `${JSON.stringify(profile)} is not a production profile: its image is readable by whoever ` +\n `operates the node. Trust ${JSON.stringify(PRODUCTION_PROFILE)}, or pass allowDebugProfile to test`,\n );\n }\n const accepted = (image.allowed_tcb_statuses ?? ['uptodate']).map((status) => tcbStatus(status, name));\n statuses = statuses === undefined ? accepted : statuses.filter((status) => accepted.includes(status));\n return {\n mrtd: image.mrtd,\n rtmr0: image.rtmr0,\n rtmr1: image.rtmr1,\n rtmr2: image.rtmr2,\n rtmr3: image.rtmr3,\n };\n });\n if (!statuses || statuses.length === 0) {\n throw new Error('The releases given accept no TCB status in common');\n }\n return { allowedMeasurements, allowedTcbStatuses: statuses };\n}\n\nfunction tcbStatus(status: string, release: string): string {\n const known = TCB_STATUSES.find((candidate) => candidate.toLowerCase() === String(status).toLowerCase());\n if (!known) {\n throw new Error(`${release} accepts TCB status ${JSON.stringify(status)}, which this verifier does not know`);\n }\n return known;\n}\n", "/**\n * Trusting a TEE node's image by its signed release, fetched at run time from\n * anywhere, instead of shipping the release's `published-mrtds.json` with the\n * app.\n *\n * Each mero-tee node release publishes `published-mrtds.json` (the\n * measurements of its image) with a cosign keyless bundle, signed by the\n * mero-tee release workflow on GitHub Actions. {@link verifySignedNodeRelease}\n * checks that signature here, against the Sigstore trust root embedded in this\n * package, so the file can come from any source: the cloud's mirror\n * (`GET https://cloud.calimero.network/api/tee/node-releases/{version}`), a\n * mirror of your own, or a file bundled with the app. None of them is\n * trusted; a file whose signature does not verify is refused.\n *\n * What is trusted:\n *\n * - the signer: the node release workflow of `calimero-network/mero-tee` on\n * `master` ({@link NODE_RELEASE_SIGNER}), the identity core pins as\n * `NODE_RELEASE_IDENTITY`;\n * - the Sigstore public-good trust root: Fulcio's CAs and Rekor's key;\n * - the minimum release you pass, below which no release is accepted.\n *\n * What is not: the transport, the server that serves the release, and the\n * node's choice of release. A node can present any genuinely signed release\n * at or above the minimum, and no other; its quote must then match that\n * release's measurements exactly, so it cannot claim one release and run\n * another.\n */\n\nimport { verifyCosignBundle, type SignerIdentity } from './sigstore.js';\nimport {\n createQuoteVerifier,\n trustedMeasurementsFromReleases,\n type DcapVerify,\n type PublishedMrtds,\n type QuoteVerifier,\n type QuoteVerifierOptions,\n type TrustedProfileOptions,\n} from './verify.js';\n\n/** The workflow that signs every mero-tee node release, and the issuer of its identity. */\nexport const NODE_RELEASE_SIGNER: Readonly<SignerIdentity> = Object.freeze({\n identity:\n 'https://github.com/calimero-network/mero-tee/.github/workflows/release-node-image-gcp.yaml@refs/heads/master',\n issuer: 'https://token.actions.githubusercontent.com',\n});\n\nconst MEASUREMENTS = ['mrtd', 'rtmr0', 'rtmr1', 'rtmr2', 'rtmr3'] as const;\n\n/**\n * The public mirror of signed node releases, used when no other source is\n * given. Only a transport: what it serves is verified, so it can fail to\n * answer but cannot make a release trusted.\n */\nexport const DEFAULT_RELEASE_MIRROR = 'https://cloud.calimero.network';\n\n/**\n * Where browsers get Intel's collateral for a quote: the cloud's mirror of the\n * PCCS paths `@phala/dcap-qvl` reads, open to any origin. Intel's PCS sends no\n * CORS header. The mirror only carries Intel-signed items.\n */\nexport const DEFAULT_COLLATERAL_MIRROR = `${DEFAULT_RELEASE_MIRROR}/api/tee/pcs`;\n\n/**\n * A node release as the servers hand it out, wrapped as `{\"data\": ...}`: the\n * release's `published-mrtds.json`, byte for byte, and its cosign bundle.\n * Unverified until {@link verifySignedNodeRelease} says otherwise.\n */\nexport interface SignedNodeRelease {\n /** The release, e.g. `2.3.87`. It must be the signed file's `tag`. */\n version: string;\n /** `published-mrtds.json`, exactly as signed. */\n publishedMrtds: string;\n /** `published-mrtds.json.bundle.json`, as JSON text. */\n bundle: string;\n}\n\nexport interface VerifySignedNodeReleaseOptions {\n /** Require the file's `tag` to be this release. */\n expectedVersion?: string;\n /** The certificate identity required. Defaults to {@link NODE_RELEASE_SIGNER}'s. */\n identity?: string;\n /** The OIDC issuer required. Defaults to {@link NODE_RELEASE_SIGNER}'s. */\n issuer?: string;\n /** The release's detached `published-mrtds.json.sig`, when you have it; it must be the bundle's. */\n signature?: string;\n}\n\n/**\n * Verify a node release's `published-mrtds.json` against its cosign bundle,\n * as `cosign verify-blob` would, and return the file parsed. Rejects, with the\n * reason, unless:\n *\n * - the signature over the exact bytes verifies with the bundle's certificate;\n * - that certificate chains to a Fulcio CA in the Sigstore trust root, and it\n * and the CA were valid when Rekor logged the signature;\n * - it names the node release workflow and GitHub Actions as its issuer;\n * - Rekor's signed entry timestamp verifies, for an entry that is this\n * signature over this file by this certificate;\n * - the file is a node release (`role: \"node\"`), and `expectedVersion`, when\n * given, is its `tag`.\n *\n * Nothing is read from the clock: the certificate is checked at the time Rekor\n * logged the signature, so a release that verifies once always does.\n */\nexport async function verifySignedNodeRelease(\n publishedMrtds: string | Uint8Array,\n bundle: string | object,\n options: VerifySignedNodeReleaseOptions = {},\n): Promise<PublishedMrtds> {\n const body = typeof publishedMrtds === 'string' ? new TextEncoder().encode(publishedMrtds) : publishedMrtds;\n await verifyCosignBundle(\n body,\n bundle,\n {\n identity: options.identity ?? NODE_RELEASE_SIGNER.identity,\n issuer: options.issuer ?? NODE_RELEASE_SIGNER.issuer,\n },\n options.signature,\n );\n\n let release: PublishedMrtds;\n try {\n release = JSON.parse(new TextDecoder().decode(body));\n } catch {\n throw new Error('The signed release is not JSON');\n }\n if (release?.role !== 'node') {\n throw new Error(`The signed release is a ${JSON.stringify(release?.role)} release, not a node one`);\n }\n // The workflow signs other files too, some with a `role` and `profiles` of\n // their own (`release-provenance.json`): the signature covers bytes, not a\n // file name, so check this is the measurements file.\n const profiles = Object.values(release.profiles ?? {});\n const measured = (image: unknown) =>\n MEASUREMENTS.every((register) => /^[0-9a-f]{96}$/i.test(String((image as Record<string, unknown>)?.[register])));\n if (typeof release.tag !== 'string' || profiles.length === 0 || !profiles.every(measured)) {\n throw new Error(\"The signed file is not a release's published-mrtds.json: it lists no measured profiles\");\n }\n if (options.expectedVersion !== undefined && release.tag !== options.expectedVersion) {\n throw new Error(`The signed release is ${release.tag}, not ${options.expectedVersion}`);\n }\n return release;\n}\n\n/**\n * Fetch a {@link SignedNodeRelease} from a server that wraps it as\n * `{\"data\": ...}`, such as the cloud's {@link cloudNodeReleaseUrl}. It is\n * only fetched: pass it to\n * {@link trustSignedRelease}, or {@link verifySignedNodeRelease}, before using it.\n */\nexport async function fetchNodeRelease(\n url: string,\n options: { fetch?: typeof fetch } = {},\n): Promise<SignedNodeRelease> {\n const response = await (options.fetch ?? fetch)(url, { headers: { accept: 'application/json' } });\n if (!response.ok) throw new Error(`Fetching the node release from ${url} failed: HTTP ${response.status}`);\n let release: Partial<SignedNodeRelease> | undefined;\n try {\n release = ((await response.json()) as { data?: Partial<SignedNodeRelease> })?.data;\n } catch {\n throw new Error(`${url} did not answer with JSON`);\n }\n if (\n typeof release?.version !== 'string' ||\n typeof release.publishedMrtds !== 'string' ||\n typeof release.bundle !== 'string'\n ) {\n throw new Error(`${url} did not answer with a signed node release`);\n }\n return { version: release.version, publishedMrtds: release.publishedMrtds, bundle: release.bundle };\n}\n\n/** Where mero-tee publishes its releases' assets, as core's `calimero-tee-release` fetches them. */\nexport const GITHUB_RELEASES = 'https://github.com/calimero-network/mero-tee/releases/download';\n\n/**\n * Node release `version` straight from its GitHub release (`mero-tee-v{version}`):\n * `published-mrtds.json` and its cosign bundle, the files core's Rust client\n * verifies. Only fetched: verify it with {@link trustSignedRelease}. GitHub's\n * downloads send no CORS headers, so in a browser use a mirror\n * ({@link cloudNodeReleaseUrl}) instead.\n */\nexport async function fetchGithubNodeRelease(\n version: string,\n options: { fetch?: typeof fetch; base?: string } = {},\n): Promise<SignedNodeRelease> {\n const tag = `mero-tee-v${releaseVersion(version, 'version')}`;\n const base = `${(options.base ?? GITHUB_RELEASES).replace(/\\/+$/, '')}/${tag}/published-mrtds.json`;\n const get = async (url: string): Promise<string> => {\n const response = await (options.fetch ?? fetch)(url);\n if (!response.ok) throw new Error(`Fetching ${url} failed: HTTP ${response.status}`);\n return response.text();\n };\n const [publishedMrtds, bundle] = await Promise.all([get(base), get(`${base}.bundle.json`)]);\n return { version, publishedMrtds, bundle };\n}\n\n/** Where the cloud at `cloudUrl` (e.g. `https://cloud.calimero.network`) mirrors node release `version`. */\nexport function cloudNodeReleaseUrl(cloudUrl: string, version: string): string {\n return `${cloudUrl.replace(/\\/+$/, '')}/api/tee/node-releases/${releaseVersion(version, 'version')}`;\n}\n\nexport interface TrustSignedReleaseOptions extends TrustedProfileOptions {\n /** The release, from any source; it is verified here. */\n release: SignedNodeRelease;\n /**\n * The oldest release accepted, e.g. `2.3.87`. Required: every release ever\n * signed stays validly signed, so without a floor a node could present an\n * old release, with a flaw since fixed, and a quote from that old image\n * would pass. Raise it when a release must no longer be trusted.\n */\n minReleaseVersion: string;\n /** Override the signer; defaults to {@link NODE_RELEASE_SIGNER}. */\n identity?: string;\n issuer?: string;\n}\n\n/**\n * The {@link QuoteVerifierOptions} that trust one profile of a signed node\n * release, from an untrusted source: its signature is verified, its signed\n * `tag` must be `release.version` and no older than `minReleaseVersion`, and\n * then it is read as {@link trustedMeasurementsFromReleases} reads a bundled\n * file.\n *\n * ```ts\n * const version = claimedRelease(attestationDoc, '2.3.109'); // the release the node names\n * const release = await fetchNodeRelease(cloudNodeReleaseUrl(DEFAULT_RELEASE_MIRROR, version));\n * const verifier = createQuoteVerifier({\n * dcapVerify,\n * ...(await trustSignedRelease({ release, profile: 'locked-read-only', minReleaseVersion: '2.3.87' })),\n * });\n * ```\n */\nexport async function trustSignedRelease(\n options: TrustSignedReleaseOptions,\n): Promise<Required<Pick<QuoteVerifierOptions, 'allowedMeasurements' | 'allowedTcbStatuses'>>> {\n const minimum = releaseVersion(options.minReleaseVersion, 'minReleaseVersion');\n const version = releaseVersion(options.release?.version, 'The release version');\n const published = await verifySignedNodeRelease(options.release.publishedMrtds, options.release.bundle, {\n expectedVersion: version,\n identity: options.identity,\n issuer: options.issuer,\n });\n if (compareReleaseVersions(version, minimum) < 0) {\n throw new Error(`Release ${version} is older than the minimum trusted, ${minimum}`);\n }\n return trustedMeasurementsFromReleases([published], {\n profile: options.profile,\n allowDebugProfile: options.allowDebugProfile,\n });\n}\n\nexport interface SignedReleaseVerifierOptions extends Omit<TrustSignedReleaseOptions, 'release'> {\n /** DCAP verification: `verify` from `@phala/dcap-qvl`. */\n dcapVerify: DcapVerify;\n /**\n * Where to get the node's release, asked again each time the node is\n * attested (a restarted node may run a newer one). Untrusted: it is\n * verified, and the quote must match it.\n */\n release: () => Promise<SignedNodeRelease>;\n /** As {@link QuoteVerifierOptions.fetchCollateral}. */\n fetchCollateral?: QuoteVerifierOptions['fetchCollateral'];\n /** The current time in milliseconds, for the quote's collateral; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\n/**\n * A {@link createQuoteVerifier} whose trusted image is the signed release the\n * node says it runs. On each attestation it gets the release, checks it with\n * {@link trustSignedRelease}, and verifies the quote against that release's\n * measurements only.\n *\n * The node's choice of release is the one thing taken from it, and it is\n * bounded: only a genuinely signed release at or above `minReleaseVersion`\n * passes, and the quote must then be of exactly that release's image. Pass it\n * as `CloudPolicy.verifyQuote` to choose where the release comes from yourself.\n */\nexport function createSignedReleaseVerifier(options: SignedReleaseVerifierOptions): QuoteVerifier {\n releaseVersion(options.minReleaseVersion, 'minReleaseVersion');\n const verifier = async (args: Parameters<QuoteVerifier>[0]): Promise<boolean> => {\n const trusted = await trustSignedRelease({\n release: await options.release(),\n profile: options.profile,\n allowDebugProfile: options.allowDebugProfile,\n minReleaseVersion: options.minReleaseVersion,\n identity: options.identity,\n issuer: options.issuer,\n });\n return createQuoteVerifier({\n dcapVerify: options.dcapVerify,\n fetchCollateral: options.fetchCollateral,\n now: options.now,\n ...trusted,\n })(args);\n };\n return Object.assign(verifier, { includeCollateral: true as const });\n}\n\nconst RELEASE_VERSION = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/;\n\n/** `value` if it is a release version (`2.3.87`, `2.3.88-rc.1`); throws otherwise. */\nexport function releaseVersion(value: unknown, what: string): string {\n const match = typeof value === 'string' ? RELEASE_VERSION.exec(value) : null;\n const pre = match?.[4];\n if (!match || (pre !== undefined && pre.split('.').some((id) => id === ''))) {\n throw new Error(`${what} is ${JSON.stringify(value)}, not a release version like 2.3.87`);\n }\n return value as string;\n}\n\n/**\n * Order two release versions as semver does, and as core's\n * `compare_release_versions`: numerically by `X.Y.Z`, a pre-release before its\n * release, build metadata ignored.\n */\nexport function compareReleaseVersions(a: string, b: string): number {\n const [aCore, aPre] = splitVersion(a);\n const [bCore, bPre] = splitVersion(b);\n for (let i = 0; i < 3; i += 1) {\n if (aCore[i] !== bCore[i]) return aCore[i] < bCore[i] ? -1 : 1;\n }\n if (aPre === undefined || bPre === undefined) return aPre === bPre ? 0 : aPre === undefined ? 1 : -1;\n const aIds = aPre.split('.');\n const bIds = bPre.split('.');\n for (let i = 0; i < Math.max(aIds.length, bIds.length); i += 1) {\n const [x, y] = [aIds[i], bIds[i]];\n if (x === undefined || y === undefined) return x === undefined ? -1 : 1;\n const [xNum, yNum] = [/^\\d+$/.test(x), /^\\d+$/.test(y)];\n const order =\n xNum && yNum ? Math.sign(Number(x) - Number(y)) : xNum !== yNum ? (xNum ? -1 : 1) : x < y ? -1 : x > y ? 1 : 0;\n if (order !== 0) return order;\n }\n return 0;\n}\n\nfunction splitVersion(version: string): [number[], string | undefined] {\n const match = RELEASE_VERSION.exec(version) as RegExpExecArray;\n return [[Number(match[1]), Number(match[2]), Number(match[3])], match[4]];\n}\n", "/**\n * The check every cloud client runs before it sends anything: the node's quote\n * must be genuine (or, in development, an explicitly allowed mock), from an\n * image this client trusts, and its report data must bind this nonce, the\n * expected app and the transport key the sealed channel will be opened to.\n *\n * Report data, as core's `calimero-cloud-client::attest` builds it:\n * `nonce(32) || SHA-256(\"calimero.tee-attest.transport-key.v1\" | app_hash | transport_key)`.\n *\n * A real quote is judged as the Rust client judges it (`attest::verify` with\n * `Measurements::Release`): the node names the mero-tee release it runs; that\n * release must be at least `minReleaseVersion`; its `published-mrtds.json` is\n * fetched and its Sigstore signature checked against the node release workflow;\n * the quote's signature chain and TCB status are checked against Intel's\n * collateral (fetched here: the node sends none, and cannot forge it); the TD\n * must not be a debug TD; and its registers must be the release's image for the\n * trusted profile, `locked-read-only` unless a debug profile is explicitly\n * allowed. Nothing here reads the environment: mock quotes pass only with\n * `allowMock`.\n */\n\nimport { fromHex, hex } from '../crypto/internal.js';\nimport {\n DEFAULT_COLLATERAL_MIRROR,\n DEFAULT_RELEASE_MIRROR,\n cloudNodeReleaseUrl,\n compareReleaseVersions,\n fetchGithubNodeRelease,\n fetchNodeRelease,\n releaseVersion,\n trustSignedRelease,\n type SignedNodeRelease,\n} from '../sealed/release.js';\nimport { transportKeyBinding, type VerifyTransportQuote } from '../sealed/sealed.js';\nimport { PRODUCTION_PROFILE, createQuoteVerifier, type DcapCollateral, type DcapVerify } from '../sealed/verify.js';\n\n/** The mock quote format development clusters use. */\nexport const MOCK_QUOTE_HEADER = 'MOCK_TDX_QUOTE_V1';\n\n/** How the signed release a node names is trusted (core's `Measurements::Release`). */\nexport interface CloudReleasePolicy {\n /**\n * The oldest mero-tee release trusted, e.g. `2.3.109`. Required: every\n * release ever signed stays validly signed, so without a floor a node could\n * name an old release with a flaw since fixed.\n */\n minReleaseVersion: string;\n /** The image profile trusted; defaults to `locked-read-only`. */\n profile?: string;\n /** Trust a debug profile. Its image is readable by the operator: testing only. */\n allowDebugProfile?: boolean;\n /**\n * Where the release's signed measurements come from: `'github'` (the release\n * assets, what core's Rust client reads; no CORS, so not in browsers), the\n * base URL of a mirror (default {@link DEFAULT_RELEASE_MIRROR}), or a function.\n * Untrusted either way: the Sigstore signature is checked here.\n */\n releaseSource?: 'github' | string | ((version: string) => Promise<SignedNodeRelease>);\n /** DCAP verification; defaults to `verify` from `@phala/dcap-qvl`, loaded on first use. */\n dcapVerify?: DcapVerify;\n /**\n * Intel's collateral for a quote. Defaults to `@phala/dcap-qvl`'s\n * `getCollateral` from `collateralSource`.\n */\n fetchCollateral?: (quote: Uint8Array) => Promise<DcapCollateral>;\n /**\n * Where the default `fetchCollateral` gets Intel's collateral: a PCCS base\n * URL (default {@link DEFAULT_COLLATERAL_MIRROR}, the cloud's mirror, which a\n * browser on any origin can read), or `'intel'` for Intel's PCS itself (no\n * CORS: not in browsers). Untrusted either way: every item is signed by\n * Intel and verified up to Intel's root CA, which `@phala/dcap-qvl` carries.\n */\n collateralSource?: 'intel' | string;\n /**\n * Refuse collateral whose TCB info Intel issued more than this many days\n * ago. Unset: only Intel's own `nextUpdate` (about 30 days out) bounds how\n * old it may be. A mirror cannot forge collateral, but it can replay an\n * older, still valid copy; this shortens that window. Too small a value\n * refuses every node if Intel is slow to re-sign.\n */\n maxCollateralAgeDays?: number;\n /** Override the release signer (defaults to the mero-tee node release workflow). */\n identity?: string;\n issuer?: string;\n /** The current time in milliseconds; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\nexport interface CloudPolicy {\n /** Accept mock quotes. Development clusters only; never set from the environment. */\n allowMock?: boolean;\n /** Trust real quotes from the signed release the node runs. */\n release?: CloudReleasePolicy;\n /**\n * Verify a real quote yourself instead (e.g. `createQuoteVerifier` with\n * pinned measurements). Takes precedence over `release`.\n */\n verifyQuote?: VerifyTransportQuote;\n /** The app bundle hash (hex) the quote must bind, when talking to one app. */\n appHash?: string;\n}\n\nexport interface AttestationDoc {\n quote: string;\n transportKey: string;\n appHash: string;\n nonce: string;\n release: { version: string; profile: string };\n cluster: string;\n node: number;\n mock: boolean;\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n return diff === 0;\n}\n\ntype DcapModule = {\n verify?: unknown;\n getCollateral?: unknown;\n getCollateralFromPcs?: unknown;\n default?: { verify?: unknown; getCollateral?: unknown; getCollateralFromPcs?: unknown };\n};\nlet dcapModule: Promise<DcapModule> | undefined;\n\n/** A function out of `@phala/dcap-qvl`, whatever shape the bundler gave the (CommonJS) module. */\nasync function dcap<T>(name: 'verify' | 'getCollateral' | 'getCollateralFromPcs'): Promise<T> {\n dcapModule ??= import('@phala/dcap-qvl') as Promise<DcapModule>;\n const ns = await dcapModule;\n const f = typeof ns[name] === 'function' ? ns[name] : ns.default?.[name];\n if (typeof f !== 'function') throw new TypeError(`@phala/dcap-qvl loaded without ${name}`);\n return f as T;\n}\n\n/**\n * The release a node names, checked against the floor before anything is\n * fetched. Accepts `2.3.109` and the tag form `mero-tee-v2.3.109`.\n */\nexport function claimedRelease(doc: Pick<AttestationDoc, 'release'>, minReleaseVersion: string): string {\n const floor = releaseVersion(minReleaseVersion, 'minReleaseVersion');\n const raw = String(doc.release?.version ?? '').trim().replace(/^mero-tee-v/, '').replace(/^v/, '');\n const version = releaseVersion(raw, 'The release the node names');\n if (compareReleaseVersions(version, floor) < 0) {\n throw new Error(`mero-tee release ${version} is older than the minimum ${floor}`);\n }\n return version;\n}\n\nasync function releaseFor(version: string, policy: CloudReleasePolicy, fetchImpl: typeof fetch) {\n const source = policy.releaseSource;\n if (typeof source === 'function') return source(version);\n if (source === 'github') return fetchGithubNodeRelease(version, { fetch: fetchImpl });\n return fetchNodeRelease(cloudNodeReleaseUrl(source ?? DEFAULT_RELEASE_MIRROR, version), { fetch: fetchImpl });\n}\n\n/** The collateral fetch a policy gets unless it brings its own: `@phala/dcap-qvl` against `collateralSource`. */\nfunction defaultCollateral(policy: CloudReleasePolicy): (quote: Uint8Array) => Promise<DcapCollateral> {\n const source = policy.collateralSource ?? DEFAULT_COLLATERAL_MIRROR;\n if (source === 'intel') {\n return async (quote) => (await dcap<(q: Uint8Array) => Promise<DcapCollateral>>('getCollateralFromPcs'))(quote);\n }\n return async (quote) =>\n (await dcap<(url: string, q: Uint8Array) => Promise<DcapCollateral>>('getCollateral'))(source, quote);\n}\n\n/** `fetch`, refusing collateral older than `policy.maxCollateralAgeDays` (by its TCB info's `issueDate`). */\nexport function freshCollateral(\n fetch: (quote: Uint8Array) => Promise<DcapCollateral>,\n policy: Pick<CloudReleasePolicy, 'maxCollateralAgeDays' | 'now'>,\n): (quote: Uint8Array) => Promise<DcapCollateral> {\n const maxDays = policy.maxCollateralAgeDays;\n if (maxDays === undefined) return fetch;\n return async (quote) => {\n const collateral = await fetch(quote);\n let issued: number;\n try {\n issued = Date.parse((JSON.parse(collateral.tcb_info) as { issueDate?: string }).issueDate ?? '');\n } catch {\n issued = Number.NaN;\n }\n if (!Number.isFinite(issued)) throw new Error(\"The quote's collateral names no TCB info issue date\");\n const ageDays = ((policy.now ?? Date.now)() - issued) / 86_400_000;\n if (ageDays > maxDays) {\n throw new Error(\n `The quote's collateral was issued ${Math.floor(ageDays)} days ago, more than the ${maxDays} this client accepts`,\n );\n }\n return collateral;\n };\n}\n\n/** Judge a real quote as core's `Measurements::Release` does. */\nasync function verifyRelease(\n doc: AttestationDoc,\n args: Parameters<VerifyTransportQuote>[0],\n policy: CloudReleasePolicy,\n fetchImpl: typeof fetch,\n): Promise<boolean> {\n // Refuse what no release could admit before reaching for the network.\n const version = claimedRelease(doc, policy.minReleaseVersion);\n const trusted = await trustSignedRelease({\n release: await releaseFor(version, policy, fetchImpl),\n profile: policy.profile ?? PRODUCTION_PROFILE,\n allowDebugProfile: policy.allowDebugProfile,\n minReleaseVersion: policy.minReleaseVersion,\n identity: policy.identity,\n issuer: policy.issuer,\n });\n const fetchCollateral = freshCollateral(policy.fetchCollateral ?? defaultCollateral(policy), policy);\n const verifier = createQuoteVerifier({\n dcapVerify: policy.dcapVerify ?? (await dcap<DcapVerify>('verify')),\n fetchCollateral,\n now: policy.now,\n ...trusted,\n });\n return verifier(args);\n}\n\n/** Fetch the node's attestation and return its transport key once it checks out. */\nexport async function fetchAttestedKey(\n baseUrl: string,\n policy: CloudPolicy,\n fetchImpl: typeof fetch = (input, init) => fetch(input, init),\n): Promise<Uint8Array> {\n const nonce = hex(crypto.getRandomValues(new Uint8Array(32)));\n const url = new URL(`${baseUrl.replace(/\\/+$/, '')}/attestation`);\n url.searchParams.set('nonce', nonce);\n if (policy.appHash) url.searchParams.set('appHash', policy.appHash);\n const response = await fetchImpl(url.toString());\n if (!response.ok) throw new Error(`The node refused to attest: HTTP ${response.status}`);\n const doc = (await response.json()) as AttestationDoc;\n const transportKey = fromHex(doc.transportKey, 'transportKey', 32);\n const inner = policy.appHash ? fromHex(policy.appHash, 'appHash', 32) : new Uint8Array(32);\n const suffix = await transportKeyBinding(inner, transportKey);\n const quote = base64ToBytes(doc.quote);\n const header = new TextEncoder().encode(MOCK_QUOTE_HEADER);\n if (equal(quote.slice(0, header.length), header)) {\n if (!policy.allowMock) {\n throw new Error('mock quote refused: this client only trusts real TEEs');\n }\n const report = quote.slice(header.length, header.length + 64);\n if (!equal(report.slice(0, 32), fromHex(nonce, 'nonce', 32)) || !equal(report.slice(32), suffix)) {\n throw new Error('the quote does not bind this transport key, app and nonce');\n }\n return transportKey;\n }\n const args = { quoteB64: doc.quote, nonce, reportDataSuffix: hex(suffix) };\n let ok: boolean;\n if (policy.verifyQuote) {\n ok = await policy.verifyQuote(args);\n } else if (policy.release) {\n ok = await verifyRelease(doc, args, policy.release, fetchImpl);\n } else {\n throw new Error('real quote refused: this client trusts no TD image (set policy.release)');\n }\n if (!ok) throw new Error('The attestation did not verify, so its transport key is not trusted');\n return transportKey;\n}\n", "/**\n * The Calimero Cloud node directory: which nodes of a cluster take traffic now,\n * and in what order this client tries them.\n *\n * `GET {directory}/{cluster}` (no auth) answers\n * `{ cluster, nodes: [{ id, url, zone, weight }], refreshAfterSeconds }`. The\n * directory is not trusted for security: it only picks which nodes to try.\n * Every node is attested under the caller's own policy before anything is sent\n * to it, so a bad list can only make connecting fail.\n */\n\n/** The Calimero Cloud control plane's public node directory. */\nexport const DEFAULT_DIRECTORY = 'https://manager.cloud.calimero.network/api/v2/directory';\n\n/** How long a listing stands when the directory does not say. */\nconst DEFAULT_REFRESH_SECONDS = 60;\n\n/** Why {@link DirectoryError} was thrown. */\nexport type DirectoryFailure = 'unreachable' | 'not-found' | 'bad-response' | 'empty';\n\n/**\n * The directory could not name a node to try: it could not be reached or\n * answered an error (`unreachable`), does not know the cluster (`not-found`,\n * a 404), answered something that is not a listing (`bad-response`), or listed\n * no usable node (`empty`).\n */\nexport class DirectoryError extends Error {\n constructor(\n readonly cluster: string,\n readonly reason: DirectoryFailure,\n message: string,\n readonly status?: number,\n readonly cause?: unknown,\n ) {\n super(`directory for cluster ${cluster}: ${message}`);\n this.name = 'DirectoryError';\n }\n}\n\n/** One usable node of a listing. */\nexport interface DirectoryNode {\n url: string;\n zone?: string;\n weight: number;\n}\n\nexport interface DirectoryListing {\n nodes: DirectoryNode[];\n refreshAfterSeconds: number;\n}\n\n/** The URL of `cluster`'s listing in `directory`. */\nexport function directoryUrl(directory: string, cluster: string): string {\n return `${directory.replace(/\\/+$/, '')}/${encodeURIComponent(cluster)}`;\n}\n\n/**\n * Read `cluster`'s listing, keeping only the entries with an http(s) URL and a\n * positive integer weight (the first of a repeated URL).\n */\nexport async function readDirectory(directory: string, cluster: string, fetcher: typeof fetch): Promise<DirectoryListing> {\n let response: Response;\n try {\n response = await fetcher(directoryUrl(directory, cluster), { method: 'GET', headers: { accept: 'application/json' } });\n } catch (error) {\n throw new DirectoryError(cluster, 'unreachable', `could not be reached: ${String(error)}`, undefined, error);\n }\n if (response.status === 404) throw new DirectoryError(cluster, 'not-found', 'unknown cluster', 404);\n if (!response.ok) throw new DirectoryError(cluster, 'unreachable', `answered ${response.status}`, response.status);\n let body: unknown;\n try {\n body = await response.json();\n } catch (error) {\n throw new DirectoryError(cluster, 'bad-response', 'answered something other than JSON', response.status, error);\n }\n const listing = body as { nodes?: unknown; refreshAfterSeconds?: unknown } | null;\n if (!listing || typeof listing !== 'object' || !Array.isArray(listing.nodes)) {\n throw new DirectoryError(cluster, 'bad-response', 'answered no node list', response.status);\n }\n const nodes: DirectoryNode[] = [];\n const seen = new Set<string>();\n for (const entry of listing.nodes) {\n const node = usable(entry);\n if (node && !seen.has(node.url)) {\n seen.add(node.url);\n nodes.push(node);\n }\n }\n if (nodes.length === 0) throw new DirectoryError(cluster, 'empty', 'lists no usable node', response.status);\n const after = listing.refreshAfterSeconds;\n const refreshAfterSeconds =\n typeof after === 'number' && Number.isFinite(after) && after >= 1 ? after : DEFAULT_REFRESH_SECONDS;\n return { nodes, refreshAfterSeconds };\n}\n\nfunction usable(entry: unknown): DirectoryNode | undefined {\n if (!entry || typeof entry !== 'object') return undefined;\n const { url, zone, weight } = entry as Record<string, unknown>;\n if (typeof url !== 'string' || typeof weight !== 'number' || !Number.isInteger(weight) || weight < 1) return undefined;\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return undefined;\n }\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') return undefined;\n return { url: url.replace(/\\/+$/, ''), zone: typeof zone === 'string' ? zone : undefined, weight };\n}\n\n/**\n * The order to try `nodes` in: those in `zone` first (when given), each group\n * in weighted-random order, a node's weight its relative chance to come next.\n * `random` answers in [0, 1), as `Math.random` does.\n */\nexport function orderNodes(nodes: DirectoryNode[], zone: string | undefined, random: () => number): string[] {\n const near = zone === undefined ? [] : nodes.filter((node) => node.zone === zone);\n const far = zone === undefined ? nodes : nodes.filter((node) => node.zone !== zone);\n return [...weightedOrder(near, random), ...weightedOrder(far, random)];\n}\n\nfunction weightedOrder(nodes: DirectoryNode[], random: () => number): string[] {\n const left = [...nodes];\n const order: string[] = [];\n while (left.length > 0) {\n let roll = random() * left.reduce((sum, node) => sum + node.weight, 0);\n let pick = 0;\n while (pick < left.length - 1 && roll >= left[pick].weight) roll -= left[pick++].weight;\n order.push(left.splice(pick, 1)[0].url);\n }\n return order;\n}\n", "/**\n * What the cloud node's refusals mean to a caller (spec D64, D70).\n *\n * The node answers an error as `{ error: CODE, message, details }` with an HTTP\n * status. {@link errorFrom} is the one place the client turns that into an\n * error a caller can switch on; every call, view and event stream goes through\n * it. It matches the status and the code together, never the status alone: the\n * node sends other 409s (`CONFLICT`, `NOT_INSTALLED`) that are not an\n * idempotency mismatch, and other 413s (`TOO_LARGE` from the sealed transport)\n * that are not oversized call arguments. Anything it does not recognise stays a\n * plain {@link CalimeroError} carrying both.\n *\n * Every typed error extends {@link CalimeroError}, so `instanceof CalimeroError`\n * and its `status` and `code` (the node's code) keep working for all of them.\n */\n\nexport class CalimeroError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n readonly details: Record<string, unknown> = {},\n ) {\n super(`${status} ${code}: ${message}`);\n this.name = 'CalimeroError';\n }\n}\n\n/**\n * `401 UNAUTHENTICATED` that refreshing could not answer: sign in (again) and\n * repeat the request.\n *\n * A session token is signed by the node that issued it, and other nodes take\n * it only while they can vouch for that node's signing key: a `401` often\n * means only that the issuer was replaced or cannot be reached, not that the\n * user signed out. The client answers that itself when it holds a refresh\n * token: it refreshes once (any node takes the refresh) and repeats the\n * request. This error reaches a caller when there is no refresh token (an API\n * key, say), or the refresh was refused.\n */\nexport class LoginRequired extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(401, 'UNAUTHENTICATED', message, details);\n this.name = 'LoginRequired';\n }\n}\n\n/**\n * `421 WRONG_NODE`: this node runs a mero-tee release the account's owners have\n * not approved, so it neither issues nor takes the account's sessions. Use\n * another node of the cluster; refreshing here would not help.\n *\n * The client moves to the next node it was given (`nodes`) and repeats the\n * request once by itself (a refresh: once per node). This error reaches a\n * caller when it knows no other node, when the next one refused too (for a\n * refresh, every node), or after a sign-in (which needs the passkey again:\n * repeat it, and it goes to the next node).\n */\nexport class WrongNode extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(421, 'WRONG_NODE', message, details);\n this.name = 'WrongNode';\n }\n}\n\n/**\n * `404 NOT_FOUND`: what the request names does not exist for this caller. For\n * an app this does not say whether it exists: an account the app does not\n * admit gets the same answer as a missing app.\n */\nexport class NotFound extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(404, 'NOT_FOUND', message, details);\n this.name = 'NotFound';\n }\n}\n\n/**\n * `412 CONFIRM_REQUIRED`: the call needs the account holder's passkey over a\n * challenge in `details`. The `*Confirmed` methods answer it themselves; it\n * reaches a caller only from a method that was given no passkey.\n */\nexport class ConfirmRequired extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(412, 'CONFIRM_REQUIRED', message, details);\n this.name = 'ConfirmRequired';\n }\n}\n\n/** The user declined the passkey prompt a confirmation asked for. Nothing was sent. */\nexport class ConfirmCancelled extends Error {\n constructor(readonly cause?: unknown) {\n super('the passkey confirmation was cancelled');\n this.name = 'ConfirmCancelled';\n }\n}\n\n/** `413 ARGS_TOO_LARGE`: the call's arguments are over the node's limit; it did not run. */\nexport class ArgsTooLarge extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(413, 'ARGS_TOO_LARGE', message, details);\n this.name = 'ArgsTooLarge';\n }\n}\n\n/** `409 IDEMPOTENCY_MISMATCH`: the idempotency key was used before with different arguments. */\nexport class IdempotencyMismatch extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(409, 'IDEMPOTENCY_MISMATCH', message, details);\n this.name = 'IdempotencyMismatch';\n }\n}\n\n/**\n * `409 RELEASE_DEADLINE`: a mero-tee release's deadline has passed and the\n * set that governs this work (the app's publisher's, or its owner's) has not\n * approved it or a newer one, so new work (creating an app, installing a\n * release, upgrading an app) is refused. Apps already running keep running.\n * Approving `release` lifts it at once.\n */\nexport class ReleaseDeadlineError extends CalimeroError {\n /** The release to approve. */\n readonly release: string;\n /** Its deadline, RFC 3339 (`''` when the node did not say). */\n readonly after: string;\n\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(409, 'RELEASE_DEADLINE', message, details);\n this.name = 'ReleaseDeadlineError';\n this.release = typeof details.release === 'string' ? details.release : '';\n this.after = typeof details.after === 'string' ? details.after : '';\n }\n}\n\n/**\n * `409 CONSENT_STALE`: what a consent page showed (the app's bundle, the\n * target release, the release's measurements) changed before the person\n * approved. Nothing was approved; ask for a new consent request so they see\n * the new facts.\n */\nexport class ConsentStale extends CalimeroError {\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(409, 'CONSENT_STALE', message, details);\n this.name = 'ConsentStale';\n }\n}\n\n/**\n * `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared\n * error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was\n * logged, so its idempotency key is spent.\n */\nexport class AppError extends CalimeroError {\n readonly appCode: string;\n readonly fields: Record<string, unknown>;\n\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(422, 'APP_ERROR', message, details);\n this.name = 'AppError';\n const { appCode, fields } = appErrorOf(details);\n this.appCode = appCode;\n this.fields = fields;\n }\n}\n\n/** `422 TRAP`: the run trapped (`OutOfFuel`, `OutOfMemory`, ...). The call was logged. */\nexport class TrapError extends CalimeroError {\n readonly kind: string;\n\n constructor(message: string, details: Record<string, unknown> = {}) {\n super(422, 'TRAP', message, details);\n this.name = 'TrapError';\n this.kind = typeof details.kind === 'string' ? details.kind : '';\n }\n}\n\n/**\n * Whether a call the node answered 503 may have committed: `false` when the\n * node says it did not (`TIMEOUT`, `MIGRATING`), `\"unknown\"` otherwise (a call\n * that raced a leader change). Never a plain boolean: `\"unknown\"` must not read\n * as \"no\".\n */\nexport type Committed = false | 'unknown';\n\n/**\n * Any `503`, or a connection that failed, after the client's retries with the\n * same idempotency key ran out. `reason` is the node's code in lower case\n * (`timeout`, `migrating`, `unavailable`, ...), or `network` when the node gave\n * no answer at all (code `NETWORK`, `cause` the `fetch` failure); such a call\n * may have committed, so its `committed` is `'unknown'`.\n */\nexport class UnavailableError extends CalimeroError {\n readonly reason: string;\n readonly committed: Committed;\n /** Seconds the node asked to wait, when it said. */\n readonly retryAfter: number | undefined;\n /** What failed, when the node gave no answer. */\n readonly cause: unknown;\n\n constructor(code: string, message: string, details: Record<string, unknown> = {}, retryAfter?: number, cause?: unknown) {\n super(503, code, message, details);\n this.name = 'UnavailableError';\n this.reason = code.toLowerCase();\n this.committed = code === 'TIMEOUT' || code === 'MIGRATING' ? false : 'unknown';\n this.retryAfter = retryAfter;\n this.cause = cause;\n }\n}\n\nfunction record(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n}\n\n/**\n * The app's code and named fields. The node puts them in `details` as\n * `{ code, fields }`; an older node nests the app's error under `details.error`.\n * Positional payloads (`\"0\"`, `\"1\"`) are never read as fields (D63).\n */\nfunction appErrorOf(details: Record<string, unknown>): { appCode: string; fields: Record<string, unknown> } {\n const source = typeof details.code === 'string' ? details : record(details.error);\n const appCode = typeof source.code === 'string' ? source.code : '';\n return { appCode, fields: { ...record(source.fields) } };\n}\n\nfunction retryAfterOf(details: Record<string, unknown>, header?: string | null): number | undefined {\n for (const candidate of [details.retryAfter, header == null ? undefined : Number(header)]) {\n if (typeof candidate === 'number' && Number.isFinite(candidate) && candidate >= 0) return candidate;\n }\n return undefined;\n}\n\n/**\n * The error for a refusal the node answered with `status` and `body` (its JSON\n * `{ error, message, details }`, or whatever it sent). The one place statuses\n * become typed errors.\n */\nexport function errorFrom(status: number, body: unknown, retryAfterHeader?: string | null): CalimeroError {\n const value = record(body);\n const code = typeof value.error === 'string' ? value.error : 'ERROR';\n const message = typeof value.message === 'string' ? value.message : '';\n const details = record(value.details);\n if (status === 503) return new UnavailableError(code, message, details, retryAfterOf(details, retryAfterHeader));\n switch (`${status} ${code}`) {\n case '401 UNAUTHENTICATED':\n return new LoginRequired(message, details);\n case '421 WRONG_NODE':\n return new WrongNode(message, details);\n case '404 NOT_FOUND':\n return new NotFound(message, details);\n case '409 IDEMPOTENCY_MISMATCH':\n return new IdempotencyMismatch(message, details);\n case '409 RELEASE_DEADLINE':\n return new ReleaseDeadlineError(message, details);\n case '409 CONSENT_STALE':\n return new ConsentStale(message, details);\n case '412 CONFIRM_REQUIRED':\n return new ConfirmRequired(message, details);\n case '413 ARGS_TOO_LARGE':\n return new ArgsTooLarge(message, details);\n case '422 APP_ERROR':\n return new AppError(message, details);\n case '422 TRAP':\n return new TrapError(message, details);\n default:\n return new CalimeroError(status, code, message, details);\n }\n}\n", "/**\n * Passkeys: the browser's WebAuthn API, or anything that answers like it.\n *\n * Every binary field crosses the wire as base64url, matching\n * `calimero-identity`'s `Registration` and `Assertion`.\n */\n\nexport interface RegistrationJSON {\n attestationObject: string;\n clientDataJson: string;\n}\n\nexport interface AssertionJSON {\n credentialId: string;\n authenticatorData: string;\n clientDataJson: string;\n signature: string;\n}\n\n/** Something that holds a passkey. */\nexport interface PasskeyProvider {\n /** Answer `navigator.credentials.create` for the node's options. */\n create(options: Record<string, unknown>): Promise<RegistrationJSON>;\n /** Sign `challenge` (an assertion), optionally limited to `allowCredentials`. */\n get(challenge: Uint8Array, rpId: string, allowCredentials?: string[]): Promise<AssertionJSON>;\n}\n\nexport function b64url(bytes: Uint8Array): string {\n let bin = '';\n for (const b of bytes) bin += String.fromCharCode(b);\n return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nexport function fromB64url(s: string): Uint8Array {\n const pad = s.replace(/-/g, '+').replace(/_/g, '/') + '==='.slice((s.length + 3) % 4);\n const bin = atob(pad);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nconst buf = (b: Uint8Array): ArrayBuffer => b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength) as ArrayBuffer;\n\n/** A dismissed prompt, named as WebAuthn names one (`NotAllowedError`), so a confirmation reads it as declined. */\nfunction cancelled(message: string): Error {\n const error = new Error(message);\n error.name = 'NotAllowedError';\n return error;\n}\n\n/** The platform authenticator (Touch ID, Face ID, Windows Hello, a security key, a synced passkey). */\nexport function browserPasskey(): PasskeyProvider {\n return {\n async create(options) {\n const o = options as {\n challenge: string;\n rp: { id: string; name: string };\n user: { id: string; name: string; displayName: string };\n pubKeyCredParams: Array<{ type: 'public-key'; alg: number }>;\n excludeCredentials?: Array<{ type: 'public-key'; id: string }>;\n authenticatorSelection?: AuthenticatorSelectionCriteria;\n timeout?: number;\n };\n const cred = (await navigator.credentials.create({\n publicKey: {\n challenge: buf(fromB64url(o.challenge)),\n rp: o.rp,\n user: { ...o.user, id: buf(fromB64url(o.user.id)) },\n pubKeyCredParams: o.pubKeyCredParams,\n excludeCredentials: (o.excludeCredentials ?? []).map((c) => ({ type: c.type, id: buf(fromB64url(c.id)) })),\n authenticatorSelection: o.authenticatorSelection,\n attestation: 'none',\n timeout: o.timeout,\n },\n })) as PublicKeyCredential | null;\n if (!cred) throw cancelled('passkey creation was cancelled');\n const r = cred.response as AuthenticatorAttestationResponse;\n return {\n attestationObject: b64url(new Uint8Array(r.attestationObject)),\n clientDataJson: b64url(new Uint8Array(r.clientDataJSON)),\n };\n },\n async get(challenge, rpId, allowCredentials) {\n const cred = (await navigator.credentials.get({\n publicKey: {\n challenge: buf(challenge),\n rpId,\n userVerification: 'preferred',\n allowCredentials: (allowCredentials ?? []).map((id) => ({ type: 'public-key', id: buf(fromB64url(id)) })),\n },\n })) as PublicKeyCredential | null;\n if (!cred) throw cancelled('passkey sign-in was cancelled');\n const r = cred.response as AuthenticatorAssertionResponse;\n return {\n credentialId: b64url(new Uint8Array(cred.rawId)),\n authenticatorData: b64url(new Uint8Array(r.authenticatorData)),\n clientDataJson: b64url(new Uint8Array(r.clientDataJSON)),\n signature: b64url(new Uint8Array(r.signature)),\n };\n },\n };\n}\n", "/**\n * Release and upgrade approvals as core's node reports them, and the consent\n * page an app sends its user to when one is theirs to make.\n *\n * An app never approves in its own page. A passkey assertion is blind (the\n * authenticator shows a site name, never what the challenge commits to), so\n * the page that runs the ceremony decides what the person believes they\n * approve. The node therefore refuses every approval route to a session\n * opened on an app's frontend, and serves its own **consent page** instead:\n * the app asks for a request (`POST /consent/requests`), sends the person to\n * the page's `url` on the node's own origin, and reads the decision when the\n * page sends them back (`returnTo?request_id=\u2026&result=\u2026`) or from\n * `GET /consent/{id}/result`. See core's\n * [consent page](https://calimero-network.github.io/core/protocol/consent-page/)\n * and [governance](https://calimero-network.github.io/core/protocol/governance/).\n */\n\nimport { compareReleaseVersions } from '../sealed/release.js';\n\n// ---------------------------------------------------------------- governance\n\n/**\n * Who holds one decision on a cluster (core's `Authority`), fixed at genesis\n * and attested by every replica. `owner`: the parties around each app, with a\n * passkey (for release approvals the app's publisher, for upgrades whoever\n * its package's manifest names); `operator`: the operator, for every app.\n */\nexport type Authority = 'owner' | 'operator';\n\n/** Core's `Governance`: which side holds each decision on this cluster. */\nexport interface Governance {\n releases: Authority;\n appUpgrades: Authority;\n outbound: Authority;\n /** Who may install apps: any account (`open`, left out) or granted deployers only. */\n deployments?: 'open' | 'granted';\n /** Who grants deployers: the operator (left out) or the cluster's owner. */\n deployers?: 'operator' | 'owner';\n}\n\n/**\n * Who upgrades a package's instances, as its signed manifest declares\n * (`upgrades`; absent means `owner`), where the cluster leaves app upgrades to\n * owners. `owner`: each instance's owner (an organization's\n * `MANAGE_APPLICATION` holders); `publisher`: the `MANAGE_APPLICATION`\n * holders of the organization the package's signing key is bound to, for\n * every instance ({@link CalimeroClient.upgradePublished}). A package may move\n * from `publisher` to `owner` in a later release, never back.\n */\nexport type UpgradeAuthority = 'owner' | 'publisher';\n\n// ---------------------------------------------------------------- reports\n\n/** Whose approvals a report covers: an organization's, or the account's own apps. */\nexport type ReportScope = { kind: 'account' } | { kind: 'org'; org: string };\n\n/** A package release as a report names it. */\nexport interface ReportedRelease {\n package: string;\n version: string;\n /** The service, for a multi-service bundle (account reports only). */\n service?: string | null;\n}\n\n/** A bundle as a report names it: its digest, and its release where the reader may see it. */\nexport interface ReportedBundle {\n bundle: string;\n package?: string;\n version?: string;\n}\n\n/** Who made an upgrade, by kind. */\nexport type ActorKind = 'owner' | 'member' | 'operator';\n\n/** An app's last upgrade. `actor`, `error` and `run` are left out of the operator's report. */\nexport interface LastUpgrade {\n from: ReportedBundle;\n to: ReportedBundle;\n /** Unix seconds. */\n at: number;\n ok: boolean;\n actorKind: ActorKind;\n actor?: string;\n error?: unknown;\n run?: string;\n}\n\n/** One replica of an app: its node, the node's attested release, and whether the app's set approves it. */\nexport interface ReportedReplica {\n node: number;\n /** `null` while the node's release is not known yet (it then holds nothing). */\n release: string | null;\n approved: boolean;\n}\n\n/** One app in a report. `name`, `team` and `availableVersions` are in members' and accounts' reports only. */\nexport interface ReportedApp {\n app: string;\n group: number;\n scope: ReportScope;\n /** `hex(SHA-256)` of the WASM it runs. */\n bundle: string;\n package: ReportedRelease | null;\n /** The package's pinned signer (`did:key`). */\n publisher: { signer: string } | null;\n upgradesHeldBy: Authority;\n lastUpgrade: LastUpgrade | null;\n /** The releases approved to hold this app (its publisher's set, or its scope's); `null`: unrestricted. */\n approvedReleases: string[] | null;\n replicas: ReportedReplica[];\n name?: string;\n team?: string;\n /** Newer releases of its package it may be upgraded to, oldest first (at most 16, the newest). */\n availableVersions?: string[];\n}\n\n/** A mero-tee release the cluster's nodes run, with how many and whether the scope approved it. */\nexport interface ClusterRelease {\n release: string;\n nodes: number;\n approved: boolean;\n}\n\n/** `GET /auth/apps` or `GET /orgs/{org}/apps`: one page. */\nexport interface AppsReport {\n scope: ReportScope;\n governance: Governance;\n /** The scope's own approved set, newest last; `null`: none ever recorded (unrestricted). */\n approvedReleases: string[] | null;\n clusterReleases: ClusterRelease[];\n apps: ReportedApp[];\n /** Pass as `after` for the next page; `null` on the last. */\n next: string | null;\n}\n\n/** `GET /ops/apps`: one page, for the operator. */\nexport interface OpsAppsReport {\n /** This node had caught up with the system leader. */\n fresh: boolean;\n governance: Governance;\n apps: ReportedApp[];\n next: string | null;\n}\n\n/** `GET /ops/orgs`: one page, for the operator. */\nexport interface OpsOrgsReport {\n fresh: boolean;\n governance: Governance;\n orgs: Array<{ org: string; approvedReleases: string[] | null }>;\n next: string | null;\n}\n\n/** A page of a report: entries after the id `after`, at most `limit` (1 to {@link MAX_REPORT_PAGE}). */\nexport interface PageOptions {\n after?: string;\n limit?: number;\n}\n\n/** The most entries one page of a report answers (core's `MAX_REPORT_PAGE`). */\nexport const MAX_REPORT_PAGE = 100;\n\n/** `?after=&limit=` for a report route; `limit` outside 1 to 100 is refused before sending. */\nexport function pageQuery(page: PageOptions = {}): string {\n const q = new URLSearchParams();\n if (page.after !== undefined) q.set('after', page.after);\n if (page.limit !== undefined) {\n if (!Number.isInteger(page.limit) || page.limit < 1 || page.limit > MAX_REPORT_PAGE) {\n throw new RangeError(`limit is 1 to ${MAX_REPORT_PAGE}`);\n }\n q.set('limit', String(page.limit));\n }\n const s = q.toString();\n return s ? `?${s}` : '';\n}\n\n// ---------------------------------------------------------------- deadlines\n\n/** A release's end-of-new-work deadline. */\nexport interface ReleaseDeadline {\n version: string;\n /** RFC 3339. */\n after: string;\n /** Unix seconds. */\n afterSecs: number;\n}\n\n/** `GET /releases`: the cluster's release rules, public inside the sealed channel. */\nexport interface ReleaseRules {\n governance: Governance;\n /** Oldest release first. */\n deadlines: ReleaseDeadline[];\n}\n\n/** Semver order (core's `compare_versions`); text order for versions that are not semver. */\nexport function compareVersions(a: string, b: string): number {\n try {\n return compareReleaseVersions(a, b);\n } catch {\n return a < b ? -1 : a > b ? 1 : 0;\n }\n}\n\n/**\n * Whether a scope whose approved set is `approved` has lost new work at `now`\n * (Unix seconds), as core's `SystemState::stalled` judges it: a release's\n * deadline has passed and the newest approved release is older. Names the\n * newest such release, since approving it lifts every one. `null` approved\n * (unrestricted) is never stalled.\n */\nexport function stalledBy(\n approved: string[] | null,\n deadlines: ReleaseDeadline[],\n now: number = Date.now() / 1000,\n): ReleaseDeadline | null {\n if (approved === null || approved.length === 0) return null;\n const newest = approved.reduce((a, b) => (compareVersions(a, b) >= 0 ? a : b));\n let stall: ReleaseDeadline | null = null;\n for (const d of deadlines) {\n if (d.afterSecs <= now && compareVersions(newest, d.version) < 0) {\n if (stall === null || compareVersions(d.version, stall.version) > 0) stall = d;\n }\n }\n return stall;\n}\n\n// ---------------------------------------------------------------- publishers\n\n/** `GET /publishers/{signerId}`: what a key signs to bind it here next. */\nexport interface PublisherBindingInfo {\n signerId: string;\n /** The cluster's name, as the binding message names it. */\n cluster: string;\n /** How many bindings the key has had here: a signature binds once. */\n generation: number;\n bound: boolean;\n}\n\n/**\n * The text a package signing key signs to bind it to `org` as its publisher\n * (core's `system::publisher_binding_message`). Take `cluster` and\n * `generation` from {@link CalimeroClient.publisherBinding}; sign the UTF-8\n * bytes with the key's Ed25519 secret and send\n * {@link CalimeroClient.bindPublisher}.\n */\nexport function publisherBindingMessage(cluster: string, org: string, signerId: string, generation: number): string {\n return `calimero-publisher-binding/v1\\n${cluster}\\n${org}\\n${signerId}\\n${generation}`;\n}\n\n/** {@link publisherBindingMessage} as the bytes to sign. */\nexport function publisherBindingBytes(cluster: string, org: string, signerId: string, generation: number): Uint8Array {\n return new TextEncoder().encode(publisherBindingMessage(cluster, org, signerId, generation));\n}\n\n/** `POST /orgs/{org}/publishers`: the key's proof, base64url without padding. */\nexport interface PublisherProof {\n signerId: string;\n /** The Ed25519 public key the `did:key` names. */\n publicKey: string;\n /** Its signature over {@link publisherBindingMessage}. */\n signature: string;\n}\n\n// ---------------------------------------------------------------- consent page\n\n/** Whose approval a release or outbound request is for. */\nexport type ConsentScope = 'account' | { org: string };\n\n/** What the app asks its user to approve (`POST /consent/requests`). Unknown fields are refused. */\nexport type ConsentRequest =\n | {\n kind: 'release';\n scope: ConsentScope;\n /** `withdraw: true` asks to withdraw the release's approval instead of approving it. */\n subject: { version: string; withdraw?: boolean };\n /** Where the page sends the person back: the package's frontend origin, or one its manifest names. */\n returnTo: string;\n }\n | {\n kind: 'upgrade';\n subject: { app: string; toVersion: string };\n returnTo: string;\n }\n | {\n kind: 'outbound';\n scope: ConsentScope;\n /** `package`: a package-bound session's own when left out; `prefixes`: every one the latest release declares. */\n subject: { package?: string; prefixes?: string[] };\n returnTo: string;\n };\n\n/** The node's answer to a consent request: send the person to `url`. */\nexport interface ConsentStarted {\n requestId: string;\n /** The consent page, on the node's own origin. */\n url: string;\n /** Unix seconds; a request lives 10 minutes. */\n expiresAt: number;\n /**\n * The confirmation code the consent page shows, `XXX-XXX`\n * ({@link confirmationCode} of `requestId`). Show it to the person before\n * sending them to `url`: the page they land on should show the same code,\n * which tells them it is the page their request opened. Not a secret.\n * Nodes older than the code leave it out.\n */\n code?: string;\n}\n\n/** How {@link CalimeroClient.openConsentPage} sends the person to the page. */\nexport interface OpenConsentOptions {\n /** Sends the browser to the page's `url`; by default `window.location.assign`. */\n navigate?: (url: string) => void;\n /**\n * Runs after the node answers and before navigating, with the answer: show\n * the person `started.code` here so they can check the page shows the same.\n * Answer `false` and the page is not opened (the request stays on the node\n * until it expires).\n */\n confirm?: (started: ConsentStarted) => boolean | Promise<boolean>;\n}\n\nconst CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\n\n/**\n * The confirmation code the node's consent page shows for `requestId`: the\n * first 30 bits of SHA-256 of its UTF-8 bytes, big-endian, as six Crockford\n * base32 characters written `XXX-XXX` (core's consent page). Compare it with\n * {@link ConsentStarted.code} to check the node's answer.\n */\nexport async function confirmationCode(requestId: string): Promise<string> {\n const h = new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(requestId)));\n const word = ((h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3]) >>> 0;\n let code = '';\n for (let i = 0; i < 6; i++) {\n if (i === 3) code += '-';\n code += CROCKFORD[(word >>> (27 - 5 * i)) & 31];\n }\n return code;\n}\n\nexport type ConsentStatus = 'pending' | 'approved' | 'declined';\n\n/** `GET /consent/{id}/result`. */\nexport interface ConsentResult {\n requestId: string;\n kind: ConsentRequest['kind'];\n status: ConsentStatus;\n /** Unix seconds, once decided. */\n decidedAt: number | null;\n}\n\n/**\n * What the consent page put on `returnTo` when it sent the person back, or\n * `null` when `href` carries none. A hint only (anyone can type a URL): confirm\n * with {@link CalimeroClient.consentResult} before acting on it.\n */\nexport function consentReturn(href: string | URL): { requestId: string; result: 'approved' | 'declined' } | null {\n const url = typeof href === 'string' ? new URL(href) : href;\n const requestId = url.searchParams.get('request_id');\n const result = url.searchParams.get('result');\n if (!requestId || (result !== 'approved' && result !== 'declined')) return null;\n return { requestId, result };\n}\n\n// ---------------------------------------------------------------- pending\n\n/** The public verifier for mero-tee releases (`attestation-verifier`). */\nexport const RELEASE_VERIFIER = 'https://mero-tee.vercel.app';\n\n/** A mero-tee release's notes on GitHub. */\nexport function releaseNotesUrl(version: string): string {\n return `https://github.com/calimero-network/mero-tee/releases/tag/mero-tee-v${encodeURIComponent(version)}`;\n}\n\n/** The public verifier's page for a mero-tee release. */\nexport function verifyReleaseUrl(version: string): string {\n return `${RELEASE_VERIFIER}/mero-tee?release_tag=${encodeURIComponent(`mero-tee-v${version}`)}`;\n}\n\n/** A mero-tee release the cluster's nodes run that the scope has not approved. */\nexport interface PendingRelease {\n version: string;\n /** How many of the cluster's nodes run it. */\n nodes: number;\n /** Whether the scope's side holds release approvals (else the operator does). */\n actionable: boolean;\n releaseNotesUrl: string;\n verifyUrl: string;\n /** Its deadline, when it carries one. */\n deadline: ReleaseDeadline | null;\n}\n\n/** An app with newer releases of its package. */\nexport interface PendingUpgrade {\n app: string;\n name: string | null;\n package: string;\n from: string;\n /** The newest it may move to. */\n to: string;\n /** Every newer release it may move to, oldest first. */\n available: string[];\n /** Whether owners hold app upgrades on this cluster; the node checks the package's own `upgrades` when asked. */\n actionable: boolean;\n}\n\n/** What {@link CalimeroClient.pendingApprovals} answers. */\nexport interface PendingApprovals {\n scope: ReportScope;\n governance: Governance;\n approvedReleases: string[] | null;\n releases: PendingRelease[];\n upgrades: PendingUpgrade[];\n /** A passed deadline has stopped new work for the scope: approve `stalledBy.version` (or newer) to lift it. */\n stalledBy: ReleaseDeadline | null;\n /** Whether anything here is the user's to approve. */\n actionable: boolean;\n}\n\n/**\n * The pending list from a scope's report pages (every page's apps\n * concatenated into `report.apps`) and the cluster's release rules.\n */\nexport function pendingApprovalsFrom(report: AppsReport, rules: ReleaseRules, now: number = Date.now() / 1000): PendingApprovals {\n const deadlineOf = (v: string) => rules.deadlines.find((d) => d.version === v) ?? null;\n const releasesActionable = report.governance.releases === 'owner';\n const upgradesActionable = report.governance.appUpgrades === 'owner';\n const releases: PendingRelease[] = report.clusterReleases\n .filter((r) => !r.approved)\n .sort((a, b) => compareVersions(b.release, a.release))\n .map((r) => ({\n version: r.release,\n nodes: r.nodes,\n actionable: releasesActionable,\n releaseNotesUrl: releaseNotesUrl(r.release),\n verifyUrl: verifyReleaseUrl(r.release),\n deadline: deadlineOf(r.release),\n }));\n const upgrades: PendingUpgrade[] = [];\n for (const a of report.apps) {\n const available = a.availableVersions ?? [];\n if (a.package === null || available.length === 0) continue;\n upgrades.push({\n app: a.app,\n name: a.name ?? null,\n package: a.package.package,\n from: a.package.version,\n to: available[available.length - 1],\n available,\n actionable: upgradesActionable,\n });\n }\n return {\n scope: report.scope,\n governance: report.governance,\n approvedReleases: report.approvedReleases,\n releases,\n upgrades,\n stalledBy: stalledBy(report.approvedReleases, rules.deadlines, now),\n actionable: releases.some((r) => r.actionable) || upgrades.some((u) => u.actionable),\n };\n}\n\n/**\n * The consent request that approves `version` for `scope`, or with\n * `{ withdraw: true }` withdraws its approval ({@link withdrawConsent}).\n */\nexport function releaseConsent(\n scope: ReportScope,\n version: string,\n returnTo: string,\n options: { withdraw?: boolean } = {},\n): ConsentRequest {\n return {\n kind: 'release',\n scope: scope.kind === 'org' ? { org: scope.org } : 'account',\n subject: options.withdraw ? { version, withdraw: true } : { version },\n returnTo,\n };\n}\n\n/**\n * The consent request that withdraws `version`'s approval for `scope`: nodes\n * on it are then sent none of the scope's apps' data (nothing already there\n * moves). The page fetches no measurements for it. Withdrawing the scope's\n * last approved release is refused on the page (`400 REJECTED`, the request\n * stays pending), and the page warns before.\n */\nexport function withdrawConsent(scope: ReportScope, version: string, returnTo: string): ConsentRequest {\n return releaseConsent(scope, version, returnTo, { withdraw: true });\n}\n\n/**\n * The `release` part of a release request's model, as the consent page reads\n * it (`GET /consent/{id}/model`, on the node's origin; the app never needs\n * it). An approval carries the release's signed measurements; a withdrawal\n * carries none, and says whether the release is approved now and whether it\n * is the scope's last approved release (which cannot be withdrawn).\n */\nexport type ConsentReleaseModel =\n | {\n version: string;\n change: 'approve';\n alreadyApproved: boolean;\n approved: unknown;\n nodes: unknown;\n profile: string | null;\n measurements: Record<string, unknown>;\n }\n | {\n version: string;\n change: 'withdraw';\n currentlyApproved: boolean;\n lastApproved: boolean;\n approved: unknown;\n nodes: unknown;\n profile: string | null;\n };\n\n/** The consent request that upgrades `app` to `toVersion`. */\nexport function upgradeConsent(app: string, toVersion: string, returnTo: string): ConsentRequest {\n return { kind: 'upgrade', subject: { app, toVersion }, returnTo };\n}\n", "/**\n * Client for Calimero 1.0, the confidential cloud: one app = one replicated log on\n * attested nodes; this client verifies the node, seals every request to it,\n * signs people in with passkeys and machines with API keys.\n *\n * ```ts\n * const cloud = new CalimeroClient({ baseUrl, policy: { release: { minReleaseVersion: '2.3.109' } } });\n * await cloud.signIn(browserPasskey());\n * const { result } = await cloud.call(appId, 'set', { key: 'a', value: '1' });\n * ```\n */\n\nimport { SealedTransportError, createSealedFetch } from '../sealed/sealed.js';\nimport { fetchAttestedKey, type AttestationDoc, type CloudPolicy } from './attestation.js';\nimport { DEFAULT_DIRECTORY, orderNodes, readDirectory } from './directory.js';\nimport {\n CalimeroError,\n ConfirmCancelled,\n ConfirmRequired,\n LoginRequired,\n UnavailableError,\n WrongNode,\n errorFrom,\n} from './errors.js';\nimport { b64url, fromB64url, type PasskeyProvider } from './passkey.js';\nimport {\n confirmationCode,\n pageQuery,\n pendingApprovalsFrom,\n type AppsReport,\n type ConsentRequest,\n type ConsentResult,\n type ConsentStarted,\n type OpenConsentOptions,\n type OpsAppsReport,\n type OpsOrgsReport,\n type PageOptions,\n type PendingApprovals,\n type PublisherBindingInfo,\n type PublisherProof,\n type ReleaseRules,\n type ReportedApp,\n} from './approvals.js';\n\nexport {\n AppError,\n ArgsTooLarge,\n CalimeroError,\n ConfirmCancelled,\n ConfirmRequired,\n IdempotencyMismatch,\n LoginRequired,\n ConsentStale,\n NotFound,\n ReleaseDeadlineError,\n TrapError,\n UnavailableError,\n WrongNode,\n errorFrom,\n} from './errors.js';\nexport type { Committed } from './errors.js';\n\nexport interface CalimeroSession {\n accountId: string;\n sessionToken: string;\n expiresAt: number;\n refreshToken: string;\n}\n\nexport interface CallResult {\n index: number;\n result: unknown;\n events: Array<{ kind: string; data: unknown }>;\n}\n\nexport interface ViewResult {\n index: number;\n result: unknown;\n}\n\nexport interface CloudEvent {\n id: string;\n kind: string;\n data: unknown;\n}\n\n/** What installing a package release answers. */\nexport interface PackageInstalled {\n package: string;\n version: string;\n signerId: string;\n /** Service name (`''` for a single-service bundle) -> the bundle hash it runs as. */\n services: Record<string, string>;\n}\n\n/** An installed package and its releases. */\nexport interface PackageInfo {\n package: string;\n signerId: string;\n owner: string;\n latest: string | null;\n versions: Array<{\n version: string;\n mpk: string;\n size: number;\n source: 'registry' | 'upload';\n services: Record<string, string>;\n metadata: unknown;\n outbound: string[];\n installedBy: string;\n installedAt: number;\n }>;\n}\n\n/** One app instance as `listApps` answers it. */\nexport interface AppInfo {\n appId: string;\n name: string;\n owner: string;\n org: string | null;\n bundle: string;\n package: string | null;\n version: string | null;\n /** The deployment it was created from, if any. */\n deployment?: string | null;\n}\n\n/**\n * An organization-wide upgrade run, as `upgradeOrg`, `upgradeRun` and\n * `retryUpgradeRun` answer it (core's `UpgradeRun`).\n */\nexport interface UpgradeRun {\n runId: string;\n package: string;\n version: string;\n team?: string;\n cascade: boolean;\n /** The account that started it, or `operator`. */\n by: string;\n startedAt: number;\n apps: string[];\n done: string[];\n /** App id -> why its upgrade failed. */\n failed: Record<string, unknown>;\n finished: boolean;\n}\n\n/** One of an app's blobs: `blobId` base58 (what apps print), `id` hex. */\nexport interface BlobInfo {\n blobId: string;\n id: string;\n size: number;\n}\n\n/** One device present in an app (`publishPresence`); `state` hex, `null` once retracted. */\nexport interface PresenceEntry {\n account: string;\n device: string;\n state: string | null;\n}\n\n/** What an organization-wide upgrade targets. */\nexport interface OrgUpgradeTarget {\n package: string;\n version: string;\n /** Only this team's apps (and, with `cascade`, those of the teams below it). */\n team?: string;\n cascade?: boolean;\n migrate?: string;\n}\n\n/**\n * `GET /orgs/{org}`: the organization as the caller sees it. Besides its\n * members, teams and metadata, who may approve its releases, the package\n * signing keys it publishes, and whether a passed release deadline has\n * stopped new work on its own set.\n */\nexport interface OrgInfo extends Record<string, unknown> {\n /** Accounts holding `APPROVE_RELEASES` there (owner and admins included). */\n releaseApprovers: string[];\n /** The signer ids (`did:key`) bound to it as publisher. */\n publishes: string[];\n /** `null` unless a deadline stopped new work: approve `release` (or newer) to lift it. */\n newWorkStopped: { release: string; after: string } | null;\n}\n\n/** A blob's bytes with the content type the node serves them as. */\nexport interface BlobContent {\n data: Uint8Array;\n /** What the uploader gave (component apps); `application/octet-stream` otherwise. */\n contentType: string;\n}\n\n/** One xcall that was never delivered (core's `DeadLetter`). */\nexport interface DeadLetter {\n seq: number;\n /** The target app. */\n app: string;\n method: string;\n reason: string;\n /** The log entry's timestamp it was dead-lettered at (ms since the epoch). */\n atMs: number;\n}\n\n/** `GET /apps/{app}/xcalls`: a component app's outbox and its dead letters, newest last. */\nexport interface AppXcalls {\n /** Messages waiting in the outbox. */\n pending: number;\n deadLetters: DeadLetter[];\n}\n\n/**\n * An account or an organization, as a deployer, a deployment's owner or the\n * cluster's owner: `{ account: id }` or `{ org: id }`.\n */\nexport type Deployer = { account: string } | { org: string };\n\n/** A deployer's key, as `GET /deployers` lists it and `DELETE /deployers/{key}` takes it. */\nexport function deployerKey(deployer: Deployer): string {\n return 'account' in deployer ? `account:${deployer.account}` : `org:${deployer.org}`;\n}\n\n/** One deployer grant, as `GET /deployers` lists it. */\nexport interface DeployerGrant {\n /** `account:{id}` or `org:{id}`. */\n key: string;\n deployer: Deployer | null;\n /** RFC 3339; `null`: it does not end. */\n until: string | null;\n untilSecs: number | null;\n grantedAt: string;\n grantedBy: string;\n}\n\n/** `GET /deployers`: who may install apps on the cluster, and who grants it. */\nexport interface DeployersInfo {\n /** `open` (any account) or `granted` (deployers only); absent on a default cluster. */\n deployments?: 'open' | 'granted';\n /** Who grants deployers: `operator` (its key) or `owner` (the cluster's owner, with a passkey). */\n deployers?: 'operator' | 'owner';\n owner: Deployer | null;\n grants: DeployerGrant[];\n}\n\n/** One app a deployment offers, as its managers read it. */\nexport interface DeploymentOffer {\n /** The app's name in the deployment. */\n app: string;\n package: string;\n version: string;\n addedBy: string;\n /** RFC 3339. */\n addedAt: string;\n}\n\n/** A deployment as its managers read it (`GET /deployments`). */\nexport interface DeploymentInfo {\n id: string;\n name: string;\n owner: Deployer;\n apps: DeploymentOffer[];\n createdBy: string;\n /** RFC 3339. */\n createdAt: string;\n}\n\n/**\n * `GET /deployments/{id}`, public: what a frontend and the customer's consent\n * show. Never its managers, members or customers.\n */\nexport interface PublicDeployment {\n id: string;\n name: string;\n /** The owner's kind and name (`null` if it is gone). */\n owner: { kind: 'account' | 'org'; name: string | null };\n apps: Array<{ app: string; package: string; version: string }>;\n}\n\n/** `GET /deployments/{id}/orgs`: the organizations with instances created from a deployment. */\nexport interface DeploymentOrgs {\n deployment: string;\n orgs: Array<{\n orgId: string;\n name: string | null;\n instances: number;\n /** Which of the deployment's apps they run, at which release. */\n apps: Array<{ app: string; version: string }>;\n /** RFC 3339: when its first instance from the deployment was created. */\n firstCreatedAt: string;\n }>;\n /** Instances outside any organization, counted only. */\n outsideOrgs: number;\n}\n\n/**\n * A package frontend's `/.well-known/calimero.json`: the package, its\n * releases, the deployments offering it and the cluster's API URLs.\n */\nexport interface FrontendManifest {\n package: string;\n versions: string[];\n deployments: Array<{ id: string; name: string; app: string; version: string }>;\n api: string[];\n}\n\n/**\n * Read the `/.well-known/calimero.json` of the frontend at `origin` (by\n * default the page's own). Served in the clear by the frontend host, like the\n * page itself: for choosing a deployment and the API URL to connect to, never\n * for trust (the client attests the node it then talks to).\n */\nexport async function frontendManifest(origin?: string, fetcher: typeof fetch = fetch): Promise<FrontendManifest> {\n const base = origin ?? (globalThis as { location?: { origin?: string } }).location?.origin;\n if (!base) throw new Error('no page origin to read the frontend manifest from; pass `origin`');\n const response = await fetcher(new URL('/.well-known/calimero.json', base).toString());\n if (!response.ok) throw await refusal(response);\n const manifest = (await response.json()) as FrontendManifest;\n return { ...manifest, deployments: manifest.deployments ?? [] };\n}\n\n/**\n * The deployment a frontend page was opened for: the node serves\n * `/d/{deployment}/` by redirecting to `/{version}/\u2026?deployment={id}`, so the\n * page creates its instances from that deployment\n * (`createApp(name, { deployment, package })`). `null` when the page was\n * not opened through a deployment. `href` defaults to `window.location.href`.\n */\nexport function pageDeployment(href?: string): string | null {\n const at = href ?? (globalThis as { location?: { href?: string } }).location?.href;\n if (!at) return null;\n try {\n return new URL(at).searchParams.get('deployment') || null;\n } catch {\n return null;\n }\n}\n\n/** One URL path segment, so an id cannot reach another route. */\nfunction seg(value: string): string {\n return encodeURIComponent(value);\n}\n\n/**\n * The node refuses an envelope past its 64 MiB sealed cap with `413` in the\n * clear, before opening it, so the refusal arrives as the transport's. To the\n * caller it is the API's `TOO_LARGE`, as the Rust client reports it.\n */\nfunction sealedError(error: unknown): unknown {\n if (error instanceof SealedTransportError && error.status === 413) {\n return errorFrom(413, {\n error: 'TOO_LARGE',\n message: error.message.replace(/^Sealed request refused: /, ''),\n });\n }\n return error;\n}\n\n/** Read a refused response's body and map it ({@link errorFrom}). */\nasync function refusal(response: Response): Promise<CalimeroError> {\n const text = await response.text().catch(() => '');\n let body: unknown = {};\n try {\n body = text ? JSON.parse(text) : {};\n } catch {\n body = { message: text };\n }\n return errorFrom(response.status, body, response.headers.get('retry-after'));\n}\n\n/** Server-sent event frames from a response body: `{ id, kind, data }` each, `data` parsed as JSON when it is. */\nasync function* sseFrames(body: ReadableStream<Uint8Array>): AsyncGenerator<CloudEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n for (;;) {\n const { value, done } = await reader.read();\n if (done) return;\n buffer += decoder.decode(value, { stream: true });\n let cut: number;\n while ((cut = buffer.indexOf('\\n\\n')) >= 0) {\n const frame = buffer.slice(0, cut);\n buffer = buffer.slice(cut + 2);\n let id = '';\n let kind = '';\n let data = '';\n for (const line of frame.split('\\n')) {\n if (line.startsWith('id:')) id = line.slice(3).trim();\n else if (line.startsWith('event:')) kind = line.slice(6).trim();\n else if (line.startsWith('data:')) data += line.slice(5).trim();\n }\n if (!kind && !data) continue;\n let parsed: unknown = data;\n try {\n parsed = JSON.parse(data);\n } catch {\n /* plain text */\n }\n yield { id, kind, data: parsed };\n }\n }\n}\n\n/** Bytes as lower-case hex. */\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * A key for a call the caller gave none, made once so every retry shares it:\n * `node:c-` and 16 random bytes in base64url without padding, as the Rust\n * client mints it. It only has to outlive this client's own retries, so it\n * takes the node's short-lived class: a key starting `node:` is kept 10\n * minutes, a caller's own key 24 hours.\n * `getRandomValues`, not `randomUUID`, which a page outside a secure context lacks.\n */\nfunction newIdempotencyKey(): string {\n return `node:c-${b64url(crypto.getRandomValues(new Uint8Array(16)))}`;\n}\n\n/**\n * How a call or a view is sent again while the node is unavailable (D70): with\n * the same key, after a backoff that starts at `baseDelayMs` and doubles up to\n * `maxDelayMs`, no jitter, at most `retries` times. The defaults are the Rust\n * client's: 6 retries, 200 ms doubling, at most 2 s (about 9 s in all, past a\n * leader election).\n */\nexport interface CloudRetryOptions {\n /** Retries after the first attempt. Default 6. */\n retries?: number;\n /** The first backoff; each retry doubles it. Default 200 ms. */\n baseDelayMs?: number;\n /** The longest backoff. Default 2 s. */\n maxDelayMs?: number;\n}\n\nexport const DEFAULT_RETRY = { retries: 6, baseDelayMs: 200, maxDelayMs: 2000 } as const;\n\n/** The backoff before retry `retry` (0 for the first): `baseDelayMs` doubling, at most `maxDelayMs`. */\nexport function retryDelayMs(retry: number, options: { baseDelayMs: number; maxDelayMs: number }): number {\n return Math.min(options.baseDelayMs * 2 ** retry, options.maxDelayMs);\n}\n\nexport interface CalimeroClientOptions {\n /** One node of the cluster: the one the client talks to first. */\n baseUrl: string;\n /**\n * Other nodes of the same cluster, in the order to move to them when a node\n * answers `421 WRONG_NODE` (its release may not serve this account), or stays\n * unavailable to a call or a view through all its retries. Each is attested\n * under the same `policy` before anything is sent to it. Without them a `421`\n * reaches the caller as {@link WrongNode}.\n */\n nodes?: string[];\n policy: CloudPolicy;\n /** Fetch that carries attestation and envelopes. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /** How calls and views retry a 503 or a failed connection. */\n retry?: CloudRetryOptions;\n}\n\n/** How {@link CalimeroClient.connect} reaches a Calimero Cloud cluster by name. */\nexport interface CalimeroConnectOptions {\n /** The cluster's name, e.g. `eu-shared-1`. */\n cluster: string;\n /** What every node must attest to before anything is sent to it. */\n policy: CloudPolicy;\n /** The node directory to ask. Default {@link DEFAULT_DIRECTORY}. */\n directory?: string;\n /** Try the nodes in this zone (e.g. `europe-west4-a`) first. */\n zone?: string;\n /** Fetch for the directory, attestation and envelopes. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /** How calls and views retry a 503 or a failed connection. */\n retry?: CloudRetryOptions;\n /** Randomness for the weighted node order, in [0, 1). Defaults to `Math.random`. */\n random?: () => number;\n}\n\n/** Where a client made by {@link CalimeroClient.connect} re-reads its node list. */\ninterface DirectorySource {\n directory: string;\n cluster: string;\n zone: string | undefined;\n random: () => number;\n /** When the listing is due to be read again (ms since the epoch). */\n due: number;\n /** The re-read under way, if any. */\n reading?: Promise<void>;\n}\n\n/**\n * The ceremonies that mint a session, which {@link CalimeroClient.send} never\n * repeats by itself: a sign-in or sign-up is started again by its caller (with\n * the passkey), and a refresh moves through the nodes in\n * {@link CalimeroClient.exchangeRefresh}. A node answers them `421 WRONG_NODE`\n * before it spends the challenge or the refresh token (core #4774).\n */\nfunction ceremony(path: string): boolean {\n return path === 'auth/refresh' || path.startsWith('auth/passkey/');\n}\n\nexport class CalimeroClient {\n /** Every node this client may use, `baseUrl` first (or as the directory last ordered them). */\n private nodeUrls: string[];\n /** The one in use: an index into {@link nodeUrls}. */\n private at = 0;\n /** A sealed fetch per node, each attesting its own node on first use. */\n private readonly channels = new Map<string, typeof fetch>();\n private readonly policy: CloudPolicy;\n /** The unsealed fetch, for the one route served in the clear (`/attestation`). */\n private readonly raw: typeof fetch;\n private auth: string | undefined;\n private current: CalimeroSession | undefined;\n /** The refresh under way, which every request that needs one shares. */\n private refreshing: Promise<CalimeroSession> | undefined;\n private readonly retry: Required<CloudRetryOptions>;\n /** Rejections of the underlying `fetch` itself: the node could not be reached or dropped the connection. */\n private readonly networkFailures = new WeakSet<object>();\n /** The directory the node list came from, for a client made by {@link connect}. */\n private source: DirectorySource | undefined;\n\n /**\n * A client for the Calimero Cloud cluster named `cluster`: its node list read\n * from the public node directory, those in `zone` first, each group in\n * weighted-random order. The directory only picks which nodes to try: each is\n * attested under `policy` before anything is sent to it. Throws\n * {@link DirectoryError} when the directory names no usable node.\n *\n * The list is read again in the background after a failover, and at the\n * first request once the directory's `refreshAfterSeconds` has passed.\n */\n static async connect(options: CalimeroConnectOptions): Promise<CalimeroClient> {\n const directory = options.directory ?? DEFAULT_DIRECTORY;\n const random = options.random ?? Math.random;\n const fetcher = options.fetch ?? ((input, init) => fetch(input, init));\n const listing = await readDirectory(directory, options.cluster, fetcher);\n const [baseUrl, ...nodes] = orderNodes(listing.nodes, options.zone, random);\n const client = new CalimeroClient({ baseUrl, nodes, policy: options.policy, fetch: options.fetch, retry: options.retry });\n client.source = {\n directory,\n cluster: options.cluster,\n zone: options.zone,\n random,\n due: Date.now() + listing.refreshAfterSeconds * 1000,\n };\n return client;\n }\n\n constructor(options: CalimeroClientOptions) {\n const trim = (url: string) => url.replace(/\\/+$/, '');\n this.nodeUrls = [...new Set([options.baseUrl, ...(options.nodes ?? [])].map(trim))];\n this.policy = options.policy;\n this.retry = { ...DEFAULT_RETRY, ...options.retry };\n const given = options.fetch ?? ((input, init) => fetch(input, init));\n // `fetch` rejects with a `TypeError` when it gets no answer: the connection\n // was refused, reset or dropped before the response. The sealed fetch passes\n // that rejection on unchanged, so it is recognised here, at its source, and\n // not by its type alone (a bad URL is a `TypeError` too, and is not retried).\n const raw: typeof fetch = async (input, init) => {\n try {\n return await given(input, init);\n } catch (error) {\n if (error instanceof TypeError) this.networkFailures.add(error);\n throw error;\n }\n };\n this.raw = raw;\n }\n\n /** The node requests go to now: `baseUrl`, until a `421 WRONG_NODE` or a failover moved the client on. */\n get nodeUrl(): string {\n return this.nodeUrls[this.at];\n }\n\n /** Every node this client may use, in the order it moves through them. */\n get nodes(): string[] {\n return [...this.nodeUrls];\n }\n\n /** The sealed channel to `url`, attested under the client's policy before its first request. */\n private channel(url: string): typeof fetch {\n let sealed = this.channels.get(url);\n if (!sealed) {\n sealed = createSealedFetch({\n baseUrl: url,\n transportPublicKey: () => fetchAttestedKey(url, this.policy, this.raw),\n fetch: this.raw,\n });\n this.channels.set(url, sealed);\n }\n return sealed;\n }\n\n /**\n * Move on from node `from` (the one that answered `421 WRONG_NODE`) to the\n * next one. False when there is no other. A request that saw the same node\n * refuse after another request moved on already does not move again.\n */\n private moveOn(from: string): boolean {\n if (this.nodeUrls.length < 2) return false;\n if (this.nodeUrl === from) this.at = (this.at + 1) % this.nodeUrls.length;\n return true;\n }\n\n /**\n * Fail over from node `from`, where a request's retries ran out, to the next\n * node it has not `tried`. False when it has tried them all. A request whose\n * node another request moved away from already goes to that node, if untried.\n */\n private failOver(from: string, tried: Set<string>): boolean {\n if (this.nodeUrl !== from && !tried.has(this.nodeUrl)) return true;\n const count = this.nodeUrls.length;\n for (let step = 1; step < count; step++) {\n const next = (this.at + step) % count;\n if (!tried.has(this.nodeUrls[next])) {\n this.at = next;\n this.reread();\n return true;\n }\n }\n return false;\n }\n\n /**\n * Read the node list again from the directory, in the background, for a\n * client made by {@link connect}: the node in use stays first, then the\n * directory's order; a node no longer listed is dropped. A failed read is\n * ignored. One read at a time.\n */\n private reread(): void {\n const source = this.source;\n if (!source || source.reading) return;\n source.reading = readDirectory(source.directory, source.cluster, this.raw)\n .then((listing) => {\n const current = this.nodeUrl;\n const listed = orderNodes(listing.nodes, source.zone, source.random);\n this.nodeUrls = [current, ...listed.filter((url) => url !== current)];\n this.at = 0;\n source.due = Date.now() + listing.refreshAfterSeconds * 1000;\n })\n .catch(() => undefined)\n .finally(() => {\n source.reading = undefined;\n });\n }\n\n /** Authenticate every request with an API key. */\n useApiKey(key: string): void {\n this.auth = key;\n this.current = undefined;\n }\n\n useSession(session: CalimeroSession): void {\n this.auth = session.sessionToken;\n this.current = session;\n }\n\n get session(): CalimeroSession | undefined {\n return this.current;\n }\n\n /**\n * Send one request to the node in use, with the credential held now, and\n * answer the response, whatever its status. {@link send} judges it.\n */\n private async request(\n method: string,\n path: string,\n body?: unknown,\n raw?: Uint8Array,\n contentType = 'application/wasm',\n signal?: AbortSignal,\n ): Promise<Response> {\n const headers: Record<string, string> = {};\n if (this.auth) headers.authorization = `Bearer ${this.auth}`;\n let payload: BodyInit | undefined;\n if (raw) {\n headers['content-type'] = contentType;\n payload = raw as unknown as BodyInit;\n } else if (body !== undefined) {\n headers['content-type'] = 'application/json';\n payload = JSON.stringify(body);\n }\n if (this.source && Date.now() >= this.source.due) this.reread();\n const url = this.nodeUrl;\n try {\n return await this.channel(url)(`${url}/${path}`, { method, headers, body: payload, signal });\n } catch (error) {\n throw sealedError(error);\n }\n }\n\n /**\n * {@link request}, answering what a lost issuing node or a node on the\n * wrong release does to a session: a successful response, or the refusal as a\n * typed error ({@link errorFrom}).\n *\n * - `401 UNAUTHENTICATED` to a request that carried a session: the node that\n * signed the session may be gone, replaced, or out of reach of the node\n * asked, which any node of the cluster answers with a refresh. The client\n * refreshes once, shared by every request that needs it at the same time\n * ({@link refresh}), and repeats the request once. A refresh that is\n * refused surfaces as {@link LoginRequired}.\n * - `421 WRONG_NODE`: this node's release may not serve the account. The\n * client moves to the next node it knows and repeats the request once; with\n * none, the {@link WrongNode} reaches the caller.\n *\n * Repeating is safe even for a request that is not idempotent: the node\n * answers `401` and `421` when it judges the credential, before it reads what\n * the request asks, so the first attempt ran nothing. The exceptions are the\n * ceremonies that mint a session ({@link ceremony}), never repeated here.\n */\n private async send(\n method: string,\n path: string,\n body?: unknown,\n raw?: Uint8Array,\n contentType?: string,\n signal?: AbortSignal,\n ): Promise<Response> {\n let refreshed = false;\n let moved = false;\n for (;;) {\n const [token, at] = [this.auth, this.nodeUrl];\n const response = await this.request(method, path, body, raw, contentType, signal);\n if (response.ok) return response;\n const error = await refusal(response);\n if (error instanceof WrongNode && !moved) {\n moved = true;\n if (this.moveOn(at) && !ceremony(path)) continue;\n } else if (error instanceof LoginRequired && !refreshed && this.mayRefresh(token, path)) {\n refreshed = true;\n await this.renew(token as string);\n continue;\n }\n throw error;\n }\n }\n\n /** Whether a `401` to a request sent with `token` is one a refresh may answer. */\n private mayRefresh(token: string | undefined, path: string): boolean {\n return token !== undefined && this.current !== undefined && !ceremony(path);\n }\n\n /**\n * A fresh session in place of the one `token` belonged to: by the refresh\n * another request already made, or by one this request starts.\n */\n private async renew(token: string): Promise<void> {\n if (this.auth !== token) return;\n await this.refresh();\n }\n\n private async json<T>(\n method: string,\n path: string,\n body?: unknown,\n raw?: Uint8Array,\n contentType?: string,\n ): Promise<T> {\n const response = await this.send(method, path, body, raw, contentType);\n const text = await response.text();\n return (text ? JSON.parse(text) : {}) as T;\n }\n\n /**\n * {@link json} for a call or a view (D70): while the node answers 503 or\n * cannot be reached, the same request, with the same idempotency key, is sent\n * again after {@link retryDelayMs} (or the pause the node asked for, if\n * longer), at most `retries` times. Every other answer is final.\n *\n * When a node's retries run out, the request fails over to the next node the\n * client knows and its retries start again there, with the same key: the\n * key is kept in the app's replicated log, so the cluster answers it once\n * whichever node it reaches. Each node is tried once per request. The last\n * failure surfaces as {@link UnavailableError}: the node's 503, or reason\n * `network` for a connection that failed, whose `committed` is `'unknown'`.\n *\n * `once` sends the request exactly once, to the node in use (the confirmed\n * attempt of {@link callConfirmed}, whose challenge is single-use).\n */\n private async retried<T>(method: string, path: string, body: Record<string, unknown>, once = false): Promise<T> {\n const retries = once ? 0 : this.retry.retries;\n const tried = new Set<string>();\n for (;;) {\n let unavailable: UnavailableError | undefined;\n let node = this.nodeUrl;\n for (let attempt = 0; ; attempt++) {\n node = this.nodeUrl;\n tried.add(node);\n try {\n return await this.json<T>(method, path, body);\n } catch (error) {\n if (error instanceof UnavailableError) unavailable = error;\n else if (error instanceof TypeError && this.networkFailures.has(error)) {\n unavailable = new UnavailableError('NETWORK', `the node could not be reached: ${error.message}`, {}, undefined, error);\n } else throw error;\n }\n if (attempt >= retries) break;\n const backoff = retryDelayMs(attempt, this.retry);\n await new Promise((resolve) => setTimeout(resolve, Math.max(backoff, (unavailable.retryAfter ?? 0) * 1000)));\n }\n if (once || !this.failOver(node, tried)) throw unavailable;\n }\n }\n\n post<T = Record<string, unknown>>(path: string, body: unknown = {}): Promise<T> {\n return this.json<T>('POST', path, body);\n }\n\n get<T = Record<string, unknown>>(path: string): Promise<T> {\n return this.json<T>('GET', path);\n }\n\n put<T = Record<string, unknown>>(path: string, body: unknown = {}): Promise<T> {\n return this.json<T>('PUT', path, body);\n }\n\n delete<T = Record<string, unknown>>(path: string, body?: unknown): Promise<T> {\n return this.json<T>('DELETE', path, body);\n }\n\n // ---------------------------------------------------------------- identity\n\n /** Create an account with a new passkey, and sign in. */\n async signUp(passkey: PasskeyProvider, name: string): Promise<CalimeroSession> {\n const begin = await this.post<{ challengeId: string; options: Record<string, unknown> }>(\n 'auth/passkey/register/begin',\n { name },\n );\n const registration = await passkey.create(begin.options);\n const session = await this.post<CalimeroSession>('auth/passkey/register/finish', {\n challengeId: begin.challengeId,\n registration,\n });\n this.useSession(session);\n return session;\n }\n\n /** Sign in with an existing passkey. */\n async signIn(passkey: PasskeyProvider): Promise<CalimeroSession> {\n const begin = await this.post<{ challengeId: string; options: { challenge: string; rpId: string } }>(\n 'auth/passkey/login/begin',\n );\n const assertion = await passkey.get(fromB64url(begin.options.challenge), begin.options.rpId);\n const session = await this.post<CalimeroSession>('auth/passkey/login/finish', {\n challengeId: begin.challengeId,\n assertion,\n });\n this.useSession(session);\n return session;\n }\n\n /**\n * Swap the refresh token for a new session, on whichever node the client\n * uses: any node of the cluster takes it. A refresh token is used once, so\n * calls made while one refresh is under way share it rather than sending the\n * same token again (which would revoke the session).\n */\n refresh(): Promise<CalimeroSession> {\n if (!this.refreshing) {\n const pending = this.exchangeRefresh();\n this.refreshing = pending;\n const clear = () => {\n if (this.refreshing === pending) this.refreshing = undefined;\n };\n pending.then(clear, clear);\n }\n return this.refreshing;\n }\n\n private async exchangeRefresh(): Promise<CalimeroSession> {\n const current = this.current;\n if (!current) throw new Error('no session to refresh');\n let session: CalimeroSession | undefined;\n // A node that may not serve the account answers `421 WRONG_NODE` before it\n // spends the refresh token (core #4774), so the same token goes to the next\n // node (`send` moved there already): once per node, at most.\n for (let tried = 1; session === undefined; tried++) {\n try {\n session = await this.post<CalimeroSession>('auth/refresh', { refreshToken: current.refreshToken });\n } catch (error) {\n if (!(error instanceof WrongNode) || tried >= this.nodeUrls.length) throw error;\n }\n }\n // A sign-in or another session taken while this one was refreshing wins.\n if (this.current === current) this.useSession(session);\n return session;\n }\n\n async signOut(): Promise<void> {\n await this.post('auth/logout');\n this.auth = undefined;\n this.current = undefined;\n }\n\n /** End every session of the signed-in account, on every device, this one too. */\n async signOutEverywhere(): Promise<void> {\n await this.post('auth/logout-all');\n this.auth = undefined;\n this.current = undefined;\n }\n\n me(): Promise<Record<string, unknown>> {\n return this.get('auth/me');\n }\n\n /**\n * Add another passkey (another device, `passkey`) to the signed-in account;\n * answers its credential id. The node asks for the approval of a passkey\n * the account already has (`412 CONFIRM_REQUIRED`, never the new one),\n * which `approver` gives.\n */\n async addPasskey(passkey: PasskeyProvider, approver: PasskeyProvider): Promise<string> {\n const begin = await this.post<{ challengeId: string; options: Record<string, unknown> }>('auth/passkeys/add/begin');\n const registration = await passkey.create(begin.options);\n const { credentialId } = await this.postConfirmed<{ credentialId: string }>(\n 'auth/passkeys/add/finish',\n { challengeId: begin.challengeId, registration },\n approver,\n );\n return credentialId;\n }\n\n /** Remove one of the account's passkeys (not the last), approved with `passkey` (one it has). */\n async removePasskey(credentialId: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`auth/passkeys/${seg(credentialId)}`, passkey);\n }\n\n /** Name one of the account's passkeys (a device label); `''` clears the name. */\n async labelPasskey(credentialId: string, label: string): Promise<void> {\n await this.post(`auth/passkeys/${seg(credentialId)}`, { label });\n }\n\n /** What this account uses (apps, bundle bytes, API keys, owned orgs), with the cluster's quotas. */\n usage(): Promise<Record<string, unknown>> {\n return this.get('auth/usage');\n }\n\n /**\n * The node's attestation document, unverified: for display only. Every\n * request this client sends is sealed to a key it verified itself first.\n */\n async attestation(): Promise<AttestationDoc> {\n const nonce = toHex(crypto.getRandomValues(new Uint8Array(32)));\n const response = await this.raw(`${this.nodeUrl}/attestation?nonce=${nonce}`);\n if (!response.ok) throw await refusal(response);\n return (await response.json()) as AttestationDoc;\n }\n\n /** The account's API keys (never the keys themselves). */\n async listApiKeys(): Promise<Array<Record<string, unknown>>> {\n const { keys } = await this.get<{ keys: Array<Record<string, unknown>> }>('auth/apikeys');\n return keys;\n }\n\n async revokeApiKey(keyId: string): Promise<void> {\n await this.delete(`auth/apikeys/${seg(keyId)}`);\n }\n\n /**\n * Create an API key for an agent or server, approved with the account's\n * `passkey` (`412 CONFIRM_REQUIRED`); needs a passkey session (an API key\n * is refused `403`). The key is returned once.\n */\n createApiKey(\n options: {\n label?: string;\n apps?: string[];\n methods?: string[];\n readOnly?: boolean;\n allowConfirm?: boolean;\n ttlSecs?: number;\n },\n passkey: PasskeyProvider,\n ): Promise<{ keyId: string; key: string }> {\n return this.postConfirmed('auth/apikeys', { ...options }, passkey);\n }\n\n // ---------------------------------------------------------------- apps\n\n /** Upload a raw WASM bundle (development clusters only); answers its hash. */\n async uploadBundle(wasm: Uint8Array): Promise<string> {\n const { hash } = await this.json<{ hash: string }>('POST', 'bundles', undefined, wasm);\n return hash;\n }\n\n /**\n * Upload a blob for `app`: `blobId` is base58 (what apps print), `id` hex.\n * `contentType` (default `application/octet-stream`; printable ASCII, the\n * node refuses another with `400`) is sent as the upload's `Content-Type`:\n * a component app records it and serves downloads with it. A component\n * app holding as many blobs as it may answers `429 QUOTA_EXCEEDED`.\n */\n uploadBlob(\n app: string,\n data: Uint8Array,\n contentType: string | { contentType?: string } = {},\n ): Promise<{ blobId: string; id: string; size: number }> {\n const mime = (typeof contentType === 'string' ? contentType : contentType.contentType) ?? 'application/octet-stream';\n return this.json('POST', `apps/${seg(app)}/blobs`, undefined, data, mime);\n }\n\n /** One of `app`'s blobs, by id (base58 or hex). */\n async downloadBlob(app: string, id: string): Promise<Uint8Array> {\n return (await this.blobContent(app, id)).data;\n }\n\n /**\n * Download a component app's blob with a grant one of its runs handed out\n * (`BlobRef::grant`, up to 24 h). No session needed: the grant is the\n * permission. A bad or expired grant answers `NotFound`, as a missing blob.\n */\n async downloadBlobGranted(app: string, id: string, grant: string): Promise<Uint8Array> {\n return (await this.blobContent(app, id, { grant })).data;\n }\n\n /**\n * {@link downloadBlob} (or, with `grant`, {@link downloadBlobGranted}) with\n * the content type the node serves it as: the uploader's, for a component\n * app; `application/octet-stream` otherwise.\n */\n async blobContent(app: string, id: string, options: { grant?: string } = {}): Promise<BlobContent> {\n const query = options.grant === undefined ? '' : `?grant=${encodeURIComponent(options.grant)}`;\n const response = await this.send('GET', `apps/${seg(app)}/blobs/${seg(id)}${query}`);\n return {\n data: new Uint8Array(await response.arrayBuffer()),\n contentType: response.headers.get('content-type') ?? 'application/octet-stream',\n };\n }\n\n /** `app`'s blobs. */\n async listBlobs(app: string): Promise<BlobInfo[]> {\n const { blobs } = await this.get<{ blobs: BlobInfo[] }>(`apps/${seg(app)}/blobs`);\n return blobs;\n }\n\n /** One of `app`'s blobs' id and size; `NotFound` if the app has no such blob. */\n blobInfo(app: string, id: string): Promise<BlobInfo> {\n return this.get(`apps/${seg(app)}/blobs/${seg(id)}/info`);\n }\n\n /** Delete one of `app`'s blobs (its owner, or an admin of its organization). */\n async deleteBlob(app: string, id: string): Promise<void> {\n await this.delete(`apps/${seg(app)}/blobs/${seg(id)}`);\n }\n\n // ---------------------------------------------------------------- packages\n\n /** Install a signed `.mpk` package file. */\n uploadPackage(mpk: Uint8Array): Promise<PackageInstalled> {\n return this.json('POST', 'packages', undefined, mpk, 'application/octet-stream');\n }\n\n /** Install `package@version` from the cluster's registry; every node that runs it verifies it. */\n installPackage(pkg: string, version: string): Promise<PackageInstalled> {\n return this.post('packages/install', { package: pkg, version });\n }\n\n /** Installed packages and their versions. */\n async packages(): Promise<PackageInfo[]> {\n const { packages } = await this.get<{ packages: PackageInfo[] }>('packages');\n return packages;\n }\n\n /** One installed package and its versions. */\n package(pkg: string): Promise<PackageInfo> {\n return this.get(`packages/${seg(pkg)}`);\n }\n\n /** Uninstall one version, or the whole package. Refused while an app runs it. */\n uninstallPackage(pkg: string, version?: string): Promise<Record<string, unknown>> {\n return this.delete(version === undefined ? `packages/${seg(pkg)}` : `packages/${seg(pkg)}/${seg(version)}`);\n }\n\n // ---------------------------------------------------------------- app instances\n\n /** Apps this caller reaches, optionally only those of one package or bundle. */\n async listApps(filter: { package?: string; bundle?: string } = {}): Promise<AppInfo[]> {\n const q = new URLSearchParams();\n if (filter.package) q.set('package', filter.package);\n if (filter.bundle) q.set('bundle', filter.bundle);\n const query = q.toString();\n const { apps } = await this.get<{ apps: AppInfo[] }>(query ? `apps?${query}` : 'apps');\n return apps;\n }\n\n getApp(app: string): Promise<Record<string, unknown>> {\n return this.get(`apps/${seg(app)}`);\n }\n\n /** Delete an app instance (its owner, or an admin of its organization). */\n async deleteApp(app: string): Promise<void> {\n await this.delete(`apps/${seg(app)}`);\n }\n\n /** Who may reach the app: `{ kind: 'owner' | 'org' | 'public' | 'accounts' | 'team', ... }`. */\n async setAccess(app: string, access: Record<string, unknown>): Promise<void> {\n await this.post(`apps/${seg(app)}/access`, { access });\n }\n\n /** Set the app instance's metadata (its owner, or an admin of its organization); at most 16 KiB. */\n async setAppMetadata(app: string, metadata: unknown): Promise<void> {\n await this.post(`apps/${seg(app)}/metadata`, { metadata });\n }\n\n /**\n * A component app's xcalls: how many messages wait in its outbox, and the\n * dead letters (never delivered), newest last. Its owner's or an org\n * admin's (`403` to anyone else); `409 NOT_SUPPORTED` for an app on the\n * wasmer runtime, whose xcalls are follow-ups.\n */\n appXcalls(app: string): Promise<AppXcalls> {\n return this.get(`apps/${seg(app)}/xcalls`);\n }\n\n /** What the app's storage holds: `{ keys, bytes, blobs, blobBytes }`. */\n appStorage(app: string): Promise<Record<string, unknown>> {\n return this.get(`apps/${seg(app)}/storage`);\n }\n\n /** The ABI the app's bundle embeds: `{ bundle, abi }`. */\n appAbi(app: string): Promise<Record<string, unknown>> {\n return this.get(`apps/${seg(app)}/abi`);\n }\n\n /**\n * Hand the app to another account (an organization's app only to one of its\n * members). The owner approves with `passkey`.\n */\n async transferApp(app: string, to: string, passkey: PasskeyProvider): Promise<void> {\n await this.postConfirmed(`apps/${seg(app)}/transfer`, { to }, passkey);\n }\n\n /**\n * Move an app to another release of its package (`{ version }`), another\n * package, or a bundle hash, running its migration. Answers the upgrade's\n * entry; a failed migration rejects with code `UPGRADE_FAILED` (422).\n * Where owners hold app upgrades, the node asks for the approval of\n * whoever the package's manifest names (`412 CONFIRM_REQUIRED`), which\n * `passkey` gives. Refused (`403`) to a session opened on an app's\n * frontend: an app asks its user with {@link requestConsent} instead. Past\n * a release deadline its approver has not met: {@link ReleaseDeadlineError}.\n */\n upgradeApp(\n app: string,\n target: { version?: string; package?: string; service?: string; bundle?: string; migrate?: string },\n passkey?: PasskeyProvider,\n ): Promise<{ index: number; status: string; error: unknown }> {\n const path = `apps/${seg(app)}/upgrade`;\n return passkey ? this.postConfirmed(path, target, passkey) : this.post(path, target);\n }\n\n /**\n * POST `body` to `path`, answering a `412 CONFIRM_REQUIRED` with `passkey`'s\n * assertion over the node's challenge (deleting an org, approving a release,\n * adding a member, ...): the same body again, with `confirm`. Without a\n * passkey (a caller in plain JavaScript passing none) the `412` reaches the\n * caller as {@link ConfirmRequired}, carrying the challenge.\n */\n postConfirmed<T>(path: string, body: Record<string, unknown>, passkey: PasskeyProvider): Promise<T> {\n return this.confirmed<T>('POST', path, body, passkey);\n }\n\n /**\n * {@link postConfirmed} for a DELETE (deleting an organization, removing a\n * member or a passkey): `body` (`{}` by default) goes as JSON, and the\n * confirmed retry carries `confirm` beside it.\n */\n deleteConfirmed<T>(path: string, passkey: PasskeyProvider, body: Record<string, unknown> = {}): Promise<T> {\n return this.confirmed<T>('DELETE', path, body, passkey);\n }\n\n private async confirmed<T>(\n method: 'POST' | 'DELETE',\n path: string,\n body: Record<string, unknown>,\n passkey: PasskeyProvider | undefined,\n send: (body: Record<string, unknown>) => Promise<T> = (b) => this.json<T>(method, path, b),\n ): Promise<T> {\n try {\n return await send(body);\n } catch (error) {\n if (!(error instanceof ConfirmRequired) || !passkey) throw error;\n const d = error.details as { challengeId: string; challenge: string; rpId: string; allowCredentials?: string[] };\n let assertion: Awaited<ReturnType<PasskeyProvider['get']>>;\n try {\n assertion = await passkey.get(fromB64url(d.challenge), d.rpId, d.allowCredentials);\n } catch (declined) {\n // WebAuthn rejects a prompt the user dismissed with `NotAllowedError`\n // (`AbortError` when it was aborted); anything else is a real failure.\n const name = (declined as { name?: unknown } | null)?.name;\n if (name === 'NotAllowedError' || name === 'AbortError') throw new ConfirmCancelled(declined);\n throw declined;\n }\n return send({ ...body, confirm: { challengeId: d.challengeId, assertion } });\n }\n }\n\n /**\n * Create an app instance from a bundle hash, or from a package release\n * (`{ package, version?, service? }`, installed from the registry first if\n * the cluster lacks it). With `deployment`, the instance runs the release\n * that deployment offers for `package` (`version`, if given, must be it)\n * and records the deployment; no install, no deployer grant. A package or\n * version it does not offer answers `400 NOT_OFFERED`, several offered\n * releases with no `version` `400 VERSION_REQUIRED`, and an unknown\n * `service` `400 NO_SUCH_SERVICE`. A page opened through `/d/{deployment}/`\n * finds its deployment with {@link pageDeployment}.\n */\n async createApp(\n name: string,\n bundle: string | { package: string; version?: string; service?: string; deployment?: string },\n options: {\n org?: string;\n access?: Record<string, unknown>;\n confirmMethods?: string[];\n /** Arguments for the app's `init`. A failed init rejects with code `INIT_FAILED`. */\n initArgs?: unknown;\n } = {},\n ): Promise<string> {\n const target = typeof bundle === 'string' ? { bundle } : bundle;\n const { appId } = await this.post<{ appId: string }>('apps', { name, ...target, ...options });\n return appId;\n }\n\n /**\n * Call a method. A retry with the same `idempotencyKey` is answered once.\n * Without one, the client makes one, so its own retries of a 503 share it.\n */\n call(app: string, method: string, args: unknown = {}, idempotencyKey?: string): Promise<CallResult> {\n const key = idempotencyKey ?? newIdempotencyKey();\n return this.retried('POST', `apps/${seg(app)}/intents`, { method, args, idempotencyKey: key });\n }\n\n /**\n * Call a method that needs the account holder's approval: the node returns a\n * challenge over this exact call, which `passkey` signs. A declined prompt\n * rejects with {@link ConfirmCancelled}.\n */\n async callConfirmed(\n app: string,\n method: string,\n args: unknown,\n passkey: PasskeyProvider,\n idempotencyKey?: string,\n ): Promise<CallResult> {\n const path = `apps/${seg(app)}/intents`;\n const key = idempotencyKey ?? newIdempotencyKey();\n // The confirmed attempt goes out exactly once: its challenge is single-use,\n // so a resend would be refused on the challenge, not answered from the key.\n return this.confirmed<CallResult>('POST', path, { method, args, idempotencyKey: key }, passkey, (body) =>\n this.retried<CallResult>('POST', path, body, body.confirm !== undefined),\n );\n }\n\n /** Run a read-only method: strong by default, or stale from any replica. */\n view(app: string, method: string, args: unknown = {}, options: { stale?: boolean; minIndex?: number } = {}): Promise<ViewResult> {\n return this.retried('POST', `apps/${seg(app)}/views`, {\n method,\n args,\n consistency: options.stale ? 'stale' : 'strong',\n minIndex: options.minIndex ?? 0,\n });\n }\n\n /** Committed events from index `from`, then live, until `signal` aborts. */\n events(app: string, from = 0, signal?: AbortSignal): AsyncGenerator<CloudEvent> {\n return this.stream(`apps/${seg(app)}/events?from=${from}`, signal);\n }\n\n /** A server-sent event stream on `path`, sealed like every other answer. */\n private async *stream(path: string, signal?: AbortSignal): AsyncGenerator<CloudEvent> {\n const response = await this.send('GET', path, undefined, undefined, undefined, signal);\n if (!response.body) throw new CalimeroError(response.status, 'EVENTS', 'the event stream has no body');\n yield* sseFrames(response.body);\n }\n\n // ---------------------------------------------------------------- presence\n\n /**\n * Publish this device's presence in `app`: `state` (at most 4 KiB) or `null`\n * to retract it. The newest `seq` wins; send the same `seq` and state again\n * as a heartbeat, since an entry not refreshed within 7 s is gone.\n */\n async publishPresence(app: string, seq: number, state: Uint8Array | null): Promise<void> {\n await this.post(`apps/${seg(app)}/presence`, { seq, state: state === null ? null : toHex(state) });\n }\n\n /** Who is present in `app` now. */\n async presence(app: string): Promise<PresenceEntry[]> {\n const { present } = await this.get<{ present: PresenceEntry[] }>(`apps/${seg(app)}/presence`);\n return present;\n }\n\n /**\n * Presence as a stream until `signal` aborts: a `snapshot` event (`data` the\n * entries present), then a `presence` event (`data` one entry) per change.\n */\n presenceStream(app: string, signal?: AbortSignal): AsyncGenerator<CloudEvent> {\n return this.stream(`apps/${seg(app)}/presence/stream`, signal);\n }\n\n // ---------------------------------------------------------------- aliases\n\n /** Name an app (its id or context id) for this account. */\n async setAlias(alias: string, app: string): Promise<void> {\n await this.put(`auth/aliases/${seg(alias)}`, { app });\n }\n\n /** This account's aliases, alias \u2192 app id. */\n async aliases(): Promise<Record<string, string>> {\n const { aliases } = await this.get<{ aliases: Record<string, string> }>('auth/aliases');\n return aliases;\n }\n\n /** The app an alias names. */\n async alias(alias: string): Promise<string> {\n const { appId } = await this.get<{ appId: string }>(`auth/aliases/${seg(alias)}`);\n return appId;\n }\n\n async deleteAlias(alias: string): Promise<void> {\n await this.delete(`auth/aliases/${seg(alias)}`);\n }\n\n // ---------------------------------------------------------------- organizations\n\n async createOrg(name: string): Promise<string> {\n const { orgId } = await this.post<{ orgId: string }>('orgs', { name });\n return orgId;\n }\n\n /** The organization, with the teams this caller reaches or manages. */\n getOrg(org: string): Promise<OrgInfo> {\n return this.get(`orgs/${seg(org)}`);\n }\n\n /**\n * Delete an organization with its teams, invites and apps (its owner only).\n * The node asks for the owner's passkey (`412 CONFIRM_REQUIRED`), which `passkey` gives.\n */\n async deleteOrg(org: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`orgs/${seg(org)}`, passkey);\n }\n\n /** Set the organization's metadata (an admin, or a holder of `MANAGE_METADATA`); at most 16 KiB. */\n async setOrgMetadata(org: string, metadata: unknown): Promise<void> {\n await this.post(`orgs/${seg(org)}/metadata`, { metadata });\n }\n\n /** Set a member's metadata (theirs, or an admin's); `null` clears it. */\n async setMemberMetadata(org: string, account: string, metadata: unknown): Promise<void> {\n await this.post(`orgs/${seg(org)}/members/${seg(account)}/metadata`, { metadata });\n }\n\n /**\n * Upgrade every app of `org` that runs `target.package` to `target.version`\n * (optionally one team's, with `cascade` the teams below it). The org's owner,\n * or a holder of `MANAGE_APPLICATION`, approves the whole run with `passkey`.\n * Answers the run; {@link upgradeRun} follows it.\n */\n upgradeOrg(org: string, target: OrgUpgradeTarget, passkey: PasskeyProvider): Promise<UpgradeRun> {\n return this.postConfirmed(`orgs/${seg(org)}/upgrade`, { ...target }, passkey);\n }\n\n /** An organization-wide upgrade run: its apps, those done and those that failed. */\n upgradeRun(org: string, run: string): Promise<UpgradeRun> {\n return this.get(`orgs/${seg(org)}/upgrades/${seg(run)}`);\n }\n\n /** Run the apps that failed in `run` again, as a new run, approved with `passkey`. */\n retryUpgradeRun(org: string, run: string, passkey: PasskeyProvider): Promise<UpgradeRun> {\n return this.postConfirmed(`orgs/${seg(org)}/upgrades/${seg(run)}/retry`, {}, passkey);\n }\n\n /**\n * Approve a mero-tee release to hold the apps of `org`, or of this account\n * outside any organization (`org` `null`); `approved: false` withdraws it.\n * Until then, nodes on that release get none of those apps' data. For an\n * organization, a member holding `APPROVE_RELEASES` approves with `passkey`;\n * the node binds the release's measurements itself. Refused (`403`) to a\n * session opened on an app's frontend: an app asks its user with\n * {@link requestConsent} instead.\n */\n async approveRelease(\n org: string | null,\n version: string,\n passkey: PasskeyProvider,\n approved = true,\n ): Promise<Record<string, unknown>> {\n const path = org === null ? 'auth/releases' : `orgs/${seg(org)}/releases`;\n return this.postConfirmed(path, { version, approved }, passkey);\n }\n\n /**\n * Approve the URL prefixes apps from `pkg`'s publisher may call out to, for\n * `org`'s apps or this account's own (`org` `null`). `prefixes` `'manifest'`\n * (the default) approves every prefix the package's latest release declares;\n * `replace` sets exactly `prefixes`, which is how one is revoked. Approved\n * with `passkey`. Refused (`403`) to a session opened on an app's frontend:\n * an app asks with {@link requestConsent} (`kind: 'outbound'`) instead.\n */\n async approveOutbound(\n org: string | null,\n pkg: string,\n passkey: PasskeyProvider,\n options: { prefixes?: string[] | 'manifest'; replace?: boolean } = {},\n ): Promise<Record<string, unknown>> {\n const path = org === null ? 'auth/outbound' : `orgs/${seg(org)}/outbound`;\n return this.postConfirmed(\n path,\n { package: pkg, prefixes: options.prefixes ?? 'manifest', replace: options.replace ?? false },\n passkey,\n );\n }\n\n // ---------------------------------------------------------------- approvals\n\n /**\n * One page of the report of a scope's apps: an organization's (any member;\n * `404` to anyone else) or, with `org` `null`, the account's own outside any\n * organization (a session bound to an app's frontend: that package's apps).\n * The governance, the scope's approved releases, the releases the cluster's\n * nodes run and whether each is approved, and per app its release, newer\n * releases it may move to, last upgrade and replicas.\n */\n appsReport(org: string | null, page: PageOptions = {}): Promise<AppsReport> {\n const path = org === null ? 'auth/apps' : `orgs/${seg(org)}/apps`;\n return this.get(`${path}${pageQuery(page)}`);\n }\n\n /** {@link appsReport}, every page, with the apps of all of them in `apps`. */\n async appsReportAll(org: string | null): Promise<AppsReport> {\n const first = await this.appsReport(org);\n const apps: ReportedApp[] = [...first.apps];\n let next = first.next;\n while (next !== null) {\n const page = await this.appsReport(org, { after: next });\n apps.push(...page.apps);\n next = page.next;\n }\n return { ...first, apps, next: null };\n }\n\n /** `GET /releases`: the cluster's governance and every release deadline. Public. */\n releaseRules(): Promise<ReleaseRules> {\n return this.get('releases');\n }\n\n /**\n * What waits for a decision in a scope (`org`, or the account's own apps\n * with `null`): mero-tee releases the cluster's nodes run that the scope has\n * not approved, apps with newer releases of their package, and whether a\n * passed deadline stops new work. Read over the sealed channel; act on an\n * item by sending the user to the consent page ({@link requestConsent},\n * `releaseConsent`, `upgradeConsent`).\n */\n async pendingApprovals(org: string | null = null): Promise<PendingApprovals> {\n const [report, rules] = await Promise.all([this.appsReportAll(org), this.releaseRules()]);\n return pendingApprovalsFrom(report, rules);\n }\n\n /**\n * Ask the node to ask the user: a release, upgrade or outbound approval\n * that only the account holder may make, decided on the node's own consent\n * page, never in the app. Needs a passkey session (a session bound to the\n * app's frontend is fine). Send the person to the answer's `url`; the page\n * sends them back to `returnTo?request_id=\u2026&result=approved|declined`\n * (`consentReturn`), and {@link consentResult} confirms the decision.\n */\n requestConsent(request: ConsentRequest): Promise<ConsentStarted> {\n return this.post('consent/requests', request);\n }\n\n /**\n * {@link requestConsent}, then send the browser to the consent page\n * (`navigate`, by default `window.location.assign`). Pass `navigate` itself\n * or {@link OpenConsentOptions}, whose `confirm` runs first with the node's\n * answer so the app can show the person its `code`; when it answers `false`\n * the page is not opened. When the node sends a `code` that is not\n * {@link confirmationCode} of `requestId`, it throws `CalimeroError`\n * (`CONSENT_CODE_MISMATCH`) and does not navigate. Answers the request\n * once `navigate` returns (or `confirm` declines): with a popup\n * (`url => window.open(url)`), poll it with {@link waitForConsent}.\n */\n async openConsentPage(\n request: ConsentRequest,\n navigateOrOptions: ((url: string) => void) | OpenConsentOptions = {},\n ): Promise<ConsentStarted> {\n const options = typeof navigateOrOptions === 'function' ? { navigate: navigateOrOptions } : navigateOrOptions;\n const navigate =\n options.navigate ??\n ((url: string) => {\n const w = (globalThis as { window?: { location: { assign(url: string): void } } }).window;\n if (!w) throw new Error('no window to open the consent page in; pass `navigate`');\n w.location.assign(url);\n });\n const started = await this.requestConsent(request);\n if (started.code !== undefined) {\n const expected = await confirmationCode(started.requestId);\n if (started.code !== expected) {\n throw new CalimeroError(200, 'CONSENT_CODE_MISMATCH', 'the consent page code does not match the request', {\n requestId: started.requestId,\n code: started.code,\n expected,\n });\n }\n }\n if (options.confirm && !(await options.confirm(started))) return started;\n navigate(started.url);\n return started;\n }\n\n /** The decision on a consent request (any node answers, for the account that asked). */\n consentResult(requestId: string): Promise<ConsentResult> {\n return this.get(`consent/${seg(requestId)}/result`);\n }\n\n /**\n * Poll {@link consentResult} until the request is decided, every\n * `intervalMs` (2 s), until `signal` aborts or `expiresAt` (Unix seconds)\n * passes, when it answers the last `pending` result.\n */\n async waitForConsent(\n requestId: string,\n options: { intervalMs?: number; signal?: AbortSignal; expiresAt?: number } = {},\n ): Promise<ConsentResult> {\n const interval = options.intervalMs ?? 2000;\n for (;;) {\n const result = await this.consentResult(requestId);\n if (result.status !== 'pending') return result;\n if (options.signal?.aborted) return result;\n if (options.expiresAt !== undefined && Date.now() / 1000 >= options.expiresAt) return result;\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n }\n\n /** `GET /publishers/{signerId}`: the cluster name and binding generation a key signs to bind it next. */\n publisherBinding(signerId: string): Promise<PublisherBindingInfo> {\n return this.get(`publishers/${seg(signerId)}`);\n }\n\n /**\n * Bind a package signing key to `org`, which then approves the node images\n * every instance of the key's packages runs on, and upgrades those whose\n * package declares `upgrades: publisher`. `proof` is the key's signature\n * over `publisherBindingMessage(cluster, org, signerId, generation)`; a\n * member holding `APPROVE_RELEASES` sends it with `passkey`.\n */\n bindPublisher(org: string, proof: PublisherProof, passkey: PasskeyProvider): Promise<Record<string, unknown>> {\n return this.postConfirmed(`orgs/${seg(org)}/publishers`, { ...proof }, passkey);\n }\n\n /**\n * Upgrade every instance of `pkg` whose release declares `upgrades:\n * publisher`, whoever owns it, as its publisher `org` (a\n * `MANAGE_APPLICATION` holder there), with one passkey approval. Answers\n * the run, kept on the publisher.\n */\n upgradePublished(\n org: string,\n pkg: string,\n target: { version: string; migrate?: string },\n passkey: PasskeyProvider,\n ): Promise<UpgradeRun> {\n return this.postConfirmed(`orgs/${seg(org)}/packages/${seg(pkg)}/upgrade`, { ...target }, passkey);\n }\n\n // ---------------------------------------------------------------- operator\n\n /** `GET /ops/apps`: what every app runs, without names or accounts. Operator token (`useApiKey`). */\n opsApps(page: PageOptions = {}): Promise<OpsAppsReport> {\n return this.get(`ops/apps${pageQuery(page)}`);\n }\n\n /** `GET /ops/orgs`: each organization's approved releases. Operator token. */\n opsOrgs(page: PageOptions = {}): Promise<OpsOrgsReport> {\n return this.get(`ops/orgs${pageQuery(page)}`);\n }\n\n /**\n * Announce when work on images older than `version` ends: from `after` on,\n * a scope that has not approved it (or newer) starts no new work. Operator\n * token.\n */\n async setReleaseDeadline(version: string, after: Date | string): Promise<void> {\n const at = typeof after === 'string' ? after : after.toISOString();\n await this.post(`ops/releases/${seg(version)}/deadline`, { after: at });\n }\n\n /** Lift a release's deadline. Operator token. */\n async liftReleaseDeadline(version: string): Promise<void> {\n await this.delete(`ops/releases/${seg(version)}/deadline`);\n }\n\n /** Add a member, or change their role, approved with the caller's `passkey`. */\n async setMember(\n org: string,\n account: string,\n role: 'guest' | 'member' | 'admin' | 'owner',\n passkey: PasskeyProvider,\n ): Promise<void> {\n await this.postConfirmed(`orgs/${seg(org)}/members`, { account, role }, passkey);\n }\n\n /**\n * Remove a member, or leave (`account` the caller's own), approved with the\n * caller's `passkey`.\n */\n removeMember(org: string, account: string, passkey: PasskeyProvider): Promise<Record<string, unknown>> {\n return this.deleteConfirmed(`orgs/${seg(org)}/members/${seg(account)}`, passkey);\n }\n\n /**\n * Set capability bits ({@link ORG_CAPABILITIES}): for a member (`account`),\n * for a member of one team (`account` and `team`), or the organization's\n * default (neither). Approved with the caller's `passkey`.\n */\n async setCapabilities(\n org: string,\n capabilities: number,\n passkey: PasskeyProvider,\n at: { account?: string; team?: string } = {},\n ): Promise<void> {\n await this.postConfirmed(`orgs/${seg(org)}/capabilities`, { capabilities, ...at }, passkey);\n }\n\n async createTeam(org: string, name: string, join: 'everyone' | 'invite', parent?: string): Promise<string> {\n const { teamId } = await this.post<{ teamId: string }>(`orgs/${seg(org)}/teams`, { name, join, parent });\n return teamId;\n }\n\n getTeam(org: string, team: string): Promise<Record<string, unknown>> {\n return this.get(`orgs/${seg(org)}/teams/${seg(team)}`);\n }\n\n /**\n * Rename, change who may join, set the app's metadata, or move the team:\n * `parent: null` moves it to the top, an absent `parent` leaves it.\n */\n async updateTeam(\n org: string,\n team: string,\n update: { name?: string; join?: 'everyone' | 'invite'; parent?: string | null; metadata?: unknown },\n ): Promise<void> {\n await this.post(`orgs/${seg(org)}/teams/${seg(team)}`, update);\n }\n\n /** Delete a team, the teams below it and their apps. */\n async deleteTeam(org: string, team: string): Promise<void> {\n await this.delete(`orgs/${seg(org)}/teams/${seg(team)}`);\n }\n\n /**\n * Add a member to a team, or change their row: role, lead, capability bits.\n * Approved with the caller's `passkey`.\n */\n async setTeamMember(\n org: string,\n team: string,\n account: string,\n passkey: PasskeyProvider,\n row: { role?: 'lead' | 'member' | 'readOnly'; lead?: boolean; capabilities?: number } = {},\n ): Promise<void> {\n await this.postConfirmed(`orgs/${seg(org)}/teams/${seg(team)}/members`, { account, ...row }, passkey);\n }\n\n /** Remove a member from a team, approved with the caller's `passkey`. */\n async removeTeamMember(org: string, team: string, account: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`orgs/${seg(org)}/teams/${seg(team)}/members/${seg(account)}`, passkey);\n }\n\n /**\n * Make an invite into `org` (and `teams`), approved with the caller's\n * `passkey`; answers its token, which {@link redeemInvite} takes (no\n * approval there).\n */\n async invite(\n org: string,\n role: 'guest' | 'member' | 'admin',\n passkey: PasskeyProvider,\n teams: string[] = [],\n options: { ttlSecs?: number; uses?: number } = {},\n ): Promise<string> {\n const { token } = await this.postConfirmed<{ token: string }>(\n `orgs/${seg(org)}/invites`,\n { role, teams, ...options },\n passkey,\n );\n return token;\n }\n\n redeemInvite(token: string): Promise<Record<string, unknown>> {\n return this.post(`invites/${seg(token)}/redeem`);\n }\n\n // ---------------------------------------------------------------- deployers\n\n /**\n * Let an account or organization install apps where the cluster's\n * deployments are `granted`, until `until` (RFC 3339 or a `Date`; absent,\n * the grant does not end). The cluster's owner grants it, approved with\n * `passkey`, where governance says `deployers: owner`; elsewhere the\n * operator grants with its key, and this is refused `403`.\n */\n grantDeployer(\n deployer: Deployer,\n passkey: PasskeyProvider,\n options: { until?: Date | string } = {},\n ): Promise<{ key: string; deployer: Deployer; grant: Record<string, unknown> }> {\n const until = options.until instanceof Date ? options.until.toISOString() : options.until;\n return this.postConfirmed('deployers', { deployer, ...(until === undefined ? {} : { until }) }, passkey);\n }\n\n /**\n * Who may install apps on the cluster: its deployments rule, who grants\n * deployers, its owner and every grant. For the cluster's owner, or the\n * operator (its token, `useApiKey`).\n */\n deployers(): Promise<DeployersInfo> {\n return this.get('deployers');\n }\n\n /**\n * End a deployer's grant (`deployer`, or its key `account:{id}` /\n * `org:{id}`), as the cluster's owner, approved with `passkey`. Apps it\n * installed, and the apps running them, stay.\n */\n async revokeDeployer(deployer: Deployer | string, passkey: PasskeyProvider): Promise<void> {\n const key = typeof deployer === 'string' ? deployer : deployerKey(deployer);\n await this.deleteConfirmed(`deployers/${seg(key)}`, passkey);\n }\n\n // ---------------------------------------------------------------- deployments\n\n /**\n * Create a deployment: `owner`'s (the caller's own account, or an\n * organization where it holds `MANAGE_APPLICATION` org-wide) list of the\n * apps it offers, named `name` (1 to 64 characters, one line) for\n * customers. Approved with `passkey`; where deployments are `granted` the\n * caller needs a deployer grant. Answers the deployment's id.\n */\n async createDeployment(name: string, owner: Deployer, passkey: PasskeyProvider): Promise<string> {\n const { id } = await this.postConfirmed<{ id: string }>('deployments', { name, owner }, passkey);\n return id;\n }\n\n /** The deployments the caller manages: its account's, and its organizations' where it holds `MANAGE_APPLICATION`. */\n async deployments(): Promise<DeploymentInfo[]> {\n const { deployments } = await this.get<{ deployments: DeploymentInfo[] }>('deployments');\n return deployments;\n }\n\n /** A deployment as anyone may read it: its name, its owner's kind and name, and the apps it offers. Public. */\n deployment(id: string): Promise<PublicDeployment> {\n return this.get(`deployments/${seg(id)}`);\n }\n\n /** Delete a deployment that offers nothing and has no instances, approved with `passkey`. */\n async deleteDeployment(id: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`deployments/${seg(id)}`, passkey);\n }\n\n /**\n * Offer `package@version` (installed, and seen by the caller) as `app`\n * (1 to 64 letters, digits, `.`, `_`, `-`) in deployment `id`, or move an\n * offered app to another release of its package. Approved with `passkey`.\n */\n offerApp(\n id: string,\n offer: { app: string; package: string; version: string },\n passkey: PasskeyProvider,\n ): Promise<{ deployment: string; app: string; offer: Record<string, unknown> }> {\n return this.postConfirmed(`deployments/${seg(id)}/apps`, { ...offer }, passkey);\n }\n\n /**\n * Withdraw `app` from deployment `id`, approved with `passkey`; refused\n * while an instance created from the deployment still runs it.\n */\n async withdrawApp(id: string, app: string, passkey: PasskeyProvider): Promise<void> {\n await this.deleteConfirmed(`deployments/${seg(id)}/apps/${seg(app)}`, passkey);\n }\n\n /**\n * The organizations with instances created from deployment `id`, for its\n * managers: each one's id, name, instance count, apps and releases, and\n * first instance. Never members, teams or app data.\n */\n deploymentOrgs(id: string): Promise<DeploymentOrgs> {\n return this.get(`deployments/${seg(id)}/orgs`);\n }\n}\n", "/**\n * What a member may do in an organization beyond their role, as core's\n * `caps` bits (`setCapabilities`, `setTeamMember`'s `capabilities`). A team's\n * lead and an organization's admin hold them all.\n */\nexport const ORG_CAPABILITIES = {\n /** Create an app in the organization (on its team, or org-wide). */\n CREATE_APP: 1 << 0,\n /** Mint invites (org-wide, or on each team the invite names). */\n INVITE_MEMBERS: 1 << 1,\n /** Inherited into open teams; denying it keeps a member out of them. */\n JOIN_OPEN_TEAMS: 1 << 2,\n /** Add and remove a team's members. */\n MANAGE_MEMBERS: 1 << 3,\n /** Upgrade the organization's apps (and, as a publisher, every instance of its `publisher` packages), start org upgrade runs, approve outbound hosts (org-wide). */\n MANAGE_APPLICATION: 1 << 4,\n /** Create a top-level team without being an admin. */\n CREATE_TEAM: 1 << 5,\n /** Delete a team, and what it holds, without being an admin. */\n DELETE_TEAM: 1 << 6,\n /** Change who may join a team (open or invite-only). */\n MANAGE_VISIBILITY: 1 << 7,\n /** Set the organization's and its teams' metadata. */\n MANAGE_METADATA: 1 << 8,\n /**\n * Approve (or withdraw) the mero-tee releases that hold the apps the\n * organization governs (those of the packages it publishes, and its own of\n * unbound packages), and bind a package signing key to it\n * (`bindPublisher`). Organization-wide only. Bit 9 is left unused.\n */\n APPROVE_RELEASES: 1 << 10,\n} as const;\n\nexport type OrgCapability = keyof typeof ORG_CAPABILITIES;\n\n/** What a member holds unless an admin says otherwise. */\nexport const DEFAULT_ORG_CAPABILITIES = ORG_CAPABILITIES.JOIN_OPEN_TEAMS;\n\n/** The bitmask of `names`. */\nexport function orgCapabilities(...names: OrgCapability[]): number {\n return names.reduce((mask, name) => mask | ORG_CAPABILITIES[name], 0);\n}\n", "/**\n * ChaCha20-Poly1305 (RFC 8439), the AEAD mero-agent-gate's HPKE suite uses.\n * WebCrypto has no ChaCha20, and the SDK takes no runtime dependencies, so it\n * is written here from the RFC. Its tests check it against the RFC's vectors\n * and against Node's own implementation.\n *\n * Only for sealing a provisioning bundle once: short messages, one key per\n * message. Not constant-time in Poly1305's arithmetic (BigInt), which leaks\n * nothing here: the one-time Poly1305 key is never reused.\n */\n\nconst KEY_LEN = 32;\nconst NONCE_LEN = 12;\nconst TAG_LEN = 16;\n\nfunction rotl(value: number, shift: number): number {\n return ((value << shift) | (value >>> (32 - shift))) >>> 0;\n}\n\nfunction quarterRound(s: Uint32Array, a: number, b: number, c: number, d: number): void {\n s[a] = (s[a] + s[b]) >>> 0;\n s[d] = rotl(s[d] ^ s[a], 16);\n s[c] = (s[c] + s[d]) >>> 0;\n s[b] = rotl(s[b] ^ s[c], 12);\n s[a] = (s[a] + s[b]) >>> 0;\n s[d] = rotl(s[d] ^ s[a], 8);\n s[c] = (s[c] + s[d]) >>> 0;\n s[b] = rotl(s[b] ^ s[c], 7);\n}\n\nfunction u32le(bytes: Uint8Array, offset: number): number {\n return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)) >>> 0;\n}\n\n/** One 64-byte ChaCha20 block (RFC 8439 \u00A72.3). */\nexport function chacha20Block(key: Uint8Array, counter: number, nonce: Uint8Array): Uint8Array {\n const state = new Uint32Array(16);\n state[0] = 0x61707865;\n state[1] = 0x3320646e;\n state[2] = 0x79622d32;\n state[3] = 0x6b206574;\n for (let i = 0; i < 8; i += 1) state[4 + i] = u32le(key, i * 4);\n state[12] = counter >>> 0;\n for (let i = 0; i < 3; i += 1) state[13 + i] = u32le(nonce, i * 4);\n const working = state.slice();\n for (let round = 0; round < 10; round += 1) {\n quarterRound(working, 0, 4, 8, 12);\n quarterRound(working, 1, 5, 9, 13);\n quarterRound(working, 2, 6, 10, 14);\n quarterRound(working, 3, 7, 11, 15);\n quarterRound(working, 0, 5, 10, 15);\n quarterRound(working, 1, 6, 11, 12);\n quarterRound(working, 2, 7, 8, 13);\n quarterRound(working, 3, 4, 9, 14);\n }\n const out = new Uint8Array(64);\n for (let i = 0; i < 16; i += 1) {\n const word = (working[i] + state[i]) >>> 0;\n out[i * 4] = word & 0xff;\n out[i * 4 + 1] = (word >>> 8) & 0xff;\n out[i * 4 + 2] = (word >>> 16) & 0xff;\n out[i * 4 + 3] = (word >>> 24) & 0xff;\n }\n return out;\n}\n\n/** ChaCha20 encryption from block `counter` on (RFC 8439 \u00A72.4). */\nexport function chacha20(key: Uint8Array, counter: number, nonce: Uint8Array, data: Uint8Array): Uint8Array {\n const out = new Uint8Array(data.length);\n for (let offset = 0, block = counter; offset < data.length; offset += 64, block += 1) {\n const stream = chacha20Block(key, block, nonce);\n const end = Math.min(offset + 64, data.length);\n for (let i = offset; i < end; i += 1) out[i] = data[i] ^ stream[i - offset];\n }\n return out;\n}\n\nfunction leToBigInt(bytes: Uint8Array): bigint {\n let value = 0n;\n for (let i = bytes.length - 1; i >= 0; i -= 1) value = (value << 8n) | BigInt(bytes[i]);\n return value;\n}\n\nconst P1305 = (1n << 130n) - 5n;\n\n/** Poly1305 over `message` with the one-time `key` (RFC 8439 \u00A72.5). */\nexport function poly1305(key: Uint8Array, message: Uint8Array): Uint8Array {\n const r = leToBigInt(key.subarray(0, 16)) & 0x0ffffffc0ffffffc0ffffffc0fffffffn;\n const s = leToBigInt(key.subarray(16, 32));\n let acc = 0n;\n for (let offset = 0; offset < message.length; offset += 16) {\n const block = message.subarray(offset, Math.min(offset + 16, message.length));\n const n = leToBigInt(block) + (1n << BigInt(8 * block.length));\n acc = ((acc + n) * r) % P1305;\n }\n let tag = (acc + s) & ((1n << 128n) - 1n);\n const out = new Uint8Array(TAG_LEN);\n for (let i = 0; i < TAG_LEN; i += 1) {\n out[i] = Number(tag & 0xffn);\n tag >>= 8n;\n }\n return out;\n}\n\nfunction pad16(length: number): Uint8Array {\n return new Uint8Array((16 - (length % 16)) % 16);\n}\n\nfunction u64le(value: number): Uint8Array {\n const out = new Uint8Array(8);\n new DataView(out.buffer).setBigUint64(0, BigInt(value), true);\n return out;\n}\n\nfunction macData(aad: Uint8Array, ciphertext: Uint8Array): Uint8Array {\n const parts = [aad, pad16(aad.length), ciphertext, pad16(ciphertext.length), u64le(aad.length), u64le(ciphertext.length)];\n const out = new Uint8Array(parts.reduce((n, p) => n + 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\nfunction check(key: Uint8Array, nonce: Uint8Array): void {\n if (key.length !== KEY_LEN) throw new Error('ChaCha20-Poly1305 needs a 32-byte key');\n if (nonce.length !== NONCE_LEN) throw new Error('ChaCha20-Poly1305 needs a 12-byte nonce');\n}\n\n/** Seal: the ciphertext followed by its 16-byte tag (RFC 8439 \u00A72.8). */\nexport function chacha20Poly1305Seal(\n key: Uint8Array,\n nonce: Uint8Array,\n plaintext: Uint8Array,\n aad: Uint8Array = new Uint8Array(0),\n): Uint8Array {\n check(key, nonce);\n const otk = chacha20Block(key, 0, nonce).subarray(0, 32);\n const ciphertext = chacha20(key, 1, nonce, plaintext);\n const tag = poly1305(otk, macData(aad, ciphertext));\n const out = new Uint8Array(ciphertext.length + TAG_LEN);\n out.set(ciphertext);\n out.set(tag, ciphertext.length);\n return out;\n}\n\n/** Open what {@link chacha20Poly1305Seal} made; throws if it was altered. */\nexport function chacha20Poly1305Open(\n key: Uint8Array,\n nonce: Uint8Array,\n sealed: Uint8Array,\n aad: Uint8Array = new Uint8Array(0),\n): Uint8Array {\n check(key, nonce);\n if (sealed.length < TAG_LEN) throw new Error('The sealed message is shorter than its tag');\n const ciphertext = sealed.subarray(0, sealed.length - TAG_LEN);\n const otk = chacha20Block(key, 0, nonce).subarray(0, 32);\n const expected = poly1305(otk, macData(aad, ciphertext));\n let diff = 0;\n for (let i = 0; i < TAG_LEN; i += 1) diff |= expected[i] ^ sealed[ciphertext.length + i];\n if (diff !== 0) throw new Error('The sealed message did not authenticate');\n return chacha20(key, 1, nonce, ciphertext);\n}\n", "/**\n * RFC 9180 HPKE, the one suite and mode mero-agent-gate takes: Auth mode,\n * DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20-Poly1305, single-shot\n * (one message per context, sequence number 0). Auth mode proves the sender:\n * the gate opens a bundle only under the X25519 key it names, so nobody can\n * seal in an owner's name.\n *\n * X25519 and HMAC are WebCrypto; ChaCha20-Poly1305 is ./chacha20poly1305.\n * The tests open what mero-agent-gate (Rust, the `hpke` crate) sealed, and the\n * gate opens what this seals.\n */\n\nimport { concat } from '../crypto/internal.js';\nimport { dh, x25519KeyPair } from '../sealed/noise.js';\nimport { chacha20Poly1305Open, chacha20Poly1305Seal } from './chacha20poly1305.js';\n\nconst KEM_ID = 0x0020; // DHKEM(X25519, HKDF-SHA256)\nconst KDF_ID = 0x0001; // HKDF-SHA256\nconst AEAD_ID = 0x0003; // ChaCha20-Poly1305\nconst MODE_AUTH = 0x02;\nconst N_SECRET = 32;\nconst N_KEY = 32;\nconst N_NONCE = 12;\n\nconst utf8 = (s: string) => new TextEncoder().encode(s);\nconst i2osp2 = (n: number) => new Uint8Array([(n >> 8) & 0xff, n & 0xff]);\n\nconst KEM_SUITE = concat(utf8('KEM'), i2osp2(KEM_ID));\nconst HPKE_SUITE = concat(utf8('HPKE'), i2osp2(KEM_ID), i2osp2(KDF_ID), i2osp2(AEAD_ID));\n\nasync function hmac(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {\n // An empty salt is HashLen zeros (RFC 5869); WebCrypto refuses a zero-length HMAC key.\n const raw = key.length === 0 ? new Uint8Array(32) : key;\n const k = await crypto.subtle.importKey('raw', raw, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n return new Uint8Array(await crypto.subtle.sign('HMAC', k, data));\n}\n\nasync function expand(prk: Uint8Array, info: Uint8Array, length: number): Promise<Uint8Array> {\n const out = new Uint8Array(length);\n let previous = new Uint8Array(0);\n for (let i = 1, offset = 0; offset < length; i += 1) {\n previous = await hmac(prk, concat(previous, info, new Uint8Array([i])));\n out.set(previous.subarray(0, Math.min(previous.length, length - offset)), offset);\n offset += previous.length;\n }\n return out;\n}\n\nfunction labeledExtract(suite: Uint8Array, salt: Uint8Array, label: string, ikm: Uint8Array): Promise<Uint8Array> {\n return hmac(salt, concat(utf8('HPKE-v1'), suite, utf8(label), ikm));\n}\n\nfunction labeledExpand(suite: Uint8Array, prk: Uint8Array, label: string, info: Uint8Array, length: number) {\n return expand(prk, concat(i2osp2(length), utf8('HPKE-v1'), suite, utf8(label), info), length);\n}\n\nasync function extractAndExpand(dhValue: Uint8Array, kemContext: Uint8Array): Promise<Uint8Array> {\n const prk = await labeledExtract(KEM_SUITE, new Uint8Array(0), 'eae_prk', dhValue);\n return labeledExpand(KEM_SUITE, prk, 'shared_secret', kemContext, N_SECRET);\n}\n\nasync function keySchedule(sharedSecret: Uint8Array, info: Uint8Array): Promise<{ key: Uint8Array; nonce: Uint8Array }> {\n const empty = new Uint8Array(0);\n const pskIdHash = await labeledExtract(HPKE_SUITE, empty, 'psk_id_hash', empty);\n const infoHash = await labeledExtract(HPKE_SUITE, empty, 'info_hash', info);\n const context = concat(new Uint8Array([MODE_AUTH]), pskIdHash, infoHash);\n const secret = await labeledExtract(HPKE_SUITE, sharedSecret, 'secret', empty);\n return {\n key: await labeledExpand(HPKE_SUITE, secret, 'key', context, N_KEY),\n nonce: await labeledExpand(HPKE_SUITE, secret, 'base_nonce', context, N_NONCE),\n };\n}\n\nexport interface HpkeSealed {\n /** The encapsulated key: the sender's ephemeral X25519 public key. */\n enc: Uint8Array;\n ciphertext: Uint8Array;\n}\n\n/**\n * Seal `plaintext` to `recipientPublic` in Auth mode as the holder of\n * `senderSecret` (32 raw X25519 bytes). `ephemeralSecret` is for tests.\n */\nexport async function hpkeSealAuth(\n recipientPublic: Uint8Array,\n senderSecret: Uint8Array,\n info: Uint8Array,\n plaintext: Uint8Array,\n aad: Uint8Array = new Uint8Array(0),\n ephemeralSecret?: Uint8Array,\n): Promise<HpkeSealed> {\n if (recipientPublic.length !== 32) throw new Error('The recipient key is not 32 bytes of X25519');\n const ephemeral = await x25519KeyPair(ephemeralSecret);\n const sender = await x25519KeyPair(senderSecret);\n const dhValue = concat(await dh(ephemeral.privateKey, recipientPublic), await dh(sender.privateKey, recipientPublic));\n const shared = await extractAndExpand(dhValue, concat(ephemeral.publicKey, recipientPublic, sender.publicKey));\n const { key, nonce } = await keySchedule(shared, info);\n return { enc: ephemeral.publicKey, ciphertext: chacha20Poly1305Seal(key, nonce, plaintext, aad) };\n}\n\n/** Open what {@link hpkeSealAuth} (or the gate's own sealer) made, as the recipient. */\nexport async function hpkeOpenAuth(\n recipientSecret: Uint8Array,\n senderPublic: Uint8Array,\n info: Uint8Array,\n sealed: HpkeSealed,\n aad: Uint8Array = new Uint8Array(0),\n): Promise<Uint8Array> {\n const recipient = await x25519KeyPair(recipientSecret);\n const dhValue = concat(await dh(recipient.privateKey, sealed.enc), await dh(recipient.privateKey, senderPublic));\n const shared = await extractAndExpand(dhValue, concat(sealed.enc, recipient.publicKey, senderPublic));\n const { key, nonce } = await keySchedule(shared, info);\n return chacha20Poly1305Open(key, nonce, sealed.ciphertext, aad);\n}\n", "/**\n * A client for mero-agent-gate, the gate in a private agent TD (mero-tee,\n * `mero-agent-gate/`): attest an agent, claim it with your key, give it its\n * secrets sealed to the TD, and release it. It runs where the owner is (a\n * browser, a CLI), so whoever carries the requests, mdma included, sees only\n * quotes and ciphertext.\n *\n * One agent TD hosts several owners' agents, each named by an agent id. For\n * an agent the gate's quote binds, in its report data:\n *\n * `nonce \u2016 SHA-256(\"mero-agent-gate/attest/v3\" \u2016 provisioning_pub \u2016 len(id) \u2016 id \u2016 signing_pub \u2016 owner_pub)`\n *\n * (signing and owner keys 32 zero bytes while unclaimed). {@link attestAgent}\n * checks that and the quote itself before returning anything; every function\n * that sends refuses an agent whose quote names another owner.\n *\n * ```ts\n * import { verify as dcapVerify, getCollateral } from '@phala/dcap-qvl';\n *\n * const policy = await verifySignedAgentPolicy(policyJson, bundleJson, { profile: 'locked-read-only' });\n * const verifier = agentQuoteVerifier(policy, { dcapVerify, fetchCollateral: (q) => getCollateral(PCCS, q) });\n * const owner = await generateOwnerKey(); // keep owner.secret: it is the only key that can change the agent\n * const agent = await attestAgent({ gateUrl, agentId: 'a-1f2e', verifier });\n * await provisionAgent({ gateUrl, agent, ownerSecret: owner.secret, verifier, secrets: { NEAR_AI_API_KEY: key } });\n * ```\n */\n\nimport { concat, hex } from '../crypto/internal.js';\nimport { x25519KeyPair } from '../sealed/noise.js';\nimport type { VerifyTransportQuote } from '../sealed/sealed.js';\nimport { hpkeSealAuth } from './hpke.js';\n\nexport const AGENT_ATTEST_DOMAIN = 'mero-agent-gate/attest/v3';\nexport const AGENT_PROVISION_INFO_DOMAIN = 'mero-agent-gate/provision/v2';\n\nconst AGENT_ID = /^[a-z0-9][a-z0-9-]{0,62}$/;\nconst SECRET_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;\nconst MAX_SECRETS = 64;\nconst MAX_SECRET_LEN = 64 * 1024;\n\n/** A gate's refusal, with its `error` code (`not_the_owner`, `no_free_slot`, \u2026) when it gave one. */\nexport class AgentGateError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n readonly code?: string,\n ) {\n super(message);\n this.name = 'AgentGateError';\n }\n}\n\n/** An agent's keys, once its quote passed {@link attestAgent}'s checks. */\nexport interface VerifiedAgent {\n agentId: string;\n /** Base64; secrets are sealed to it. Valid until the gate restarts. */\n provisioningPublicKey: string;\n /** Base64 Ed25519 key the agent signs with; absent while unclaimed. */\n signingPublicKey?: string;\n /** Base64 X25519 key of the owner that claimed it; absent while unclaimed. */\n ownerPublicKey?: string;\n}\n\nexport interface OwnerKey {\n /** 32 raw X25519 bytes. The only key that can provision or release the agent: keep it. */\n secret: Uint8Array;\n /** Base64 of the public half: what the gate's quote names as owner. */\n publicKey: string;\n}\n\ntype Fetch = typeof fetch;\n\nexport function validateAgentId(agentId: string): void {\n if (!AGENT_ID.test(agentId)) {\n throw new Error(`Agent id ${JSON.stringify(agentId)} must match [a-z0-9][a-z0-9-]{0,62}`);\n }\n}\n\nfunction utf8(value: string): Uint8Array {\n return new TextEncoder().encode(value);\n}\n\nfunction lengthPrefixed(agentId: string): Uint8Array {\n const id = utf8(agentId);\n return concat(new Uint8Array([id.length]), id);\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nfunction fromBase64(value: string, label: string, length?: number): Uint8Array {\n let bytes: Uint8Array;\n try {\n bytes = Uint8Array.from(atob(value.trim()), (c) => c.charCodeAt(0));\n } catch {\n throw new Error(`${label} is not base64`);\n }\n if (length !== undefined && bytes.length !== length) throw new Error(`${label} is not ${length} bytes`);\n return bytes;\n}\n\n/** The 32 bytes after the nonce in a gate's quote for `agentId` (empty: the TD alone). */\nexport async function agentKeyBinding(\n provisioningPublic: Uint8Array,\n agentId: string,\n signingPublic?: Uint8Array,\n ownerPublic?: Uint8Array,\n): Promise<Uint8Array> {\n const zero = new Uint8Array(32);\n const data = concat(\n utf8(AGENT_ATTEST_DOMAIN),\n provisioningPublic,\n lengthPrefixed(agentId),\n signingPublic ?? zero,\n ownerPublic ?? zero,\n );\n return new Uint8Array(await crypto.subtle.digest('SHA-256', data));\n}\n\n/** HPKE `info` for a message to `agentId` on the gate whose provisioning key is `recipientPublic`. */\nexport function provisionInfo(recipientPublic: Uint8Array, agentId: string): Uint8Array {\n return concat(utf8(AGENT_PROVISION_INFO_DOMAIN), recipientPublic, lengthPrefixed(agentId));\n}\n\n/** A fresh owner key, made here; it never needs to leave the owner. */\nexport async function generateOwnerKey(): Promise<OwnerKey> {\n const secret = crypto.getRandomValues(new Uint8Array(32));\n return { secret, publicKey: await ownerPublicKey(secret) };\n}\n\n/** The base64 public half of an owner's X25519 secret. */\nexport async function ownerPublicKey(secret: Uint8Array): Promise<string> {\n if (secret.length !== 32) throw new Error('An owner key is 32 bytes');\n return toBase64((await x25519KeyPair(secret)).publicKey);\n}\n\nfunction url(gateUrl: string, path: string): string {\n return `${gateUrl.replace(/\\/+$/, '')}${path}`;\n}\n\nasync function postJson(fetchImpl: Fetch, target: string, body: unknown): Promise<unknown> {\n const response = await fetchImpl(target, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n });\n const text = await response.text();\n let parsed: unknown = undefined;\n try {\n parsed = text ? JSON.parse(text) : undefined;\n } catch {\n // Not JSON: reported below with the status.\n }\n if (!response.ok) {\n const error = parsed as { error?: string; details?: string } | undefined;\n throw new AgentGateError(\n `The gate answered ${response.status}${error?.error ? ` ${error.error}` : ''}: ${error?.details ?? text.slice(0, 200)}`,\n response.status,\n error?.error,\n );\n }\n return parsed;\n}\n\nexport interface AttestAgentOptions {\n /** The gate's base URL, or a relay of it (mdma's): only verified quotes are trusted. */\n gateUrl: string;\n /** The agent to attest; omit for the TD alone (no keys, nothing to send to). */\n agentId?: string;\n /** Checks the quote's signature, TCB, image and report data: {@link agentQuoteVerifier}. */\n verifier: VerifyTransportQuote;\n fetch?: Fetch;\n}\n\ninterface AttestResponseBody {\n quoteB64: string;\n provisioningPublicKeyB64: string;\n agentId?: string;\n signingPublicKeyB64?: string;\n ownerPublicKeyB64?: string;\n}\n\n/**\n * Ask the gate for a quote for `agentId` over a fresh nonce and verify it:\n * a genuine quote from a measured agent image, for this nonce, committing to\n * the agent id asked about and to the keys the gate names. Returns those\n * keys only once every check has passed.\n */\nexport async function attestAgent(options: AttestAgentOptions): Promise<VerifiedAgent> {\n const agentId = options.agentId ?? '';\n if (agentId) validateAgentId(agentId);\n const nonce = crypto.getRandomValues(new Uint8Array(32));\n const body = (await postJson(options.fetch ?? fetch, url(options.gateUrl, '/attest'), {\n nonceB64: toBase64(nonce),\n ...(agentId ? { agentId } : {}),\n })) as AttestResponseBody;\n if ((body?.agentId ?? '') !== agentId) {\n throw new Error(`Asked about agent ${JSON.stringify(agentId)}, the gate answered for ${JSON.stringify(body?.agentId)}`);\n }\n const provisioning = fromBase64(body.provisioningPublicKeyB64 ?? '', 'provisioningPublicKeyB64', 32);\n const signing = body.signingPublicKeyB64 ? fromBase64(body.signingPublicKeyB64, 'signingPublicKeyB64', 32) : undefined;\n const owner = body.ownerPublicKeyB64 ? fromBase64(body.ownerPublicKeyB64, 'ownerPublicKeyB64', 32) : undefined;\n if (!signing !== !owner) {\n throw new Error('A claimed agent has both a signing key and an owner; the gate named one');\n }\n // The id asked about, not the one answered: a quote for another agent fails here.\n const binding = await agentKeyBinding(provisioning, agentId, signing, owner);\n await options.verifier({ quoteB64: body.quoteB64, nonce: hex(nonce), reportDataSuffix: hex(binding) });\n return {\n agentId,\n provisioningPublicKey: toBase64(provisioning),\n ...(signing ? { signingPublicKey: toBase64(signing) } : {}),\n ...(owner ? { ownerPublicKey: toBase64(owner) } : {}),\n };\n}\n\n/** The owner key `ownerSecret` may act on `agent`: it is unclaimed, or claimed by that key. */\nexport async function checkOwner(agent: VerifiedAgent, ownerSecret: Uint8Array): Promise<string> {\n const mine = await ownerPublicKey(ownerSecret);\n if (agent.ownerPublicKey && agent.ownerPublicKey !== mine) {\n throw new AgentGateError(\n `This agent is claimed by another key (${agent.ownerPublicKey}); it is not yours. Send it nothing and do not authorize its signing key`,\n undefined,\n 'not_yours',\n );\n }\n return mine;\n}\n\nfunction validateSecrets(secrets: Record<string, string>): void {\n const names = Object.keys(secrets);\n if (names.length === 0) throw new Error('There are no secrets to provision');\n if (names.length > MAX_SECRETS) throw new Error(`At most ${MAX_SECRETS} secrets at once`);\n for (const name of names) {\n if (!SECRET_NAME.test(name)) throw new Error(`Secret name ${JSON.stringify(name)} must match [A-Za-z0-9][A-Za-z0-9_.-]{0,63}`);\n if (typeof secrets[name] !== 'string') throw new Error(`Secret ${name} is not a string`);\n if (utf8(secrets[name]).length > MAX_SECRET_LEN) throw new Error(`Secret ${name} is over ${MAX_SECRET_LEN} bytes`);\n }\n}\n\nasync function sendSealed(\n fetchImpl: Fetch,\n gateUrl: string,\n path: '/provision' | '/release',\n agent: VerifiedAgent,\n ownerSecret: Uint8Array,\n message: unknown,\n): Promise<unknown> {\n if (!agent.agentId) throw new Error('This quote names no agent; attest with the agent id');\n const mine = await checkOwner(agent, ownerSecret);\n const recipient = fromBase64(agent.provisioningPublicKey, 'provisioningPublicKey', 32);\n const sealed = await hpkeSealAuth(\n recipient,\n ownerSecret,\n provisionInfo(recipient, agent.agentId),\n utf8(JSON.stringify(message)),\n );\n return postJson(fetchImpl, url(gateUrl, path), {\n agentId: agent.agentId,\n provisioningPublicKeyB64: agent.provisioningPublicKey,\n senderPublicKeyB64: mine,\n encappedKeyB64: toBase64(sealed.enc),\n ciphertextB64: toBase64(sealed.ciphertext),\n });\n}\n\nexport interface ProvisionAgentOptions {\n gateUrl: string;\n /** What {@link attestAgent} returned for this agent, just now. */\n agent: VerifiedAgent;\n ownerSecret: Uint8Array;\n /** Name to value; a name replaces what was there, others stay. */\n secrets: Record<string, string>;\n /** The verifier `agent` was attested with: the claim is checked by a fresh quote. */\n verifier: VerifyTransportQuote;\n fetch?: Fetch;\n}\n\nexport interface ProvisionedAgent extends Required<VerifiedAgent> {\n written: string[];\n /** Whether this claimed the agent for your key. */\n claimed: boolean;\n}\n\n/**\n * Seal `secrets` to the agent as its owner and send them. The first bundle for\n * an unclaimed agent claims it for `ownerSecret`'s key. The gate's answer is\n * not taken as proof: a fresh quote must name your key as owner, and the\n * agent's signing key must not have changed.\n */\nexport async function provisionAgent(options: ProvisionAgentOptions): Promise<ProvisionedAgent> {\n validateSecrets(options.secrets);\n const fetchImpl = options.fetch ?? fetch;\n const answer = (await sendSealed(fetchImpl, options.gateUrl, '/provision', options.agent, options.ownerSecret, {\n secrets: options.secrets,\n })) as { written?: string[]; claimed?: boolean };\n const after = await attestAgent({ gateUrl: options.gateUrl, agentId: options.agent.agentId, verifier: options.verifier, fetch: fetchImpl });\n const mine = await ownerPublicKey(options.ownerSecret);\n if (after.ownerPublicKey !== mine || !after.signingPublicKey) {\n throw new AgentGateError('The gate accepted the secrets, but its quote does not name your key as owner');\n }\n if (options.agent.signingPublicKey && options.agent.signingPublicKey !== after.signingPublicKey) {\n throw new AgentGateError(\"The agent's signing key changed while provisioning\");\n }\n return {\n agentId: after.agentId,\n provisioningPublicKey: after.provisioningPublicKey,\n signingPublicKey: after.signingPublicKey,\n ownerPublicKey: mine,\n written: answer?.written ?? [],\n claimed: answer?.claimed === true,\n };\n}\n\nexport interface ReleaseAgentOptions {\n gateUrl: string;\n agent: VerifiedAgent;\n ownerSecret: Uint8Array;\n verifier: VerifyTransportQuote;\n fetch?: Fetch;\n}\n\n/**\n * Release the agent as its owner: the gate stops it and erases its claim,\n * keys, secrets and state. Checked by a fresh quote that names no owner.\n */\nexport async function releaseAgent(options: ReleaseAgentOptions): Promise<void> {\n if (!options.agent.ownerPublicKey) throw new Error('This agent is not claimed; there is nothing to release');\n const fetchImpl = options.fetch ?? fetch;\n await sendSealed(fetchImpl, options.gateUrl, '/release', options.agent, options.ownerSecret, { release: true });\n const after = await attestAgent({ gateUrl: options.gateUrl, agentId: options.agent.agentId, verifier: options.verifier, fetch: fetchImpl });\n if (after.ownerPublicKey) {\n throw new AgentGateError('The gate says it released the agent, but its quote still names an owner');\n }\n}\n", "/**\n * Which agent images to trust: a mero-kms release's signed agent allowlist,\n * `kms-agent-attestation-policy.<profile>.json`, and a quote verifier built\n * from it.\n *\n * The KMS release workflow measures the release's agent image and signs its\n * allowlist with cosign keyless, beside the rest of the release. The allowlist\n * can therefore come from anywhere (a release asset, mdma's mirror, a file in\n * the app): {@link verifySignedAgentPolicy} checks the signature here, against\n * the Sigstore trust root embedded in this package, and refuses anything else.\n */\n\nimport { verifyCosignBundle, type SignerIdentity } from '../sealed/sigstore.js';\nimport {\n PRODUCTION_PROFILE,\n createQuoteVerifier,\n type DcapCollateral,\n type DcapVerify,\n type QuoteVerifier,\n} from '../sealed/verify.js';\n\n/** The workflow that signs every mero-kms release, agent allowlists included. */\nexport const KMS_RELEASE_SIGNER: Readonly<SignerIdentity> = Object.freeze({\n identity: 'https://github.com/calimero-network/mero-tee/.github/workflows/release-kms.yaml@refs/heads/master',\n issuer: 'https://token.actions.githubusercontent.com',\n});\n\n/** An agent allowlist, as the KMS release publishes it. Every list must be non-empty. */\nexport interface AgentPolicy {\n schema_version?: number;\n role?: string;\n profile?: string;\n /** The mero-kms release it belongs to. */\n version?: string;\n allowed_tcb_statuses: string[];\n allowed_mrtd: string[];\n allowed_rtmr0: string[];\n allowed_rtmr1: string[];\n allowed_rtmr2: string[];\n allowed_rtmr3: string[];\n}\n\nconst LISTS = [\n 'allowed_tcb_statuses',\n 'allowed_mrtd',\n 'allowed_rtmr0',\n 'allowed_rtmr1',\n 'allowed_rtmr2',\n 'allowed_rtmr3',\n] as const;\n\nexport interface VerifySignedAgentPolicyOptions {\n /** Require this profile; defaults to `locked-read-only`, the only one whose host cannot reach in. */\n profile?: string;\n /** Require the file's `version` to be this mero-kms release. */\n expectedVersion?: string;\n /** The certificate identity required. Defaults to {@link KMS_RELEASE_SIGNER}'s. */\n identity?: string;\n /** The OIDC issuer required. Defaults to {@link KMS_RELEASE_SIGNER}'s. */\n issuer?: string;\n /**\n * The image role the allowlist must be for: `agent` (the default), or\n * `inference`, the release's `kms-inference-attestation-policy.<profile>.json`\n * for its private inference image. Both have the same shape and signer.\n */\n role?: 'agent' | 'inference';\n}\n\n/**\n * Verify an agent allowlist against its cosign bundle, as `cosign verify-blob`\n * would, and return it parsed. Rejects unless it was signed by the KMS release\n * workflow, it is an allowlist for `options.role` (default `agent`) and the profile asked\n * for, every list in it is non-empty, and `expectedVersion`, when given, is its\n * `version`.\n */\nexport async function verifySignedAgentPolicy(\n policy: string | Uint8Array,\n bundle: string | object,\n options: VerifySignedAgentPolicyOptions = {},\n): Promise<AgentPolicy> {\n const body = typeof policy === 'string' ? new TextEncoder().encode(policy) : policy;\n await verifyCosignBundle(body, bundle, {\n identity: options.identity ?? KMS_RELEASE_SIGNER.identity,\n issuer: options.issuer ?? KMS_RELEASE_SIGNER.issuer,\n });\n let parsed: AgentPolicy;\n try {\n parsed = JSON.parse(new TextDecoder().decode(body));\n } catch {\n throw new Error('The signed agent policy is not JSON');\n }\n const role = options.role ?? 'agent';\n if (parsed?.role !== role) {\n throw new Error(`The signed file is a ${JSON.stringify(parsed?.role)} policy, not an ${role} one`);\n }\n const profile = options.profile ?? PRODUCTION_PROFILE;\n if (parsed.profile !== profile) {\n throw new Error(`The signed agent policy is for the ${JSON.stringify(parsed.profile)} profile, not ${profile}`);\n }\n if (options.expectedVersion !== undefined && parsed.version !== options.expectedVersion) {\n throw new Error(`The signed agent policy is release ${JSON.stringify(parsed.version)}, not ${options.expectedVersion}`);\n }\n checkLists(parsed);\n return parsed;\n}\n\nfunction checkLists(policy: AgentPolicy): void {\n for (const list of LISTS) {\n if (!Array.isArray(policy?.[list]) || policy[list].length === 0) {\n // As the gate's own verifier: an empty list accepts nothing.\n throw new Error(`The agent policy's ${list} is empty, so no agent would be accepted`);\n }\n }\n}\n\n/** DCAP's spelling of each TCB status; the policy may use any case. */\nconst TCB_STATUSES = [\n 'UpToDate',\n 'SWHardeningNeeded',\n 'ConfigurationNeeded',\n 'ConfigurationAndSWHardeningNeeded',\n 'OutOfDate',\n 'OutOfDateConfigurationNeeded',\n];\n\nfunction tcbStatus(value: string): string {\n const found = TCB_STATUSES.find((status) => status.toLowerCase() === value.trim().toLowerCase());\n if (!found) throw new Error(`The agent policy allows an unknown TCB status ${JSON.stringify(value)}`);\n return found;\n}\n\nconst register = (value: string) => value.trim().replace(/^0x/i, '');\n\nexport interface AgentQuoteVerifierOptions {\n /** `verify` from `@phala/dcap-qvl`, or anything that verifies a quote the same way. */\n dcapVerify: DcapVerify;\n /**\n * The gate sends no collateral: fetch it, e.g.\n * `(quote) => getCollateral(PHALA_PCCS_URL, quote)` from `@phala/dcap-qvl`.\n */\n fetchCollateral: (quote: Uint8Array) => Promise<DcapCollateral>;\n /** The current time in milliseconds; defaults to `Date.now`. For tests. */\n now?: () => number;\n}\n\n/**\n * A verifier for {@link attestAgent} that accepts a quote only from an agent\n * image in `policy`: its signature and collateral verify, its TCB status is\n * one the policy allows (never `Revoked`), it is not a debug TD, and each of\n * MRTD and RTMR0-3 is in the policy's list. Mock quotes never pass.\n */\nexport function agentQuoteVerifier(policy: AgentPolicy, options: AgentQuoteVerifierOptions): QuoteVerifier {\n checkLists(policy);\n return createQuoteVerifier({\n dcapVerify: options.dcapVerify,\n fetchCollateral: options.fetchCollateral,\n now: options.now,\n allowedTcbStatuses: policy.allowed_tcb_statuses.map(tcbStatus),\n allowedMrtd: policy.allowed_mrtd.map(register),\n allowedRtmr0: policy.allowed_rtmr0.map(register),\n allowedRtmr1: policy.allowed_rtmr1.map(register),\n allowedRtmr2: policy.allowed_rtmr2.map(register),\n allowedRtmr3: policy.allowed_rtmr3.map(register),\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["nonce", "url", "open", "SEQUENCE", "utf8", "register", "nonce", "fromBase64", "register", "url", "equal", "fetch", "nonce", "url", "url", "url", "url", "nonce", "TAG_LEN", "nonce", "utf8", "nonce", "utf8", "fromBase64", "nonce", "TCB_STATUSES", "tcbStatus"]
7
7
  }