@calimero-network/mero-js 27.2.0 → 27.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cloud-v2/approvals.d.ts +27 -0
- package/dist/cloud-v2/approvals.js +18 -0
- package/dist/cloud-v2/client.d.ts +10 -5
- package/dist/cloud-v2/client.js +30 -10
- package/dist/cloud-v2/index.d.ts +2 -2
- package/dist/cloud-v2/index.js +1 -1
- package/dist/index.browser.mjs +3 -3
- package/dist/index.browser.mjs.map +3 -3
- package/dist/index.cjs +38 -8
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +38 -8
- package/dist/index.mjs.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ Pinned measurements go through `policy.verifyQuote` (`createQuoteVerifier`).
|
|
|
75
75
|
- **Blobs and presence**: `uploadBlob`, `downloadBlob`, `listBlobs`, `blobInfo`, `deleteBlob`; `publishPresence`, `presence`, `presenceStream`.
|
|
76
76
|
- **Organizations**: `createOrg`, `getOrg`, `deleteOrg`, `setOrgMetadata`, `setMember`, `removeMember`, `setMemberMetadata`, `setCapabilities` (`ORG_CAPABILITIES`), teams, `invite`, `redeemInvite`.
|
|
77
77
|
- **Owner decisions** (passkey approval, never from an app's frontend): `upgradeOrg`, `upgradeRun`, `retryUpgradeRun`, `approveRelease`, `approveOutbound`, `bindPublisher`, `upgradePublished`.
|
|
78
|
-
- **Approvals from an app**: `appsReport`, `releaseRules`, `pendingApprovals`, then `requestConsent` / `openConsentPage` to send the user to the node's consent page, and `consentResult`. See [Ask your users to approve node images and app upgrades](https://calimero-network.github.io/mero-js/guides/user-approvals/).
|
|
78
|
+
- **Approvals from an app**: `appsReport`, `releaseRules`, `pendingApprovals`, then `requestConsent` / `openConsentPage` to send the user to the node's consent page, and `consentResult`. Show the answer's `code` to the user before sending them to `url` (`openConsentPage`'s `confirm` hook); they should see the same code on the page (`confirmationCode(requestId)` checks it). See [Ask your users to approve node images and app upgrades](https://calimero-network.github.io/mero-js/guides/user-approvals/).
|
|
79
79
|
- **Operator** (ops token): `opsApps`, `opsOrgs`, `setReleaseDeadline`, `liftReleaseDeadline`.
|
|
80
80
|
- **Any route**: `get`, `post`, `put`, `delete`; `postConfirmed` and `deleteConfirmed` answer a `412 CONFIRM_REQUIRED` with a passkey.
|
|
81
81
|
|
|
@@ -234,7 +234,34 @@ export interface ConsentStarted {
|
|
|
234
234
|
url: string;
|
|
235
235
|
/** Unix seconds; a request lives 10 minutes. */
|
|
236
236
|
expiresAt: number;
|
|
237
|
+
/**
|
|
238
|
+
* The confirmation code the consent page shows, `XXX-XXX`
|
|
239
|
+
* ({@link confirmationCode} of `requestId`). Show it to the person before
|
|
240
|
+
* sending them to `url`: the page they land on should show the same code,
|
|
241
|
+
* which tells them it is the page their request opened. Not a secret.
|
|
242
|
+
* Nodes older than the code leave it out.
|
|
243
|
+
*/
|
|
244
|
+
code?: string;
|
|
237
245
|
}
|
|
246
|
+
/** How {@link CalimeroClient.openConsentPage} sends the person to the page. */
|
|
247
|
+
export interface OpenConsentOptions {
|
|
248
|
+
/** Sends the browser to the page's `url`; by default `window.location.assign`. */
|
|
249
|
+
navigate?: (url: string) => void;
|
|
250
|
+
/**
|
|
251
|
+
* Runs after the node answers and before navigating, with the answer: show
|
|
252
|
+
* the person `started.code` here so they can check the page shows the same.
|
|
253
|
+
* Answer `false` and the page is not opened (the request stays on the node
|
|
254
|
+
* until it expires).
|
|
255
|
+
*/
|
|
256
|
+
confirm?: (started: ConsentStarted) => boolean | Promise<boolean>;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The confirmation code the node's consent page shows for `requestId`: the
|
|
260
|
+
* first 30 bits of SHA-256 of its UTF-8 bytes, big-endian, as six Crockford
|
|
261
|
+
* base32 characters written `XXX-XXX` (core's consent page). Compare it with
|
|
262
|
+
* {@link ConsentStarted.code} to check the node's answer.
|
|
263
|
+
*/
|
|
264
|
+
export declare function confirmationCode(requestId: string): Promise<string>;
|
|
238
265
|
export type ConsentStatus = 'pending' | 'approved' | 'declined';
|
|
239
266
|
/** `GET /consent/{id}/result`. */
|
|
240
267
|
export interface ConsentResult {
|
|
@@ -74,6 +74,24 @@ export function publisherBindingMessage(cluster, org, signerId, generation) {
|
|
|
74
74
|
export function publisherBindingBytes(cluster, org, signerId, generation) {
|
|
75
75
|
return new TextEncoder().encode(publisherBindingMessage(cluster, org, signerId, generation));
|
|
76
76
|
}
|
|
77
|
+
const CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
78
|
+
/**
|
|
79
|
+
* The confirmation code the node's consent page shows for `requestId`: the
|
|
80
|
+
* first 30 bits of SHA-256 of its UTF-8 bytes, big-endian, as six Crockford
|
|
81
|
+
* base32 characters written `XXX-XXX` (core's consent page). Compare it with
|
|
82
|
+
* {@link ConsentStarted.code} to check the node's answer.
|
|
83
|
+
*/
|
|
84
|
+
export async function confirmationCode(requestId) {
|
|
85
|
+
const h = new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(requestId)));
|
|
86
|
+
const word = ((h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3]) >>> 0;
|
|
87
|
+
let code = '';
|
|
88
|
+
for (let i = 0; i < 6; i++) {
|
|
89
|
+
if (i === 3)
|
|
90
|
+
code += '-';
|
|
91
|
+
code += CROCKFORD[(word >>> (27 - 5 * i)) & 31];
|
|
92
|
+
}
|
|
93
|
+
return code;
|
|
94
|
+
}
|
|
77
95
|
/**
|
|
78
96
|
* What the consent page put on `returnTo` when it sent the person back, or
|
|
79
97
|
* `null` when `href` carries none. A hint only (anyone can type a URL): confirm
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { type AttestationDoc, type CloudPolicy } from './attestation.js';
|
|
13
13
|
import { type PasskeyProvider } from './passkey.js';
|
|
14
|
-
import { type AppsReport, type ConsentRequest, type ConsentResult, type ConsentStarted, type OpsAppsReport, type OpsOrgsReport, type PageOptions, type PendingApprovals, type PublisherBindingInfo, type PublisherProof, type ReleaseRules } from './approvals.js';
|
|
14
|
+
import { type AppsReport, type ConsentRequest, type ConsentResult, type ConsentStarted, type OpenConsentOptions, type OpsAppsReport, type OpsOrgsReport, type PageOptions, type PendingApprovals, type PublisherBindingInfo, type PublisherProof, type ReleaseRules } from './approvals.js';
|
|
15
15
|
export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
16
16
|
export type { Committed } from './errors.js';
|
|
17
17
|
export interface CalimeroSession {
|
|
@@ -505,11 +505,16 @@ export declare class CalimeroClient {
|
|
|
505
505
|
requestConsent(request: ConsentRequest): Promise<ConsentStarted>;
|
|
506
506
|
/**
|
|
507
507
|
* {@link requestConsent}, then send the browser to the consent page
|
|
508
|
-
* (`navigate`, by default `window.location.assign`).
|
|
509
|
-
*
|
|
510
|
-
*
|
|
508
|
+
* (`navigate`, by default `window.location.assign`). Pass `navigate` itself
|
|
509
|
+
* or {@link OpenConsentOptions}, whose `confirm` runs first with the node's
|
|
510
|
+
* answer so the app can show the person its `code`; when it answers `false`
|
|
511
|
+
* the page is not opened. When the node sends a `code` that is not
|
|
512
|
+
* {@link confirmationCode} of `requestId`, it throws `CalimeroError`
|
|
513
|
+
* (`CONSENT_CODE_MISMATCH`) and does not navigate. Answers the request
|
|
514
|
+
* once `navigate` returns (or `confirm` declines): with a popup
|
|
515
|
+
* (`url => window.open(url)`), poll it with {@link waitForConsent}.
|
|
511
516
|
*/
|
|
512
|
-
openConsentPage(request: ConsentRequest,
|
|
517
|
+
openConsentPage(request: ConsentRequest, navigateOrOptions?: ((url: string) => void) | OpenConsentOptions): Promise<ConsentStarted>;
|
|
513
518
|
/** The decision on a consent request (any node answers, for the account that asked). */
|
|
514
519
|
consentResult(requestId: string): Promise<ConsentResult>;
|
|
515
520
|
/**
|
package/dist/cloud-v2/client.js
CHANGED
|
@@ -13,7 +13,7 @@ import { SealedTransportError, createSealedFetch } from '../sealed/sealed.js';
|
|
|
13
13
|
import { fetchAttestedKey } from './attestation.js';
|
|
14
14
|
import { CalimeroError, ConfirmCancelled, ConfirmRequired, LoginRequired, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
15
15
|
import { b64url, fromB64url } from './passkey.js';
|
|
16
|
-
import { pageQuery, pendingApprovalsFrom, } from './approvals.js';
|
|
16
|
+
import { confirmationCode, pageQuery, pendingApprovalsFrom, } from './approvals.js';
|
|
17
17
|
export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
18
18
|
/** One URL path segment, so an id cannot reach another route. */
|
|
19
19
|
function seg(value) {
|
|
@@ -781,17 +781,37 @@ export class CalimeroClient {
|
|
|
781
781
|
}
|
|
782
782
|
/**
|
|
783
783
|
* {@link requestConsent}, then send the browser to the consent page
|
|
784
|
-
* (`navigate`, by default `window.location.assign`).
|
|
785
|
-
*
|
|
786
|
-
*
|
|
784
|
+
* (`navigate`, by default `window.location.assign`). Pass `navigate` itself
|
|
785
|
+
* or {@link OpenConsentOptions}, whose `confirm` runs first with the node's
|
|
786
|
+
* answer so the app can show the person its `code`; when it answers `false`
|
|
787
|
+
* the page is not opened. When the node sends a `code` that is not
|
|
788
|
+
* {@link confirmationCode} of `requestId`, it throws `CalimeroError`
|
|
789
|
+
* (`CONSENT_CODE_MISMATCH`) and does not navigate. Answers the request
|
|
790
|
+
* once `navigate` returns (or `confirm` declines): with a popup
|
|
791
|
+
* (`url => window.open(url)`), poll it with {@link waitForConsent}.
|
|
787
792
|
*/
|
|
788
|
-
async openConsentPage(request,
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
793
|
+
async openConsentPage(request, navigateOrOptions = {}) {
|
|
794
|
+
const options = typeof navigateOrOptions === 'function' ? { navigate: navigateOrOptions } : navigateOrOptions;
|
|
795
|
+
const navigate = options.navigate ??
|
|
796
|
+
((url) => {
|
|
797
|
+
const w = globalThis.window;
|
|
798
|
+
if (!w)
|
|
799
|
+
throw new Error('no window to open the consent page in; pass `navigate`');
|
|
800
|
+
w.location.assign(url);
|
|
801
|
+
});
|
|
794
802
|
const started = await this.requestConsent(request);
|
|
803
|
+
if (started.code !== undefined) {
|
|
804
|
+
const expected = await confirmationCode(started.requestId);
|
|
805
|
+
if (started.code !== expected) {
|
|
806
|
+
throw new CalimeroError(200, 'CONSENT_CODE_MISMATCH', 'the consent page code does not match the request', {
|
|
807
|
+
requestId: started.requestId,
|
|
808
|
+
code: started.code,
|
|
809
|
+
expected,
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
if (options.confirm && !(await options.confirm(started)))
|
|
814
|
+
return started;
|
|
795
815
|
navigate(started.url);
|
|
796
816
|
return started;
|
|
797
817
|
}
|
package/dist/cloud-v2/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { claimedRelease, fetchAttestedKey, MOCK_QUOTE_HEADER } from './attestati
|
|
|
6
6
|
export type { AttestationDoc, CloudPolicy, CloudReleasePolicy } from './attestation.js';
|
|
7
7
|
export { browserPasskey, b64url, fromB64url } from './passkey.js';
|
|
8
8
|
export type { AssertionJSON, PasskeyProvider, RegistrationJSON } from './passkey.js';
|
|
9
|
-
export { MAX_REPORT_PAGE, RELEASE_VERIFIER, compareVersions, consentReturn, pageQuery, pendingApprovalsFrom, publisherBindingBytes, publisherBindingMessage, releaseConsent, releaseNotesUrl, stalledBy, upgradeConsent, verifyReleaseUrl, withdrawConsent, } from './approvals.js';
|
|
10
|
-
export type { ActorKind, AppsReport, Authority, ClusterRelease, ConsentReleaseModel, ConsentRequest, ConsentResult, ConsentScope, ConsentStarted, ConsentStatus, Governance, LastUpgrade, OpsAppsReport, OpsOrgsReport, PageOptions, PendingApprovals, PendingRelease, PendingUpgrade, PublisherBindingInfo, PublisherProof, ReleaseDeadline, ReleaseRules, ReportScope, ReportedApp, ReportedBundle, ReportedRelease, ReportedReplica, UpgradeAuthority, } from './approvals.js';
|
|
9
|
+
export { MAX_REPORT_PAGE, RELEASE_VERIFIER, compareVersions, confirmationCode, consentReturn, pageQuery, pendingApprovalsFrom, publisherBindingBytes, publisherBindingMessage, releaseConsent, releaseNotesUrl, stalledBy, upgradeConsent, verifyReleaseUrl, withdrawConsent, } from './approvals.js';
|
|
10
|
+
export type { ActorKind, AppsReport, Authority, ClusterRelease, ConsentReleaseModel, ConsentRequest, ConsentResult, ConsentScope, ConsentStarted, ConsentStatus, OpenConsentOptions, Governance, LastUpgrade, OpsAppsReport, OpsOrgsReport, PageOptions, PendingApprovals, PendingRelease, PendingUpgrade, PublisherBindingInfo, PublisherProof, ReleaseDeadline, ReleaseRules, ReportScope, ReportedApp, ReportedBundle, ReportedRelease, ReportedReplica, UpgradeAuthority, } from './approvals.js';
|
|
11
11
|
export { DEFAULT_ORG_CAPABILITIES, ORG_CAPABILITIES, orgCapabilities } from './capabilities.js';
|
|
12
12
|
export type { OrgCapability } from './capabilities.js';
|
package/dist/cloud-v2/index.js
CHANGED
|
@@ -2,5 +2,5 @@ export { CalimeroClient } from './client.js';
|
|
|
2
2
|
export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
3
3
|
export { claimedRelease, fetchAttestedKey, MOCK_QUOTE_HEADER } from './attestation.js';
|
|
4
4
|
export { browserPasskey, b64url, fromB64url } from './passkey.js';
|
|
5
|
-
export { MAX_REPORT_PAGE, RELEASE_VERIFIER, compareVersions, consentReturn, pageQuery, pendingApprovalsFrom, publisherBindingBytes, publisherBindingMessage, releaseConsent, releaseNotesUrl, stalledBy, upgradeConsent, verifyReleaseUrl, withdrawConsent, } from './approvals.js';
|
|
5
|
+
export { MAX_REPORT_PAGE, RELEASE_VERIFIER, compareVersions, confirmationCode, consentReturn, pageQuery, pendingApprovalsFrom, publisherBindingBytes, publisherBindingMessage, releaseConsent, releaseNotesUrl, stalledBy, upgradeConsent, verifyReleaseUrl, withdrawConsent, } from './approvals.js';
|
|
6
6
|
export { DEFAULT_ORG_CAPABILITIES, ORG_CAPABILITIES, orgCapabilities } from './capabilities.js';
|
package/dist/index.browser.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
function R(r){return Array.from(r,e=>e.toString(16).padStart(2,"0")).join("")}function pe(r,e,t){let n=r.trim();if(!/^[0-9a-fA-F]*$/.test(n)||n.length!==t*2)throw new Error(`${e} must be ${t*2} hex characters, got ${n.length}`);let i=new Uint8Array(t);for(let s=0;s<t;s+=1)i[s]=Number.parseInt(n.slice(s*2,s*2+2),16);return i}function y(...r){let e=new Uint8Array(r.reduce((n,i)=>n+i.length,0)),t=0;for(let n of r)e.set(n,t),t+=n.length;return e}var gr="Noise_NK_25519_AESGCM_SHA256",Me=32,pr=16,fr=new Uint8Array([48,46,2,1,0,48,5,6,3,43,101,110,4,34,4,32]),$e=class r{constructor(e){this.k=null;this.n=0;this.ck=e,this.h=e}static async initialize(){let e=new TextEncoder().encode(gr),t=new Uint8Array(32);return t.set(e),new r(t)}async mixHash(e){this.h=await yr(y(this.h,e))}async mixKey(e){let[t,n]=await at(this.ck,e);this.ck=t,this.k=await crypto.subtle.importKey("raw",n,"AES-GCM",!1,["encrypt","decrypt"]),this.n=0}async encryptAndHash(e){if(!this.k)throw new Error("Noise: no cipher key yet");let t=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:ot(this.n),additionalData:this.h},this.k,e));return this.n+=1,await this.mixHash(t),t}async decryptAndHash(e){if(!this.k)throw new Error("Noise: no cipher key yet");let t=new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:ot(this.n),additionalData:this.h},this.k,e));return this.n+=1,await this.mixHash(e),t}split(){return at(this.ck,new Uint8Array)}};async function ct(r,e,t){let n=await $e.initialize();await n.mixHash(e),await n.mixHash(r);let i=await G(t);return await n.mixHash(i.publicKey),await n.mixKey(await W(i.privateKey,r)),{message1:y(i.publicKey,await n.encryptAndHash(new Uint8Array)),async finish(o){if(o.length<Me+pr)throw new Error("Noise: message 2 is too short");let a=o.slice(0,Me);return await n.mixHash(a),await n.mixKey(await W(i.privateKey,a)),{payload:await n.decryptAndHash(o.slice(Me)),split:await n.split()}}}}async function G(r){if(!r){let n;try{n=await crypto.subtle.generateKey({name:"X25519"},!0,["deriveBits"])}catch(s){throw new Error(`Sealed transport needs WebCrypto with X25519, which this runtime lacks (${s?.name??"no crypto.subtle"}). Current browsers and Node have it; in React Native, install react-native-quick-crypto as the global crypto.`)}let i=new Uint8Array(await crypto.subtle.exportKey("raw",n.publicKey));return{privateKey:n.privateKey,publicKey:i}}let e=await crypto.subtle.importKey("pkcs8",y(fr,r),{name:"X25519"},!0,["deriveBits"]),t=await crypto.subtle.exportKey("jwk",e);return{privateKey:e,publicKey:hr(t.x)}}async function W(r,e){let t=await crypto.subtle.importKey("raw",e,{name:"X25519"},!1,[]);return new Uint8Array(await crypto.subtle.deriveBits({name:"X25519",public:t},r,256))}function ot(r){let e=new Uint8Array(12);return new DataView(e.buffer).setBigUint64(4,BigInt(r),!1),e}async function yr(r){return new Uint8Array(await crypto.subtle.digest("SHA-256",r))}async function _e(r,e){let t=await crypto.subtle.importKey("raw",r,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return new Uint8Array(await crypto.subtle.sign("HMAC",t,e))}async function at(r,e){let t=await _e(r,e),n=await _e(t,new Uint8Array([1])),i=await _e(t,y(n,new Uint8Array([2])));return[n,i]}function hr(r){let e=r.replace(/-/g,"+").replace(/_/g,"/"),t=atob(e+"=".repeat((4-e.length%4)%4));return Uint8Array.from(t,n=>n.charCodeAt(0))}var gt="/sealed/v2/handshake",pt="/sealed/v2",ee="application/vnd.calimero.sealed",Be=2,mr=new TextEncoder().encode("calimero/sealed-http/v2"),X=16,wr=1+X+8,Ar=0,br=1,Er=2,Rr=1+64*1024+16,Pr=1024,Ur=6e4,xr="calimero.tee-attest.transport-key.v1",Tr=[101,204,205,304],ft=new TextEncoder,te=class extends Error{constructor(){super("The node no longer holds the attested transport key; attest again for the current one");this.name="StaleTransportKeyError"}},S=class extends Error{constructor(t,n,i,s){super(i);this.status=t;this.code=n;this.retryAfterMs=s;this.name="SealedTransportError"}};async function Ke(r,e){let t=await crypto.subtle.digest("SHA-256",y(ft.encode(xr),r,e));return new Uint8Array(t)}function Ve(r){let e=new URL(r.baseUrl),t=e.pathname.replace(/\/+$/,""),n=`${e.origin}${t}`,i=r.fetch??((g,p)=>fetch(g,p)),s=typeof r.transportPublicKey=="function"?r.transportPublicKey:void 0,o=s?Promise.resolve().then(s):Promise.resolve(r.transportPublicKey);o.catch(()=>{});let a,c=async()=>{try{return await ut(i,n,await lt(o))}catch(g){if(!(g instanceof te)||!s)throw g;return o=Promise.resolve().then(s),ut(i,n,await lt(o))}},u=async()=>{let g=a??d(void 0),p=await g;if(Date.now()<p.renewAt)return[p,g];let h=d(g);return[await h,h]},d=g=>{if(a===g){let p=c();a=p,p.catch(()=>{a===p&&(a=void 0)})}return a};return async(g,p)=>{let h=new Request(g,p),f=new URL(h.url);if(f.origin!==e.origin||!f.pathname.startsWith(`${t}/`))throw new Error(`Refusing to send ${f.href} outside the sealed node at ${r.baseUrl}`);let b=[];h.headers.forEach((P,V)=>b.push([V,P]));let N={method:h.method,path:f.pathname.slice(t.length)+f.search,headers:b},E=new Uint8Array(await h.arrayBuffer()),x=p?.signal??(g instanceof Request?g.signal:void 0),D=async P=>{let{requestId:V,header:Z,envelope:ge}=await vr(P,N,E),L=await i(`${n}${pt}`,{method:"POST",headers:{"content-type":ee},body:ge,signal:x});if(L.headers.get("content-type")!==ee)throw await ht(L);return Cr(L,P.responseKey,Z,V)},[Ie,Oe]=await u();try{return await D(Ie)}catch(P){if(!(P instanceof S)||P.code!=="unknown_session")throw P;return D(await d(Oe))}}}async function lt(r){let e=await r;if(e.length!==32)throw new Error("transportPublicKey must be 32 bytes");return e}async function ut(r,e,t){try{return await dt(r,e,t)}catch(n){if(!(n instanceof S)||n.code!=="busy")throw n;return await new Promise(i=>setTimeout(i,n.retryAfterMs??1e3)),dt(r,e,t)}}async function dt(r,e,t){let n=await ct(t,mr),i=await r(`${e}${gt}`,{method:"POST",headers:{"content-type":ee},body:y(new Uint8Array([Be]),t,n.message1)});if(i.headers.get("content-type")!==ee)throw await ht(i);let s=await Or(i,Pr);return Sr(n,s)}async function Sr(r,e){if(e[0]!==Be)throw new Error("The handshake reply is malformed");let t;try{t=await r.finish(e.slice(1))}catch{throw new Error("The handshake reply did not open: it did not come from the attested node")}let{payload:n,split:i}=t;if(n.length!==X+4)throw new Error("The handshake reply is malformed");let s=n.slice(0,X),o=new DataView(n.buffer,n.byteOffset).getUint32(X,!1),[a,c]=await Promise.all([crypto.subtle.importKey("raw",i[0],"AES-GCM",!1,["encrypt"]),crypto.subtle.importKey("raw",i[1],"AES-GCM",!1,["decrypt"])]);return i[0].fill(0),i[1].fill(0),{requestKey:a,responseKey:c,nextRequestId:1,renewAt:Date.now()+o*1e3-Ur,header(u){let d=new Uint8Array(wr);return d[0]=Be,d.set(s,1),new DataView(d.buffer).setBigUint64(1+X,BigInt(u),!1),d}}}async function vr(r,e,t){let n=r.nextRequestId;r.nextRequestId+=1;let i=r.header(n),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:yt(n,0),additionalData:i},r.requestKey,kr(e,t));return{requestId:n,header:i,envelope:y(i,new Uint8Array(s))}}function yt(r,e){let t=new Uint8Array(12),n=new DataView(t.buffer);return n.setBigUint64(0,BigInt(r),!1),n.setUint32(8,e,!1),t}function kr(r,e){let t=ft.encode(JSON.stringify(r)),n=new Uint8Array(4);return new DataView(n.buffer).setUint32(0,t.length,!1),y(n,t,e)}async function Cr(r,e,t,n){if(!r.body)throw new Error("The sealed response has no body");let i=Ir(r.body.getReader()),s=0,o=async()=>{let d=await i.next();if(!d)return null;let g;try{g=new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:yt(n,s),additionalData:t},e,d))}catch{throw new Error("A sealed response frame did not open: it was not sealed by the attested node")}return s+=1,{kind:g[0],data:g.slice(1)}},a=await o();if(!a||a.kind!==Ar)throw new Error("The sealed response is malformed");let c=JSON.parse(new TextDecoder().decode(a.data));if(Tr.includes(c.status))return await i.cancel(),new Response(null,{status:c.status,headers:c.headers});let u=new ReadableStream({async pull(d){try{let g=await o();g?g.kind===br?d.enqueue(g.data):g.kind===Er?(d.close(),await i.cancel()):d.error(new Error("The sealed response is malformed")):d.error(new Error("The sealed response was cut short"))}catch(g){d.error(g)}},cancel(){return i.cancel()}});return new Response(u,{status:c.status,headers:c.headers})}function Ir(r){let e=new Uint8Array,t=async n=>{for(;e.length<n;){let{done:i,value:s}=await r.read();if(i)return!1;e=y(e,s)}return!0};return{async next(){if(!await t(4))return null;let n=new DataView(e.buffer,e.byteOffset).getUint32(0,!1);if(n>Rr)throw await r.cancel(),new Error("The sealed response is malformed: a frame is larger than the node sends");if(!await t(4+n))return null;let i=e.slice(4,4+n);return e=e.slice(4+n),i},cancel:()=>r.cancel()}}async function Or(r,e){if(!r.body)return new Uint8Array;let t=r.body.getReader(),n=new Uint8Array;for(;;){let{done:i,value:s}=await t.read();if(i)return n;if(n=y(n,s),n.length>e)throw await t.cancel(),new Error("The handshake reply is malformed: it is too long")}}async function ht(r){let e,t=`Sealed request refused: HTTP ${r.status}`;try{let s=await r.json();e=s?.error?.code,s?.error?.message&&(t=`Sealed request refused: ${s.error.message}`)}catch{}if(e==="stale_transport_key")return new te;let n=Number(r.headers.get("retry-after")),i=Number.isFinite(n)&&n>0?Math.min(n,5)*1e3:void 0;return new S(r.status,e,t,i)}var mt=[{uri:"https://fulcio.sigstore.dev",validFor:{start:"2021-03-07T03:20:29Z",end:"2022-12-31T23:59:59.999Z"},certChain:["MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIxMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSyA7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0JcastaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2uSu1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJxVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uupHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ=="]},{uri:"https://fulcio.sigstore.dev",validFor:{start:"2022-04-13T20:06:15Z"},certChain:["MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=","MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ"]}],wt=[{baseUrl:"https://rekor.sigstore.dev",logId:"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d",publicKey:"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwrkBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==",validFor:{start:"2021-01-12T11:53:27Z"}}];var Nr="1.2.840.10045.2.1",Dr={"1.2.840.10045.3.1.7":"P-256","1.3.132.0.34":"P-384"},Mr={"P-256":32,"P-384":48},_r={"1.2.840.10045.4.3.2":"SHA-256","1.2.840.10045.4.3.3":"SHA-384"};function At(r,e,t){if(e+2>t)throw new Error("it is truncated");let n=r[e];if((n&31)===31)throw new Error("it uses a tag this parser does not read");let i=r[e+1],s=e+2;if(i&128){let a=i&127;if(a===0||a>4||s+a>t)throw new Error("it has a length this parser does not read");i=0;for(let c=0;c<a;c+=1)i=i*256+r[s+c];s+=a}let o=s+i;if(o>t)throw new Error("it is truncated");return{tag:n,bytes:r,offset:e,start:s,end:o}}function j(r){let e=At(r,0,r.length);if(e.end!==r.length)throw new Error("it has trailing bytes");return e}function A(r){let e=[];for(let t=r.start;t<r.end;){let n=At(r.bytes,t,r.end);e.push(n),t=n.end}return e}function m(r,e,t){if(!r||r.tag!==e)throw new Error(`${t} is not where it should be`);return r}function v(r){return r.bytes.slice(r.start,r.end)}function fe(r){return r.bytes.slice(r.offset,r.end)}function F(r){let e=v(m(r,6,"An object identifier"));if(e.length===0||e[e.length-1]&128)throw new Error("it has a malformed object identifier");let t=[],n=0;for(let o of e)n=n*128+(o&127),o&128||(t.push(n),n=0);let i=t.shift();return[...i<80?[Math.floor(i/40),i%40]:[2,i-80],...t].join(".")}function $r(r){let e=new TextDecoder().decode(v(r)),t=r.tag===23?/^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/.exec(e):null,n=r.tag===24?/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/.exec(e):null,i=t??n;if(!i)throw new Error(`it holds the time ${JSON.stringify(e)}, which is not one a certificate may hold`);let s=Number(i[1]);t&&(s+=s<50?2e3:1900);let[o,a,c,u,d]=i.slice(2).map(Number);return Date.UTC(s,o-1,a,c,u,d)}function Le(r){try{let[e,t,n,...i]=A(m(j(r),48,"The certificate"));if(i.length>0)throw new Error("it has fields after its signature");let s=A(m(e,48,"The signed part")),o=s[0]?.tag===160?1:0,[a,c,u,d,g,p,...h]=s.slice(o);m(a,2,"The serial number");let f=F(A(m(t,48,"The signature algorithm"))[0]);if(F(A(m(c,48,"The signature algorithm"))[0])!==f)throw new Error("it names two different signature algorithms");let N=_r[f];if(!N)throw new Error(`it is signed with ${f}, not ECDSA with SHA-256 or SHA-384`);let[E,x]=A(m(d,48,"The validity")).map($r);if(x===void 0)throw new Error("its validity is incomplete");let[D,Ie]=A(m(p,48,"The public key"));m(Ie,3,"The public key");let[Oe,P]=A(m(D,48,"The key algorithm"));if(F(Oe)!==Nr)throw new Error("its key is not an elliptic-curve key");let V=Dr[F(P)];if(!V)throw new Error("its key is on a curve other than P-256 or P-384");let Z=new Map,ge=h.find(Ne=>Ne.tag===163);if(ge){let[Ne]=A(ge);for(let dr of A(m(Ne,48,"The extensions"))){let H=A(m(dr,48,"An extension"));if(H.length===3)m(H[1],1,"An extension's critical flag");else if(H.length!==2)throw new Error("it has a malformed extension");let De=F(H[0]);if(Z.has(De))throw new Error(`it has extension ${De} twice`);Z.set(De,v(m(H[H.length-1],4,"An extension value")))}}let L=v(m(n,3,"The signature"));if(L[0]!==0)throw new Error("its signature is not a whole number of bytes");return{der:r,tbs:fe(e),signatureHash:N,signature:L.slice(1),issuer:fe(m(u,48,"The issuer")),subject:fe(m(g,48,"The subject")),notBefore:E,notAfter:x,spki:fe(p),curve:V,extensions:Z}}catch(e){throw new Error(`The certificate is malformed: ${e.message}`)}}function bt(r){return A(m(j(r),48,"The list")).map(F)}function Br(r,e){let t=Mr[e],n=A(m(j(r),48,"The signature"));if(n.length!==2)throw new Error("The signature is not an ECDSA signature");let i=new Uint8Array(t*2);return n.forEach((s,o)=>{let a=v(m(s,2,"The signature"));if(a.length===0||a[0]&128)throw new Error("The signature is not an ECDSA signature");for(;a.length>1&&a[0]===0;)a=a.subarray(1);if(a.length>t)throw new Error("The signature is not an ECDSA signature");i.set(a,o*t+t-a.length)}),i}async function ye(r,e,t,n,i){let s;try{s=Br(n,e)}catch{return!1}let o=await crypto.subtle.importKey("spki",r,{name:"ECDSA",namedCurve:e},!1,["verify"]);return crypto.subtle.verify({name:"ECDSA",hash:t},o,s,i)}function U(r,e){let t=r.replace(/\s+/g,"");if(!/^[A-Za-z0-9+/]*={0,2}$/.test(t)||t.length%4!==0)throw new Error(`${e} is not base64`);let n=atob(t),i=new Uint8Array(n.length);for(let s=0;s<n.length;s+=1)i[s]=n.charCodeAt(s);return i}function He(r,e){let t=[...r.matchAll(/-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g)];if(t.length!==1||r.replace(t[0][0],"").trim()!=="")throw new Error(`${e} is not exactly one PEM certificate`);return U(t[0][1],e)}var Kr="2.5.29.17",Vr="2.5.29.37",Lr="1.3.6.1.5.5.7.3.3",Hr="1.3.6.1.4.1.57264.1.8",Gr="1.3.6.1.4.1.57264.1.1",Fr=134,jr=12,Qr=48,qr=new TextEncoder,Q=r=>new TextDecoder().decode(r);async function he(r,e,t,n){let{base64Signature:i,cert:s,rekorBundle:o}=Zr(e),a=o.Payload;if(n!==void 0&&n.trim()!==i.trim())throw new Error("The detached signature is not the one in the bundle");let c=U(i,"The bundle signature"),u=He(Q(U(s,"The bundle certificate")),"The bundle certificate"),d=Le(u),g=wt.find(x=>x.logId===a.logID.toLowerCase());if(!g)throw new Error(`The bundle names Rekor log ${a.logID}, which the Sigstore trust root does not know`);let p=qr.encode(`{"body":${JSON.stringify(a.body)},"integratedTime":${a.integratedTime},"logID":${JSON.stringify(a.logID)},"logIndex":${a.logIndex}}`);if(!await ye(U(g.publicKey,"The Rekor key"),"P-256","SHA-256",U(o.SignedEntryTimestamp,"The signed entry timestamp"),p))throw new Error("Rekor's signed entry timestamp does not verify: the log entry, its time or its index was altered");let f=a.integratedTime*1e3;if(!Pt(f,g.validFor))throw new Error(`Rekor log ${g.baseUrl} was not in use at ${re(f)}, when the entry says it was logged`);let b=Wr(a.body),N=R(new Uint8Array(await crypto.subtle.digest("SHA-256",r)));if(b.hash!==N)throw new Error("The file's SHA-256 is not the one Rekor logged: the file is not the one signed");if(!Ge(U(b.signature,"The logged signature"),c))throw new Error("The bundle's signature is not the one Rekor logged");let E=He(Q(U(b.publicKey,"The logged certificate")),"The logged certificate");if(!Ge(E,u))throw new Error("The bundle's certificate is not the one Rekor logged");if(d.curve!=="P-256"||!await ye(d.spki,"P-256","SHA-256",c,r))throw new Error("The signature over the file does not verify with the bundle's certificate");return await Jr(d,f),Yr(d,t),{integratedTime:a.integratedTime}}async function Jr(r,e){if(!Rt(r,e))throw new Error(`The signing certificate was valid ${re(r.notBefore)} to ${re(r.notAfter)}, not at ${re(e)} when Rekor logged it`);let t=[];for(let n of mt){let i=n.certChain.map(o=>Le(U(o,"A Fulcio certificate")));if(!await Et(r,i[0]))continue;let s=await zr(i,n.validFor,e);if(!s)return;t.push(`${n.uri} (valid from ${n.validFor.start}): ${s}`)}throw new Error(t.length>0?`The signing certificate's CA is not trusted at ${re(e)}: ${t.join("; ")}`:"The signing certificate was not issued by a Fulcio CA in the Sigstore trust root")}async function zr(r,e,t){if(!Pt(t,e))return"the trust root says it was not issuing certificates then";for(let[n,i]of r.entries()){if(!Rt(i,t))return`its certificate ${n} was not valid then`;let s=r[n+1]??i;if(!await Et(i,s))return`its certificate ${n} is not signed by the next`}}async function Et(r,e){return Ge(r.issuer,e.subject)?ye(e.spki,e.curve,r.signatureHash,r.signature,r.tbs):!1}function Yr(r,e){let t=r.extensions.get(Kr);if(!t)throw new Error("The signing certificate names no identity");let n=A(m(j(t),Qr,"The subject alternative name")),i=n.filter(u=>u.tag===Fr).map(u=>Q(v(u)));if(i.length!==1||n.length!==1||i[0]!==e.identity)throw new Error(`The release was signed by ${JSON.stringify(i.length===1?i[0]:i)}, not by ${e.identity}`);let s=r.extensions.get(Hr),o=r.extensions.get(Gr),a=s?Q(v(m(j(s),jr,"The OIDC issuer"))):o?Q(o):void 0;if(a!==e.issuer)throw new Error(`The signing certificate's OIDC issuer is ${a===void 0?"missing":JSON.stringify(a)}, not ${e.issuer}`);let c=r.extensions.get(Vr);if(!c||!bt(c).includes(Lr))throw new Error("The signing certificate is not for code signing")}function Zr(r){let e=r;if(typeof e=="string")try{e=JSON.parse(e)}catch{throw new Error("The bundle is not JSON")}let t=e,n=t?.rekorBundle?.Payload;if(!(typeof t?.base64Signature=="string"&&typeof t.cert=="string"&&typeof t.rekorBundle?.SignedEntryTimestamp=="string"&&typeof n?.body=="string"&&typeof n.logID=="string"&&/^[0-9a-fA-F]{64}$/.test(n.logID)&&Number.isSafeInteger(n.integratedTime)&&n.integratedTime>=0&&Number.isSafeInteger(n.logIndex)&&n.logIndex>=0))throw new Error("The bundle is not a cosign bundle with a Rekor entry");return t}function Wr(r){let e;try{e=JSON.parse(Q(U(r,"The logged entry")))}catch{throw new Error("The logged entry is not JSON")}let t=e?.spec?.data?.hash,n=e?.spec?.signature;if(e?.kind!=="hashedrekord"||t?.algorithm!=="sha256"||typeof t.value!="string"||typeof n?.content!="string"||typeof n.publicKey?.content!="string")throw new Error("The logged entry is not a SHA-256 hashedrekord");return{hash:t.value.toLowerCase(),signature:n.content,publicKey:n.publicKey.content}}function Rt(r,e){return r.notBefore<=e&&e<=r.notAfter}function Pt(r,e){return Date.parse(e.start)<=r&&(e.end===void 0||r<=Date.parse(e.end))}function re(r){return new Date(r).toISOString()}function Ge(r,e){return r.length===e.length&&r.every((t,n)=>t===e[n])}var Xr=/^[0-9a-f]{96}$/,en=["mrtd","rtmr0","rtmr1","rtmr2","rtmr3"];function _(r){let e=q(r.allowedMrtd??[],"allowedMrtd"),t=(r.allowedMeasurements??[]).map((a,c)=>{let u=`allowedMeasurements[${c}]`;return en.map(d=>q([a?.[d]??""],`${u}.${d}`)[0]).join()}),n=[q(r.allowedRtmr0??[],"allowedRtmr0"),q(r.allowedRtmr1??[],"allowedRtmr1"),q(r.allowedRtmr2??[],"allowedRtmr2"),q(r.allowedRtmr3??[],"allowedRtmr3")];if(r.allowedMeasurements!==void 0&&t.length===0)throw new Error("allowedMeasurements is empty, so no quote would ever be accepted");if(t.length===0){if(e.length===0)throw new Error("No image is trusted: give allowedMeasurements, or allowedMrtd with allowedRtmr1-3");if(n.slice(1).some(a=>a.length===0))throw new Error("allowedMrtd alone does not name an image: the MRTD measures the TD firmware, which images share, and the image is in RTMR1-3. Give allowedMeasurements, or allowedRtmr1-3 too")}let i=r.allowedTcbStatuses??["UpToDate"],s=r.now??Date.now;return Object.assign(async({quoteB64:a,nonce:c,reportDataSuffix:u,collateral:d})=>{let g=rn(a),p=d??await r.fetchCollateral?.(g);if(!p)throw new Error("The node sent no collateral for its quote, and no fetchCollateral was given to get it");let h;try{h=r.dcapVerify(g,p,Math.floor(s()/1e3))}catch(E){throw new Error(`The quote did not verify: ${E?.message??String(E)}`)}if(h.status==="Revoked"||!i.includes(h.status))throw new Error(`The platform's TCB status is ${h.status}, which is not accepted`);let f=tn(h.report);if(f.tdAttributes?.length!==8||(f.tdAttributes[0]&1)!==0)throw new Error("The quote is from a debug TD, or its TD attributes cannot be read");let b=[f.mrTd,f.rtMr0,f.rtMr1,f.rtMr2,f.rtMr3].map(E=>R(E));if(t.length>0&&!t.includes(b.join()))throw new Error(`The measurements (MRTD ${b[0]}, RTMR0-3 ${b.slice(1).join(", ")}) are not an image this verifier trusts`);if(e.length>0&&!e.includes(b[0]))throw new Error(`MRTD ${b[0]} is not an image this verifier trusts`);if([f.rtMr0,f.rtMr1,f.rtMr2,f.rtMr3].forEach((E,x)=>{let D=n[x];if(D.length>0&&!D.includes(R(E)))throw new Error(`RTMR${x} ${R(E)} is not one this verifier trusts`)}),R(f.reportData)!==`${c}${u}`.toLowerCase())throw new Error("The quote does not commit to this nonce and binding");return!0},{includeCollateral:!0})}function q(r,e){return r.map(t=>{let n=t.trim().toLowerCase();if(!Xr.test(n))throw new Error(`${e} holds ${JSON.stringify(t)}, which is not a 48-byte hex measurement`);return n})}function tn(r){let e=r.data;if(r.type==="td10"&&e)return e;if(r.type==="td15"&&e?.base)return e.base;throw new Error(`The quote is a ${r.type} quote, not a TDX one`)}function rn(r){let e=atob(r),t=new Uint8Array(e.length);for(let n=0;n<e.length;n+=1)t[n]=e.charCodeAt(n);return t}var nn=["UpToDate","SWHardeningNeeded","ConfigurationNeeded","ConfigurationAndSWHardeningNeeded","OutOfDate","OutOfDateConfigurationNeeded"],M="locked-read-only";function Fe(r,{profile:e,allowDebugProfile:t=!1}){if(r.length===0)throw new Error("No release given, so no image would be trusted");let n,i=r.map((s,o)=>{let a=s?.tag??`releases[${o}]`;if(s?.role!==void 0&&s.role!=="node")throw new Error(`${a} lists the measurements of a ${s.role}, not of a node image`);let c=s?.profiles?.[e];if(!c){let d=Object.keys(s?.profiles??{}).join(", ")||"none";throw new Error(`${a} has no profile ${JSON.stringify(e)} (it has: ${d})`)}if(e!==M&&!t)throw new Error(`${JSON.stringify(e)} is not a production profile: its image is readable by whoever operates the node. Trust ${JSON.stringify(M)}, or pass allowDebugProfile to test`);let u=(c.allowed_tcb_statuses??["uptodate"]).map(d=>sn(d,a));return n=n===void 0?u:n.filter(d=>u.includes(d)),{mrtd:c.mrtd,rtmr0:c.rtmr0,rtmr1:c.rtmr1,rtmr2:c.rtmr2,rtmr3:c.rtmr3}});if(!n||n.length===0)throw new Error("The releases given accept no TCB status in common");return{allowedMeasurements:i,allowedTcbStatuses:n}}function sn(r,e){let t=nn.find(n=>n.toLowerCase()===String(r).toLowerCase());if(!t)throw new Error(`${e} accepts TCB status ${JSON.stringify(r)}, which this verifier does not know`);return t}var je=Object.freeze({identity:"https://github.com/calimero-network/mero-tee/.github/workflows/release-node-image-gcp.yaml@refs/heads/master",issuer:"https://token.actions.githubusercontent.com"}),on=["mrtd","rtmr0","rtmr1","rtmr2","rtmr3"],Qe="https://cloud.calimero.network";async function xt(r,e,t={}){let n=typeof r=="string"?new TextEncoder().encode(r):r;await he(n,e,{identity:t.identity??je.identity,issuer:t.issuer??je.issuer},t.signature);let i;try{i=JSON.parse(new TextDecoder().decode(n))}catch{throw new Error("The signed release is not JSON")}if(i?.role!=="node")throw new Error(`The signed release is a ${JSON.stringify(i?.role)} release, not a node one`);let s=Object.values(i.profiles??{}),o=a=>on.every(c=>/^[0-9a-f]{96}$/i.test(String(a?.[c])));if(typeof i.tag!="string"||s.length===0||!s.every(o))throw new Error("The signed file is not a release's published-mrtds.json: it lists no measured profiles");if(t.expectedVersion!==void 0&&i.tag!==t.expectedVersion)throw new Error(`The signed release is ${i.tag}, not ${t.expectedVersion}`);return i}async function qe(r,e={}){let t=await(e.fetch??fetch)(r,{headers:{accept:"application/json"}});if(!t.ok)throw new Error(`Fetching the node release from ${r} failed: HTTP ${t.status}`);let n;try{n=(await t.json())?.data}catch{throw new Error(`${r} did not answer with JSON`)}if(typeof n?.version!="string"||typeof n.publishedMrtds!="string"||typeof n.bundle!="string")throw new Error(`${r} did not answer with a signed node release`);return{version:n.version,publishedMrtds:n.publishedMrtds,bundle:n.bundle}}var Tt="https://github.com/calimero-network/mero-tee/releases/download";async function Je(r,e={}){let t=`mero-tee-v${k(r,"version")}`,n=`${(e.base??Tt).replace(/\/+$/,"")}/${t}/published-mrtds.json`,i=async a=>{let c=await(e.fetch??fetch)(a);if(!c.ok)throw new Error(`Fetching ${a} failed: HTTP ${c.status}`);return c.text()},[s,o]=await Promise.all([i(n),i(`${n}.bundle.json`)]);return{version:r,publishedMrtds:s,bundle:o}}function ze(r,e){return`${r.replace(/\/+$/,"")}/api/tee/node-releases/${k(e,"version")}`}async function me(r){let e=k(r.minReleaseVersion,"minReleaseVersion"),t=k(r.release?.version,"The release version"),n=await xt(r.release.publishedMrtds,r.release.bundle,{expectedVersion:t,identity:r.identity,issuer:r.issuer});if(ne(t,e)<0)throw new Error(`Release ${t} is older than the minimum trusted, ${e}`);return Fe([n],{profile:r.profile,allowDebugProfile:r.allowDebugProfile})}function an(r){return k(r.minReleaseVersion,"minReleaseVersion"),Object.assign(async t=>{let n=await me({release:await r.release(),profile:r.profile,allowDebugProfile:r.allowDebugProfile,minReleaseVersion:r.minReleaseVersion,identity:r.identity,issuer:r.issuer});return _({dcapVerify:r.dcapVerify,fetchCollateral:r.fetchCollateral,now:r.now,...n})(t)},{includeCollateral:!0})}var St=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function k(r,e){let t=typeof r=="string"?St.exec(r):null,n=t?.[4];if(!t||n!==void 0&&n.split(".").some(i=>i===""))throw new Error(`${e} is ${JSON.stringify(r)}, not a release version like 2.3.87`);return r}function ne(r,e){let[t,n]=Ut(r),[i,s]=Ut(e);for(let c=0;c<3;c+=1)if(t[c]!==i[c])return t[c]<i[c]?-1:1;if(n===void 0||s===void 0)return n===s?0:n===void 0?1:-1;let o=n.split("."),a=s.split(".");for(let c=0;c<Math.max(o.length,a.length);c+=1){let[u,d]=[o[c],a[c]];if(u===void 0||d===void 0)return u===void 0?-1:1;let[g,p]=[/^\d+$/.test(u),/^\d+$/.test(d)],h=g&&p?Math.sign(Number(u)-Number(d)):g!==p?g?-1:1:u<d?-1:u>d?1:0;if(h!==0)return h}return 0}function Ut(r){let e=St.exec(r);return[[Number(e[1]),Number(e[2]),Number(e[3])],e[4]]}var Ct="MOCK_TDX_QUOTE_V1";function cn(r){let e=atob(r),t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function Ye(r,e){if(r.length!==e.length)return!1;let t=0;for(let n=0;n<r.length;n++)t|=r[n]^e[n];return t===0}var vt;async function kt(r){vt??(vt=import("@phala/dcap-qvl"));let e=await vt,t=typeof e[r]=="function"?e[r]:e.default?.[r];if(typeof t!="function")throw new TypeError(`@phala/dcap-qvl loaded without ${r}`);return t}function It(r,e){let t=k(e,"minReleaseVersion"),n=String(r.release?.version??"").trim().replace(/^mero-tee-v/,"").replace(/^v/,""),i=k(n,"The release the node names");if(ne(i,t)<0)throw new Error(`mero-tee release ${i} is older than the minimum ${t}`);return i}async function ln(r,e,t){let n=e.releaseSource;return typeof n=="function"?n(r):n==="github"?Je(r,{fetch:t}):qe(ze(n??Qe,r),{fetch:t})}async function un(r,e,t,n){let i=It(r,t.minReleaseVersion),s=await me({release:await ln(i,t,n),profile:t.profile??M,allowDebugProfile:t.allowDebugProfile,minReleaseVersion:t.minReleaseVersion,identity:t.identity,issuer:t.issuer}),o=t.fetchCollateral??(async c=>(await kt("getCollateralFromPcs"))(c));return _({dcapVerify:t.dcapVerify??await kt("verify"),fetchCollateral:o,now:t.now,...s})(e)}async function Ze(r,e,t=(n,i)=>fetch(n,i)){let n=R(crypto.getRandomValues(new Uint8Array(32))),i=new URL(`${r.replace(/\/+$/,"")}/attestation`);i.searchParams.set("nonce",n),e.appHash&&i.searchParams.set("appHash",e.appHash);let s=await t(i.toString());if(!s.ok)throw new Error(`The node refused to attest: HTTP ${s.status}`);let o=await s.json(),a=pe(o.transportKey,"transportKey",32),c=e.appHash?pe(e.appHash,"appHash",32):new Uint8Array(32),u=await Ke(c,a),d=cn(o.quote),g=new TextEncoder().encode(Ct);if(Ye(d.slice(0,g.length),g)){if(!e.allowMock)throw new Error("mock quote refused: this client only trusts real TEEs");let f=d.slice(g.length,g.length+64);if(!Ye(f.slice(0,32),pe(n,"nonce",32))||!Ye(f.slice(32),u))throw new Error("the quote does not bind this transport key, app and nonce");return a}let p={quoteB64:o.quote,nonce:n,reportDataSuffix:R(u)},h;if(e.verifyQuote)h=await e.verifyQuote(p);else if(e.release)h=await un(o,p,e.release,t);else throw new Error("real quote refused: this client trusts no TD image (set policy.release)");if(!h)throw new Error("The attestation did not verify, so its transport key is not trusted");return a}var w=class extends Error{constructor(t,n,i,s={}){super(`${t} ${n}: ${i}`);this.status=t;this.code=n;this.details=s;this.name="CalimeroError"}},J=class extends w{constructor(e,t={}){super(401,"UNAUTHENTICATED",e,t),this.name="LoginRequired"}},$=class extends w{constructor(e,t={}){super(421,"WRONG_NODE",e,t),this.name="WrongNode"}},we=class extends w{constructor(e,t={}){super(404,"NOT_FOUND",e,t),this.name="NotFound"}},z=class extends w{constructor(e,t={}){super(412,"CONFIRM_REQUIRED",e,t),this.name="ConfirmRequired"}},ie=class extends Error{constructor(t){super("the passkey confirmation was cancelled");this.cause=t;this.name="ConfirmCancelled"}},Ae=class extends w{constructor(e,t={}){super(413,"ARGS_TOO_LARGE",e,t),this.name="ArgsTooLarge"}},be=class extends w{constructor(e,t={}){super(409,"IDEMPOTENCY_MISMATCH",e,t),this.name="IdempotencyMismatch"}},Ee=class extends w{constructor(e,t={}){super(409,"RELEASE_DEADLINE",e,t),this.name="ReleaseDeadlineError",this.release=typeof t.release=="string"?t.release:"",this.after=typeof t.after=="string"?t.after:""}},Re=class extends w{constructor(e,t={}){super(409,"CONSENT_STALE",e,t),this.name="ConsentStale"}},Pe=class extends w{constructor(e,t={}){super(422,"APP_ERROR",e,t),this.name="AppError";let{appCode:n,fields:i}=dn(t);this.appCode=n,this.fields=i}},Ue=class extends w{constructor(e,t={}){super(422,"TRAP",e,t),this.name="TrapError",this.kind=typeof t.kind=="string"?t.kind:""}},B=class extends w{constructor(e,t,n={},i,s){super(503,e,t,n),this.name="UnavailableError",this.reason=e.toLowerCase(),this.committed=e==="TIMEOUT"||e==="MIGRATING"?!1:"unknown",this.retryAfter=i,this.cause=s}};function xe(r){return r&&typeof r=="object"&&!Array.isArray(r)?r:{}}function dn(r){let e=typeof r.code=="string"?r:xe(r.error);return{appCode:typeof e.code=="string"?e.code:"",fields:{...xe(e.fields)}}}function gn(r,e){for(let t of[r.retryAfter,e==null?void 0:Number(e)])if(typeof t=="number"&&Number.isFinite(t)&&t>=0)return t}function Te(r,e,t){let n=xe(e),i=typeof n.error=="string"?n.error:"ERROR",s=typeof n.message=="string"?n.message:"",o=xe(n.details);if(r===503)return new B(i,s,o,gn(o,t));switch(`${r} ${i}`){case"401 UNAUTHENTICATED":return new J(s,o);case"421 WRONG_NODE":return new $(s,o);case"404 NOT_FOUND":return new we(s,o);case"409 IDEMPOTENCY_MISMATCH":return new be(s,o);case"409 RELEASE_DEADLINE":return new Ee(s,o);case"409 CONSENT_STALE":return new Re(s,o);case"412 CONFIRM_REQUIRED":return new z(s,o);case"413 ARGS_TOO_LARGE":return new Ae(s,o);case"422 APP_ERROR":return new Pe(s,o);case"422 TRAP":return new Ue(s,o);default:return new w(r,i,s,o)}}function T(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function C(r){let e=r.replace(/-/g,"+").replace(/_/g,"/")+"===".slice((r.length+3)%4),t=atob(e),n=new Uint8Array(t.length);for(let i=0;i<t.length;i++)n[i]=t.charCodeAt(i);return n}var se=r=>r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);function Ot(r){let e=new Error(r);return e.name="NotAllowedError",e}function pn(){return{async create(r){let e=r,t=await navigator.credentials.create({publicKey:{challenge:se(C(e.challenge)),rp:e.rp,user:{...e.user,id:se(C(e.user.id))},pubKeyCredParams:e.pubKeyCredParams,excludeCredentials:(e.excludeCredentials??[]).map(i=>({type:i.type,id:se(C(i.id))})),authenticatorSelection:e.authenticatorSelection,attestation:"none",timeout:e.timeout}});if(!t)throw Ot("passkey creation was cancelled");let n=t.response;return{attestationObject:T(new Uint8Array(n.attestationObject)),clientDataJson:T(new Uint8Array(n.clientDataJSON))}},async get(r,e,t){let n=await navigator.credentials.get({publicKey:{challenge:se(r),rpId:e,userVerification:"preferred",allowCredentials:(t??[]).map(s=>({type:"public-key",id:se(C(s))}))}});if(!n)throw Ot("passkey sign-in was cancelled");let i=n.response;return{credentialId:T(new Uint8Array(n.rawId)),authenticatorData:T(new Uint8Array(i.authenticatorData)),clientDataJson:T(new Uint8Array(i.clientDataJSON)),signature:T(new Uint8Array(i.signature))}}}}var We=100;function ae(r={}){let e=new URLSearchParams;if(r.after!==void 0&&e.set("after",r.after),r.limit!==void 0){if(!Number.isInteger(r.limit)||r.limit<1||r.limit>We)throw new RangeError(`limit is 1 to ${We}`);e.set("limit",String(r.limit))}let t=e.toString();return t?`?${t}`:""}function oe(r,e){try{return ne(r,e)}catch{return r<e?-1:r>e?1:0}}function Nt(r,e,t=Date.now()/1e3){if(r===null||r.length===0)return null;let n=r.reduce((s,o)=>oe(s,o)>=0?s:o),i=null;for(let s of e)s.afterSecs<=t&&oe(n,s.version)<0&&(i===null||oe(s.version,i.version)>0)&&(i=s);return i}function Dt(r,e,t,n){return`calimero-publisher-binding/v1
|
|
1
|
+
function R(r){return Array.from(r,e=>e.toString(16).padStart(2,"0")).join("")}function pe(r,e,t){let n=r.trim();if(!/^[0-9a-fA-F]*$/.test(n)||n.length!==t*2)throw new Error(`${e} must be ${t*2} hex characters, got ${n.length}`);let i=new Uint8Array(t);for(let s=0;s<t;s+=1)i[s]=Number.parseInt(n.slice(s*2,s*2+2),16);return i}function y(...r){let e=new Uint8Array(r.reduce((n,i)=>n+i.length,0)),t=0;for(let n of r)e.set(n,t),t+=n.length;return e}var pr="Noise_NK_25519_AESGCM_SHA256",Me=32,fr=16,yr=new Uint8Array([48,46,2,1,0,48,5,6,3,43,101,110,4,34,4,32]),$e=class r{constructor(e){this.k=null;this.n=0;this.ck=e,this.h=e}static async initialize(){let e=new TextEncoder().encode(pr),t=new Uint8Array(32);return t.set(e),new r(t)}async mixHash(e){this.h=await hr(y(this.h,e))}async mixKey(e){let[t,n]=await ct(this.ck,e);this.ck=t,this.k=await crypto.subtle.importKey("raw",n,"AES-GCM",!1,["encrypt","decrypt"]),this.n=0}async encryptAndHash(e){if(!this.k)throw new Error("Noise: no cipher key yet");let t=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:at(this.n),additionalData:this.h},this.k,e));return this.n+=1,await this.mixHash(t),t}async decryptAndHash(e){if(!this.k)throw new Error("Noise: no cipher key yet");let t=new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:at(this.n),additionalData:this.h},this.k,e));return this.n+=1,await this.mixHash(e),t}split(){return ct(this.ck,new Uint8Array)}};async function lt(r,e,t){let n=await $e.initialize();await n.mixHash(e),await n.mixHash(r);let i=await G(t);return await n.mixHash(i.publicKey),await n.mixKey(await W(i.privateKey,r)),{message1:y(i.publicKey,await n.encryptAndHash(new Uint8Array)),async finish(o){if(o.length<Me+fr)throw new Error("Noise: message 2 is too short");let a=o.slice(0,Me);return await n.mixHash(a),await n.mixKey(await W(i.privateKey,a)),{payload:await n.decryptAndHash(o.slice(Me)),split:await n.split()}}}}async function G(r){if(!r){let n;try{n=await crypto.subtle.generateKey({name:"X25519"},!0,["deriveBits"])}catch(s){throw new Error(`Sealed transport needs WebCrypto with X25519, which this runtime lacks (${s?.name??"no crypto.subtle"}). Current browsers and Node have it; in React Native, install react-native-quick-crypto as the global crypto.`)}let i=new Uint8Array(await crypto.subtle.exportKey("raw",n.publicKey));return{privateKey:n.privateKey,publicKey:i}}let e=await crypto.subtle.importKey("pkcs8",y(yr,r),{name:"X25519"},!0,["deriveBits"]),t=await crypto.subtle.exportKey("jwk",e);return{privateKey:e,publicKey:mr(t.x)}}async function W(r,e){let t=await crypto.subtle.importKey("raw",e,{name:"X25519"},!1,[]);return new Uint8Array(await crypto.subtle.deriveBits({name:"X25519",public:t},r,256))}function at(r){let e=new Uint8Array(12);return new DataView(e.buffer).setBigUint64(4,BigInt(r),!1),e}async function hr(r){return new Uint8Array(await crypto.subtle.digest("SHA-256",r))}async function _e(r,e){let t=await crypto.subtle.importKey("raw",r,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return new Uint8Array(await crypto.subtle.sign("HMAC",t,e))}async function ct(r,e){let t=await _e(r,e),n=await _e(t,new Uint8Array([1])),i=await _e(t,y(n,new Uint8Array([2])));return[n,i]}function mr(r){let e=r.replace(/-/g,"+").replace(/_/g,"/"),t=atob(e+"=".repeat((4-e.length%4)%4));return Uint8Array.from(t,n=>n.charCodeAt(0))}var pt="/sealed/v2/handshake",ft="/sealed/v2",ee="application/vnd.calimero.sealed",Be=2,wr=new TextEncoder().encode("calimero/sealed-http/v2"),X=16,Ar=1+X+8,br=0,Er=1,Rr=2,Pr=1+64*1024+16,Ur=1024,xr=6e4,Tr="calimero.tee-attest.transport-key.v1",Sr=[101,204,205,304],yt=new TextEncoder,te=class extends Error{constructor(){super("The node no longer holds the attested transport key; attest again for the current one");this.name="StaleTransportKeyError"}},S=class extends Error{constructor(t,n,i,s){super(i);this.status=t;this.code=n;this.retryAfterMs=s;this.name="SealedTransportError"}};async function Ke(r,e){let t=await crypto.subtle.digest("SHA-256",y(yt.encode(Tr),r,e));return new Uint8Array(t)}function Ve(r){let e=new URL(r.baseUrl),t=e.pathname.replace(/\/+$/,""),n=`${e.origin}${t}`,i=r.fetch??((g,p)=>fetch(g,p)),s=typeof r.transportPublicKey=="function"?r.transportPublicKey:void 0,o=s?Promise.resolve().then(s):Promise.resolve(r.transportPublicKey);o.catch(()=>{});let a,c=async()=>{try{return await dt(i,n,await ut(o))}catch(g){if(!(g instanceof te)||!s)throw g;return o=Promise.resolve().then(s),dt(i,n,await ut(o))}},u=async()=>{let g=a??d(void 0),p=await g;if(Date.now()<p.renewAt)return[p,g];let h=d(g);return[await h,h]},d=g=>{if(a===g){let p=c();a=p,p.catch(()=>{a===p&&(a=void 0)})}return a};return async(g,p)=>{let h=new Request(g,p),f=new URL(h.url);if(f.origin!==e.origin||!f.pathname.startsWith(`${t}/`))throw new Error(`Refusing to send ${f.href} outside the sealed node at ${r.baseUrl}`);let b=[];h.headers.forEach((P,V)=>b.push([V,P]));let N={method:h.method,path:f.pathname.slice(t.length)+f.search,headers:b},E=new Uint8Array(await h.arrayBuffer()),x=p?.signal??(g instanceof Request?g.signal:void 0),D=async P=>{let{requestId:V,header:Z,envelope:ge}=await kr(P,N,E),H=await i(`${n}${ft}`,{method:"POST",headers:{"content-type":ee},body:ge,signal:x});if(H.headers.get("content-type")!==ee)throw await mt(H);return Ir(H,P.responseKey,Z,V)},[Ie,Oe]=await u();try{return await D(Ie)}catch(P){if(!(P instanceof S)||P.code!=="unknown_session")throw P;return D(await d(Oe))}}}async function ut(r){let e=await r;if(e.length!==32)throw new Error("transportPublicKey must be 32 bytes");return e}async function dt(r,e,t){try{return await gt(r,e,t)}catch(n){if(!(n instanceof S)||n.code!=="busy")throw n;return await new Promise(i=>setTimeout(i,n.retryAfterMs??1e3)),gt(r,e,t)}}async function gt(r,e,t){let n=await lt(t,wr),i=await r(`${e}${pt}`,{method:"POST",headers:{"content-type":ee},body:y(new Uint8Array([Be]),t,n.message1)});if(i.headers.get("content-type")!==ee)throw await mt(i);let s=await Nr(i,Ur);return vr(n,s)}async function vr(r,e){if(e[0]!==Be)throw new Error("The handshake reply is malformed");let t;try{t=await r.finish(e.slice(1))}catch{throw new Error("The handshake reply did not open: it did not come from the attested node")}let{payload:n,split:i}=t;if(n.length!==X+4)throw new Error("The handshake reply is malformed");let s=n.slice(0,X),o=new DataView(n.buffer,n.byteOffset).getUint32(X,!1),[a,c]=await Promise.all([crypto.subtle.importKey("raw",i[0],"AES-GCM",!1,["encrypt"]),crypto.subtle.importKey("raw",i[1],"AES-GCM",!1,["decrypt"])]);return i[0].fill(0),i[1].fill(0),{requestKey:a,responseKey:c,nextRequestId:1,renewAt:Date.now()+o*1e3-xr,header(u){let d=new Uint8Array(Ar);return d[0]=Be,d.set(s,1),new DataView(d.buffer).setBigUint64(1+X,BigInt(u),!1),d}}}async function kr(r,e,t){let n=r.nextRequestId;r.nextRequestId+=1;let i=r.header(n),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:ht(n,0),additionalData:i},r.requestKey,Cr(e,t));return{requestId:n,header:i,envelope:y(i,new Uint8Array(s))}}function ht(r,e){let t=new Uint8Array(12),n=new DataView(t.buffer);return n.setBigUint64(0,BigInt(r),!1),n.setUint32(8,e,!1),t}function Cr(r,e){let t=yt.encode(JSON.stringify(r)),n=new Uint8Array(4);return new DataView(n.buffer).setUint32(0,t.length,!1),y(n,t,e)}async function Ir(r,e,t,n){if(!r.body)throw new Error("The sealed response has no body");let i=Or(r.body.getReader()),s=0,o=async()=>{let d=await i.next();if(!d)return null;let g;try{g=new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:ht(n,s),additionalData:t},e,d))}catch{throw new Error("A sealed response frame did not open: it was not sealed by the attested node")}return s+=1,{kind:g[0],data:g.slice(1)}},a=await o();if(!a||a.kind!==br)throw new Error("The sealed response is malformed");let c=JSON.parse(new TextDecoder().decode(a.data));if(Sr.includes(c.status))return await i.cancel(),new Response(null,{status:c.status,headers:c.headers});let u=new ReadableStream({async pull(d){try{let g=await o();g?g.kind===Er?d.enqueue(g.data):g.kind===Rr?(d.close(),await i.cancel()):d.error(new Error("The sealed response is malformed")):d.error(new Error("The sealed response was cut short"))}catch(g){d.error(g)}},cancel(){return i.cancel()}});return new Response(u,{status:c.status,headers:c.headers})}function Or(r){let e=new Uint8Array,t=async n=>{for(;e.length<n;){let{done:i,value:s}=await r.read();if(i)return!1;e=y(e,s)}return!0};return{async next(){if(!await t(4))return null;let n=new DataView(e.buffer,e.byteOffset).getUint32(0,!1);if(n>Pr)throw await r.cancel(),new Error("The sealed response is malformed: a frame is larger than the node sends");if(!await t(4+n))return null;let i=e.slice(4,4+n);return e=e.slice(4+n),i},cancel:()=>r.cancel()}}async function Nr(r,e){if(!r.body)return new Uint8Array;let t=r.body.getReader(),n=new Uint8Array;for(;;){let{done:i,value:s}=await t.read();if(i)return n;if(n=y(n,s),n.length>e)throw await t.cancel(),new Error("The handshake reply is malformed: it is too long")}}async function mt(r){let e,t=`Sealed request refused: HTTP ${r.status}`;try{let s=await r.json();e=s?.error?.code,s?.error?.message&&(t=`Sealed request refused: ${s.error.message}`)}catch{}if(e==="stale_transport_key")return new te;let n=Number(r.headers.get("retry-after")),i=Number.isFinite(n)&&n>0?Math.min(n,5)*1e3:void 0;return new S(r.status,e,t,i)}var wt=[{uri:"https://fulcio.sigstore.dev",validFor:{start:"2021-03-07T03:20:29Z",end:"2022-12-31T23:59:59.999Z"},certChain:["MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIxMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSyA7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0JcastaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2uSu1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJxVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uupHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ=="]},{uri:"https://fulcio.sigstore.dev",validFor:{start:"2022-04-13T20:06:15Z"},certChain:["MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=","MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ"]}],At=[{baseUrl:"https://rekor.sigstore.dev",logId:"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d",publicKey:"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwrkBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==",validFor:{start:"2021-01-12T11:53:27Z"}}];var Dr="1.2.840.10045.2.1",Mr={"1.2.840.10045.3.1.7":"P-256","1.3.132.0.34":"P-384"},_r={"P-256":32,"P-384":48},$r={"1.2.840.10045.4.3.2":"SHA-256","1.2.840.10045.4.3.3":"SHA-384"};function bt(r,e,t){if(e+2>t)throw new Error("it is truncated");let n=r[e];if((n&31)===31)throw new Error("it uses a tag this parser does not read");let i=r[e+1],s=e+2;if(i&128){let a=i&127;if(a===0||a>4||s+a>t)throw new Error("it has a length this parser does not read");i=0;for(let c=0;c<a;c+=1)i=i*256+r[s+c];s+=a}let o=s+i;if(o>t)throw new Error("it is truncated");return{tag:n,bytes:r,offset:e,start:s,end:o}}function j(r){let e=bt(r,0,r.length);if(e.end!==r.length)throw new Error("it has trailing bytes");return e}function A(r){let e=[];for(let t=r.start;t<r.end;){let n=bt(r.bytes,t,r.end);e.push(n),t=n.end}return e}function m(r,e,t){if(!r||r.tag!==e)throw new Error(`${t} is not where it should be`);return r}function v(r){return r.bytes.slice(r.start,r.end)}function fe(r){return r.bytes.slice(r.offset,r.end)}function F(r){let e=v(m(r,6,"An object identifier"));if(e.length===0||e[e.length-1]&128)throw new Error("it has a malformed object identifier");let t=[],n=0;for(let o of e)n=n*128+(o&127),o&128||(t.push(n),n=0);let i=t.shift();return[...i<80?[Math.floor(i/40),i%40]:[2,i-80],...t].join(".")}function Br(r){let e=new TextDecoder().decode(v(r)),t=r.tag===23?/^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/.exec(e):null,n=r.tag===24?/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/.exec(e):null,i=t??n;if(!i)throw new Error(`it holds the time ${JSON.stringify(e)}, which is not one a certificate may hold`);let s=Number(i[1]);t&&(s+=s<50?2e3:1900);let[o,a,c,u,d]=i.slice(2).map(Number);return Date.UTC(s,o-1,a,c,u,d)}function He(r){try{let[e,t,n,...i]=A(m(j(r),48,"The certificate"));if(i.length>0)throw new Error("it has fields after its signature");let s=A(m(e,48,"The signed part")),o=s[0]?.tag===160?1:0,[a,c,u,d,g,p,...h]=s.slice(o);m(a,2,"The serial number");let f=F(A(m(t,48,"The signature algorithm"))[0]);if(F(A(m(c,48,"The signature algorithm"))[0])!==f)throw new Error("it names two different signature algorithms");let N=$r[f];if(!N)throw new Error(`it is signed with ${f}, not ECDSA with SHA-256 or SHA-384`);let[E,x]=A(m(d,48,"The validity")).map(Br);if(x===void 0)throw new Error("its validity is incomplete");let[D,Ie]=A(m(p,48,"The public key"));m(Ie,3,"The public key");let[Oe,P]=A(m(D,48,"The key algorithm"));if(F(Oe)!==Dr)throw new Error("its key is not an elliptic-curve key");let V=Mr[F(P)];if(!V)throw new Error("its key is on a curve other than P-256 or P-384");let Z=new Map,ge=h.find(Ne=>Ne.tag===163);if(ge){let[Ne]=A(ge);for(let gr of A(m(Ne,48,"The extensions"))){let L=A(m(gr,48,"An extension"));if(L.length===3)m(L[1],1,"An extension's critical flag");else if(L.length!==2)throw new Error("it has a malformed extension");let De=F(L[0]);if(Z.has(De))throw new Error(`it has extension ${De} twice`);Z.set(De,v(m(L[L.length-1],4,"An extension value")))}}let H=v(m(n,3,"The signature"));if(H[0]!==0)throw new Error("its signature is not a whole number of bytes");return{der:r,tbs:fe(e),signatureHash:N,signature:H.slice(1),issuer:fe(m(u,48,"The issuer")),subject:fe(m(g,48,"The subject")),notBefore:E,notAfter:x,spki:fe(p),curve:V,extensions:Z}}catch(e){throw new Error(`The certificate is malformed: ${e.message}`)}}function Et(r){return A(m(j(r),48,"The list")).map(F)}function Kr(r,e){let t=_r[e],n=A(m(j(r),48,"The signature"));if(n.length!==2)throw new Error("The signature is not an ECDSA signature");let i=new Uint8Array(t*2);return n.forEach((s,o)=>{let a=v(m(s,2,"The signature"));if(a.length===0||a[0]&128)throw new Error("The signature is not an ECDSA signature");for(;a.length>1&&a[0]===0;)a=a.subarray(1);if(a.length>t)throw new Error("The signature is not an ECDSA signature");i.set(a,o*t+t-a.length)}),i}async function ye(r,e,t,n,i){let s;try{s=Kr(n,e)}catch{return!1}let o=await crypto.subtle.importKey("spki",r,{name:"ECDSA",namedCurve:e},!1,["verify"]);return crypto.subtle.verify({name:"ECDSA",hash:t},o,s,i)}function U(r,e){let t=r.replace(/\s+/g,"");if(!/^[A-Za-z0-9+/]*={0,2}$/.test(t)||t.length%4!==0)throw new Error(`${e} is not base64`);let n=atob(t),i=new Uint8Array(n.length);for(let s=0;s<n.length;s+=1)i[s]=n.charCodeAt(s);return i}function Le(r,e){let t=[...r.matchAll(/-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g)];if(t.length!==1||r.replace(t[0][0],"").trim()!=="")throw new Error(`${e} is not exactly one PEM certificate`);return U(t[0][1],e)}var Vr="2.5.29.17",Hr="2.5.29.37",Lr="1.3.6.1.5.5.7.3.3",Gr="1.3.6.1.4.1.57264.1.8",Fr="1.3.6.1.4.1.57264.1.1",jr=134,Qr=12,qr=48,Jr=new TextEncoder,Q=r=>new TextDecoder().decode(r);async function he(r,e,t,n){let{base64Signature:i,cert:s,rekorBundle:o}=Wr(e),a=o.Payload;if(n!==void 0&&n.trim()!==i.trim())throw new Error("The detached signature is not the one in the bundle");let c=U(i,"The bundle signature"),u=Le(Q(U(s,"The bundle certificate")),"The bundle certificate"),d=He(u),g=At.find(x=>x.logId===a.logID.toLowerCase());if(!g)throw new Error(`The bundle names Rekor log ${a.logID}, which the Sigstore trust root does not know`);let p=Jr.encode(`{"body":${JSON.stringify(a.body)},"integratedTime":${a.integratedTime},"logID":${JSON.stringify(a.logID)},"logIndex":${a.logIndex}}`);if(!await ye(U(g.publicKey,"The Rekor key"),"P-256","SHA-256",U(o.SignedEntryTimestamp,"The signed entry timestamp"),p))throw new Error("Rekor's signed entry timestamp does not verify: the log entry, its time or its index was altered");let f=a.integratedTime*1e3;if(!Ut(f,g.validFor))throw new Error(`Rekor log ${g.baseUrl} was not in use at ${re(f)}, when the entry says it was logged`);let b=Xr(a.body),N=R(new Uint8Array(await crypto.subtle.digest("SHA-256",r)));if(b.hash!==N)throw new Error("The file's SHA-256 is not the one Rekor logged: the file is not the one signed");if(!Ge(U(b.signature,"The logged signature"),c))throw new Error("The bundle's signature is not the one Rekor logged");let E=Le(Q(U(b.publicKey,"The logged certificate")),"The logged certificate");if(!Ge(E,u))throw new Error("The bundle's certificate is not the one Rekor logged");if(d.curve!=="P-256"||!await ye(d.spki,"P-256","SHA-256",c,r))throw new Error("The signature over the file does not verify with the bundle's certificate");return await Yr(d,f),Zr(d,t),{integratedTime:a.integratedTime}}async function Yr(r,e){if(!Pt(r,e))throw new Error(`The signing certificate was valid ${re(r.notBefore)} to ${re(r.notAfter)}, not at ${re(e)} when Rekor logged it`);let t=[];for(let n of wt){let i=n.certChain.map(o=>He(U(o,"A Fulcio certificate")));if(!await Rt(r,i[0]))continue;let s=await zr(i,n.validFor,e);if(!s)return;t.push(`${n.uri} (valid from ${n.validFor.start}): ${s}`)}throw new Error(t.length>0?`The signing certificate's CA is not trusted at ${re(e)}: ${t.join("; ")}`:"The signing certificate was not issued by a Fulcio CA in the Sigstore trust root")}async function zr(r,e,t){if(!Ut(t,e))return"the trust root says it was not issuing certificates then";for(let[n,i]of r.entries()){if(!Pt(i,t))return`its certificate ${n} was not valid then`;let s=r[n+1]??i;if(!await Rt(i,s))return`its certificate ${n} is not signed by the next`}}async function Rt(r,e){return Ge(r.issuer,e.subject)?ye(e.spki,e.curve,r.signatureHash,r.signature,r.tbs):!1}function Zr(r,e){let t=r.extensions.get(Vr);if(!t)throw new Error("The signing certificate names no identity");let n=A(m(j(t),qr,"The subject alternative name")),i=n.filter(u=>u.tag===jr).map(u=>Q(v(u)));if(i.length!==1||n.length!==1||i[0]!==e.identity)throw new Error(`The release was signed by ${JSON.stringify(i.length===1?i[0]:i)}, not by ${e.identity}`);let s=r.extensions.get(Gr),o=r.extensions.get(Fr),a=s?Q(v(m(j(s),Qr,"The OIDC issuer"))):o?Q(o):void 0;if(a!==e.issuer)throw new Error(`The signing certificate's OIDC issuer is ${a===void 0?"missing":JSON.stringify(a)}, not ${e.issuer}`);let c=r.extensions.get(Hr);if(!c||!Et(c).includes(Lr))throw new Error("The signing certificate is not for code signing")}function Wr(r){let e=r;if(typeof e=="string")try{e=JSON.parse(e)}catch{throw new Error("The bundle is not JSON")}let t=e,n=t?.rekorBundle?.Payload;if(!(typeof t?.base64Signature=="string"&&typeof t.cert=="string"&&typeof t.rekorBundle?.SignedEntryTimestamp=="string"&&typeof n?.body=="string"&&typeof n.logID=="string"&&/^[0-9a-fA-F]{64}$/.test(n.logID)&&Number.isSafeInteger(n.integratedTime)&&n.integratedTime>=0&&Number.isSafeInteger(n.logIndex)&&n.logIndex>=0))throw new Error("The bundle is not a cosign bundle with a Rekor entry");return t}function Xr(r){let e;try{e=JSON.parse(Q(U(r,"The logged entry")))}catch{throw new Error("The logged entry is not JSON")}let t=e?.spec?.data?.hash,n=e?.spec?.signature;if(e?.kind!=="hashedrekord"||t?.algorithm!=="sha256"||typeof t.value!="string"||typeof n?.content!="string"||typeof n.publicKey?.content!="string")throw new Error("The logged entry is not a SHA-256 hashedrekord");return{hash:t.value.toLowerCase(),signature:n.content,publicKey:n.publicKey.content}}function Pt(r,e){return r.notBefore<=e&&e<=r.notAfter}function Ut(r,e){return Date.parse(e.start)<=r&&(e.end===void 0||r<=Date.parse(e.end))}function re(r){return new Date(r).toISOString()}function Ge(r,e){return r.length===e.length&&r.every((t,n)=>t===e[n])}var en=/^[0-9a-f]{96}$/,tn=["mrtd","rtmr0","rtmr1","rtmr2","rtmr3"];function _(r){let e=q(r.allowedMrtd??[],"allowedMrtd"),t=(r.allowedMeasurements??[]).map((a,c)=>{let u=`allowedMeasurements[${c}]`;return tn.map(d=>q([a?.[d]??""],`${u}.${d}`)[0]).join()}),n=[q(r.allowedRtmr0??[],"allowedRtmr0"),q(r.allowedRtmr1??[],"allowedRtmr1"),q(r.allowedRtmr2??[],"allowedRtmr2"),q(r.allowedRtmr3??[],"allowedRtmr3")];if(r.allowedMeasurements!==void 0&&t.length===0)throw new Error("allowedMeasurements is empty, so no quote would ever be accepted");if(t.length===0){if(e.length===0)throw new Error("No image is trusted: give allowedMeasurements, or allowedMrtd with allowedRtmr1-3");if(n.slice(1).some(a=>a.length===0))throw new Error("allowedMrtd alone does not name an image: the MRTD measures the TD firmware, which images share, and the image is in RTMR1-3. Give allowedMeasurements, or allowedRtmr1-3 too")}let i=r.allowedTcbStatuses??["UpToDate"],s=r.now??Date.now;return Object.assign(async({quoteB64:a,nonce:c,reportDataSuffix:u,collateral:d})=>{let g=nn(a),p=d??await r.fetchCollateral?.(g);if(!p)throw new Error("The node sent no collateral for its quote, and no fetchCollateral was given to get it");let h;try{h=r.dcapVerify(g,p,Math.floor(s()/1e3))}catch(E){throw new Error(`The quote did not verify: ${E?.message??String(E)}`)}if(h.status==="Revoked"||!i.includes(h.status))throw new Error(`The platform's TCB status is ${h.status}, which is not accepted`);let f=rn(h.report);if(f.tdAttributes?.length!==8||(f.tdAttributes[0]&1)!==0)throw new Error("The quote is from a debug TD, or its TD attributes cannot be read");let b=[f.mrTd,f.rtMr0,f.rtMr1,f.rtMr2,f.rtMr3].map(E=>R(E));if(t.length>0&&!t.includes(b.join()))throw new Error(`The measurements (MRTD ${b[0]}, RTMR0-3 ${b.slice(1).join(", ")}) are not an image this verifier trusts`);if(e.length>0&&!e.includes(b[0]))throw new Error(`MRTD ${b[0]} is not an image this verifier trusts`);if([f.rtMr0,f.rtMr1,f.rtMr2,f.rtMr3].forEach((E,x)=>{let D=n[x];if(D.length>0&&!D.includes(R(E)))throw new Error(`RTMR${x} ${R(E)} is not one this verifier trusts`)}),R(f.reportData)!==`${c}${u}`.toLowerCase())throw new Error("The quote does not commit to this nonce and binding");return!0},{includeCollateral:!0})}function q(r,e){return r.map(t=>{let n=t.trim().toLowerCase();if(!en.test(n))throw new Error(`${e} holds ${JSON.stringify(t)}, which is not a 48-byte hex measurement`);return n})}function rn(r){let e=r.data;if(r.type==="td10"&&e)return e;if(r.type==="td15"&&e?.base)return e.base;throw new Error(`The quote is a ${r.type} quote, not a TDX one`)}function nn(r){let e=atob(r),t=new Uint8Array(e.length);for(let n=0;n<e.length;n+=1)t[n]=e.charCodeAt(n);return t}var sn=["UpToDate","SWHardeningNeeded","ConfigurationNeeded","ConfigurationAndSWHardeningNeeded","OutOfDate","OutOfDateConfigurationNeeded"],M="locked-read-only";function Fe(r,{profile:e,allowDebugProfile:t=!1}){if(r.length===0)throw new Error("No release given, so no image would be trusted");let n,i=r.map((s,o)=>{let a=s?.tag??`releases[${o}]`;if(s?.role!==void 0&&s.role!=="node")throw new Error(`${a} lists the measurements of a ${s.role}, not of a node image`);let c=s?.profiles?.[e];if(!c){let d=Object.keys(s?.profiles??{}).join(", ")||"none";throw new Error(`${a} has no profile ${JSON.stringify(e)} (it has: ${d})`)}if(e!==M&&!t)throw new Error(`${JSON.stringify(e)} is not a production profile: its image is readable by whoever operates the node. Trust ${JSON.stringify(M)}, or pass allowDebugProfile to test`);let u=(c.allowed_tcb_statuses??["uptodate"]).map(d=>on(d,a));return n=n===void 0?u:n.filter(d=>u.includes(d)),{mrtd:c.mrtd,rtmr0:c.rtmr0,rtmr1:c.rtmr1,rtmr2:c.rtmr2,rtmr3:c.rtmr3}});if(!n||n.length===0)throw new Error("The releases given accept no TCB status in common");return{allowedMeasurements:i,allowedTcbStatuses:n}}function on(r,e){let t=sn.find(n=>n.toLowerCase()===String(r).toLowerCase());if(!t)throw new Error(`${e} accepts TCB status ${JSON.stringify(r)}, which this verifier does not know`);return t}var je=Object.freeze({identity:"https://github.com/calimero-network/mero-tee/.github/workflows/release-node-image-gcp.yaml@refs/heads/master",issuer:"https://token.actions.githubusercontent.com"}),an=["mrtd","rtmr0","rtmr1","rtmr2","rtmr3"],Qe="https://cloud.calimero.network";async function Tt(r,e,t={}){let n=typeof r=="string"?new TextEncoder().encode(r):r;await he(n,e,{identity:t.identity??je.identity,issuer:t.issuer??je.issuer},t.signature);let i;try{i=JSON.parse(new TextDecoder().decode(n))}catch{throw new Error("The signed release is not JSON")}if(i?.role!=="node")throw new Error(`The signed release is a ${JSON.stringify(i?.role)} release, not a node one`);let s=Object.values(i.profiles??{}),o=a=>an.every(c=>/^[0-9a-f]{96}$/i.test(String(a?.[c])));if(typeof i.tag!="string"||s.length===0||!s.every(o))throw new Error("The signed file is not a release's published-mrtds.json: it lists no measured profiles");if(t.expectedVersion!==void 0&&i.tag!==t.expectedVersion)throw new Error(`The signed release is ${i.tag}, not ${t.expectedVersion}`);return i}async function qe(r,e={}){let t=await(e.fetch??fetch)(r,{headers:{accept:"application/json"}});if(!t.ok)throw new Error(`Fetching the node release from ${r} failed: HTTP ${t.status}`);let n;try{n=(await t.json())?.data}catch{throw new Error(`${r} did not answer with JSON`)}if(typeof n?.version!="string"||typeof n.publishedMrtds!="string"||typeof n.bundle!="string")throw new Error(`${r} did not answer with a signed node release`);return{version:n.version,publishedMrtds:n.publishedMrtds,bundle:n.bundle}}var St="https://github.com/calimero-network/mero-tee/releases/download";async function Je(r,e={}){let t=`mero-tee-v${k(r,"version")}`,n=`${(e.base??St).replace(/\/+$/,"")}/${t}/published-mrtds.json`,i=async a=>{let c=await(e.fetch??fetch)(a);if(!c.ok)throw new Error(`Fetching ${a} failed: HTTP ${c.status}`);return c.text()},[s,o]=await Promise.all([i(n),i(`${n}.bundle.json`)]);return{version:r,publishedMrtds:s,bundle:o}}function Ye(r,e){return`${r.replace(/\/+$/,"")}/api/tee/node-releases/${k(e,"version")}`}async function me(r){let e=k(r.minReleaseVersion,"minReleaseVersion"),t=k(r.release?.version,"The release version"),n=await Tt(r.release.publishedMrtds,r.release.bundle,{expectedVersion:t,identity:r.identity,issuer:r.issuer});if(ne(t,e)<0)throw new Error(`Release ${t} is older than the minimum trusted, ${e}`);return Fe([n],{profile:r.profile,allowDebugProfile:r.allowDebugProfile})}function cn(r){return k(r.minReleaseVersion,"minReleaseVersion"),Object.assign(async t=>{let n=await me({release:await r.release(),profile:r.profile,allowDebugProfile:r.allowDebugProfile,minReleaseVersion:r.minReleaseVersion,identity:r.identity,issuer:r.issuer});return _({dcapVerify:r.dcapVerify,fetchCollateral:r.fetchCollateral,now:r.now,...n})(t)},{includeCollateral:!0})}var vt=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function k(r,e){let t=typeof r=="string"?vt.exec(r):null,n=t?.[4];if(!t||n!==void 0&&n.split(".").some(i=>i===""))throw new Error(`${e} is ${JSON.stringify(r)}, not a release version like 2.3.87`);return r}function ne(r,e){let[t,n]=xt(r),[i,s]=xt(e);for(let c=0;c<3;c+=1)if(t[c]!==i[c])return t[c]<i[c]?-1:1;if(n===void 0||s===void 0)return n===s?0:n===void 0?1:-1;let o=n.split("."),a=s.split(".");for(let c=0;c<Math.max(o.length,a.length);c+=1){let[u,d]=[o[c],a[c]];if(u===void 0||d===void 0)return u===void 0?-1:1;let[g,p]=[/^\d+$/.test(u),/^\d+$/.test(d)],h=g&&p?Math.sign(Number(u)-Number(d)):g!==p?g?-1:1:u<d?-1:u>d?1:0;if(h!==0)return h}return 0}function xt(r){let e=vt.exec(r);return[[Number(e[1]),Number(e[2]),Number(e[3])],e[4]]}var It="MOCK_TDX_QUOTE_V1";function ln(r){let e=atob(r),t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function ze(r,e){if(r.length!==e.length)return!1;let t=0;for(let n=0;n<r.length;n++)t|=r[n]^e[n];return t===0}var kt;async function Ct(r){kt??(kt=import("@phala/dcap-qvl"));let e=await kt,t=typeof e[r]=="function"?e[r]:e.default?.[r];if(typeof t!="function")throw new TypeError(`@phala/dcap-qvl loaded without ${r}`);return t}function Ot(r,e){let t=k(e,"minReleaseVersion"),n=String(r.release?.version??"").trim().replace(/^mero-tee-v/,"").replace(/^v/,""),i=k(n,"The release the node names");if(ne(i,t)<0)throw new Error(`mero-tee release ${i} is older than the minimum ${t}`);return i}async function un(r,e,t){let n=e.releaseSource;return typeof n=="function"?n(r):n==="github"?Je(r,{fetch:t}):qe(Ye(n??Qe,r),{fetch:t})}async function dn(r,e,t,n){let i=Ot(r,t.minReleaseVersion),s=await me({release:await un(i,t,n),profile:t.profile??M,allowDebugProfile:t.allowDebugProfile,minReleaseVersion:t.minReleaseVersion,identity:t.identity,issuer:t.issuer}),o=t.fetchCollateral??(async c=>(await Ct("getCollateralFromPcs"))(c));return _({dcapVerify:t.dcapVerify??await Ct("verify"),fetchCollateral:o,now:t.now,...s})(e)}async function Ze(r,e,t=(n,i)=>fetch(n,i)){let n=R(crypto.getRandomValues(new Uint8Array(32))),i=new URL(`${r.replace(/\/+$/,"")}/attestation`);i.searchParams.set("nonce",n),e.appHash&&i.searchParams.set("appHash",e.appHash);let s=await t(i.toString());if(!s.ok)throw new Error(`The node refused to attest: HTTP ${s.status}`);let o=await s.json(),a=pe(o.transportKey,"transportKey",32),c=e.appHash?pe(e.appHash,"appHash",32):new Uint8Array(32),u=await Ke(c,a),d=ln(o.quote),g=new TextEncoder().encode(It);if(ze(d.slice(0,g.length),g)){if(!e.allowMock)throw new Error("mock quote refused: this client only trusts real TEEs");let f=d.slice(g.length,g.length+64);if(!ze(f.slice(0,32),pe(n,"nonce",32))||!ze(f.slice(32),u))throw new Error("the quote does not bind this transport key, app and nonce");return a}let p={quoteB64:o.quote,nonce:n,reportDataSuffix:R(u)},h;if(e.verifyQuote)h=await e.verifyQuote(p);else if(e.release)h=await dn(o,p,e.release,t);else throw new Error("real quote refused: this client trusts no TD image (set policy.release)");if(!h)throw new Error("The attestation did not verify, so its transport key is not trusted");return a}var w=class extends Error{constructor(t,n,i,s={}){super(`${t} ${n}: ${i}`);this.status=t;this.code=n;this.details=s;this.name="CalimeroError"}},J=class extends w{constructor(e,t={}){super(401,"UNAUTHENTICATED",e,t),this.name="LoginRequired"}},$=class extends w{constructor(e,t={}){super(421,"WRONG_NODE",e,t),this.name="WrongNode"}},we=class extends w{constructor(e,t={}){super(404,"NOT_FOUND",e,t),this.name="NotFound"}},Y=class extends w{constructor(e,t={}){super(412,"CONFIRM_REQUIRED",e,t),this.name="ConfirmRequired"}},ie=class extends Error{constructor(t){super("the passkey confirmation was cancelled");this.cause=t;this.name="ConfirmCancelled"}},Ae=class extends w{constructor(e,t={}){super(413,"ARGS_TOO_LARGE",e,t),this.name="ArgsTooLarge"}},be=class extends w{constructor(e,t={}){super(409,"IDEMPOTENCY_MISMATCH",e,t),this.name="IdempotencyMismatch"}},Ee=class extends w{constructor(e,t={}){super(409,"RELEASE_DEADLINE",e,t),this.name="ReleaseDeadlineError",this.release=typeof t.release=="string"?t.release:"",this.after=typeof t.after=="string"?t.after:""}},Re=class extends w{constructor(e,t={}){super(409,"CONSENT_STALE",e,t),this.name="ConsentStale"}},Pe=class extends w{constructor(e,t={}){super(422,"APP_ERROR",e,t),this.name="AppError";let{appCode:n,fields:i}=gn(t);this.appCode=n,this.fields=i}},Ue=class extends w{constructor(e,t={}){super(422,"TRAP",e,t),this.name="TrapError",this.kind=typeof t.kind=="string"?t.kind:""}},B=class extends w{constructor(e,t,n={},i,s){super(503,e,t,n),this.name="UnavailableError",this.reason=e.toLowerCase(),this.committed=e==="TIMEOUT"||e==="MIGRATING"?!1:"unknown",this.retryAfter=i,this.cause=s}};function xe(r){return r&&typeof r=="object"&&!Array.isArray(r)?r:{}}function gn(r){let e=typeof r.code=="string"?r:xe(r.error);return{appCode:typeof e.code=="string"?e.code:"",fields:{...xe(e.fields)}}}function pn(r,e){for(let t of[r.retryAfter,e==null?void 0:Number(e)])if(typeof t=="number"&&Number.isFinite(t)&&t>=0)return t}function Te(r,e,t){let n=xe(e),i=typeof n.error=="string"?n.error:"ERROR",s=typeof n.message=="string"?n.message:"",o=xe(n.details);if(r===503)return new B(i,s,o,pn(o,t));switch(`${r} ${i}`){case"401 UNAUTHENTICATED":return new J(s,o);case"421 WRONG_NODE":return new $(s,o);case"404 NOT_FOUND":return new we(s,o);case"409 IDEMPOTENCY_MISMATCH":return new be(s,o);case"409 RELEASE_DEADLINE":return new Ee(s,o);case"409 CONSENT_STALE":return new Re(s,o);case"412 CONFIRM_REQUIRED":return new Y(s,o);case"413 ARGS_TOO_LARGE":return new Ae(s,o);case"422 APP_ERROR":return new Pe(s,o);case"422 TRAP":return new Ue(s,o);default:return new w(r,i,s,o)}}function T(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function C(r){let e=r.replace(/-/g,"+").replace(/_/g,"/")+"===".slice((r.length+3)%4),t=atob(e),n=new Uint8Array(t.length);for(let i=0;i<t.length;i++)n[i]=t.charCodeAt(i);return n}var se=r=>r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);function Nt(r){let e=new Error(r);return e.name="NotAllowedError",e}function fn(){return{async create(r){let e=r,t=await navigator.credentials.create({publicKey:{challenge:se(C(e.challenge)),rp:e.rp,user:{...e.user,id:se(C(e.user.id))},pubKeyCredParams:e.pubKeyCredParams,excludeCredentials:(e.excludeCredentials??[]).map(i=>({type:i.type,id:se(C(i.id))})),authenticatorSelection:e.authenticatorSelection,attestation:"none",timeout:e.timeout}});if(!t)throw Nt("passkey creation was cancelled");let n=t.response;return{attestationObject:T(new Uint8Array(n.attestationObject)),clientDataJson:T(new Uint8Array(n.clientDataJSON))}},async get(r,e,t){let n=await navigator.credentials.get({publicKey:{challenge:se(r),rpId:e,userVerification:"preferred",allowCredentials:(t??[]).map(s=>({type:"public-key",id:se(C(s))}))}});if(!n)throw Nt("passkey sign-in was cancelled");let i=n.response;return{credentialId:T(new Uint8Array(n.rawId)),authenticatorData:T(new Uint8Array(i.authenticatorData)),clientDataJson:T(new Uint8Array(i.clientDataJSON)),signature:T(new Uint8Array(i.signature))}}}}var We=100;function ae(r={}){let e=new URLSearchParams;if(r.after!==void 0&&e.set("after",r.after),r.limit!==void 0){if(!Number.isInteger(r.limit)||r.limit<1||r.limit>We)throw new RangeError(`limit is 1 to ${We}`);e.set("limit",String(r.limit))}let t=e.toString();return t?`?${t}`:""}function oe(r,e){try{return ne(r,e)}catch{return r<e?-1:r>e?1:0}}function Dt(r,e,t=Date.now()/1e3){if(r===null||r.length===0)return null;let n=r.reduce((s,o)=>oe(s,o)>=0?s:o),i=null;for(let s of e)s.afterSecs<=t&&oe(n,s.version)<0&&(i===null||oe(s.version,i.version)>0)&&(i=s);return i}function Mt(r,e,t,n){return`calimero-publisher-binding/v1
|
|
2
2
|
${r}
|
|
3
3
|
${e}
|
|
4
4
|
${t}
|
|
5
|
-
${n}`}function
|
|
5
|
+
${n}`}function yn(r,e,t,n){return new TextEncoder().encode(Mt(r,e,t,n))}var hn="0123456789ABCDEFGHJKMNPQRSTVWXYZ";async function Xe(r){let e=new Uint8Array(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(r))),t=(e[0]<<24|e[1]<<16|e[2]<<8|e[3])>>>0,n="";for(let i=0;i<6;i++)i===3&&(n+="-"),n+=hn[t>>>27-5*i&31];return n}function mn(r){let e=typeof r=="string"?new URL(r):r,t=e.searchParams.get("request_id"),n=e.searchParams.get("result");return!t||n!=="approved"&&n!=="declined"?null:{requestId:t,result:n}}var _t="https://mero-tee.vercel.app";function $t(r){return`https://github.com/calimero-network/mero-tee/releases/tag/mero-tee-v${encodeURIComponent(r)}`}function Bt(r){return`${_t}/mero-tee?release_tag=${encodeURIComponent(`mero-tee-v${r}`)}`}function et(r,e,t=Date.now()/1e3){let n=c=>e.deadlines.find(u=>u.version===c)??null,i=r.governance.releases==="owner",s=r.governance.appUpgrades==="owner",o=r.clusterReleases.filter(c=>!c.approved).sort((c,u)=>oe(u.release,c.release)).map(c=>({version:c.release,nodes:c.nodes,actionable:i,releaseNotesUrl:$t(c.release),verifyUrl:Bt(c.release),deadline:n(c.release)})),a=[];for(let c of r.apps){let u=c.availableVersions??[];c.package===null||u.length===0||a.push({app:c.app,name:c.name??null,package:c.package.package,from:c.package.version,to:u[u.length-1],available:u,actionable:s})}return{scope:r.scope,governance:r.governance,approvedReleases:r.approvedReleases,releases:o,upgrades:a,stalledBy:Dt(r.approvedReleases,e.deadlines,t),actionable:o.some(c=>c.actionable)||a.some(c=>c.actionable)}}function Kt(r,e,t,n={}){return{kind:"release",scope:r.kind==="org"?{org:r.org}:"account",subject:n.withdraw?{version:e,withdraw:!0}:{version:e},returnTo:t}}function wn(r,e,t){return Kt(r,e,t,{withdraw:!0})}function An(r,e,t){return{kind:"upgrade",subject:{app:r,toVersion:e},returnTo:t}}function l(r){return encodeURIComponent(r)}function bn(r){return r instanceof S&&r.status===413?Te(413,{error:"TOO_LARGE",message:r.message.replace(/^Sealed request refused: /,"")}):r}async function Vt(r){let e=await r.text().catch(()=>""),t={};try{t=e?JSON.parse(e):{}}catch{t={message:e}}return Te(r.status,t,r.headers.get("retry-after"))}async function*En(r){let e=r.getReader(),t=new TextDecoder,n="";for(;;){let{value:i,done:s}=await e.read();if(s)return;n+=t.decode(i,{stream:!0});let o;for(;(o=n.indexOf(`
|
|
6
6
|
|
|
7
7
|
`))>=0;){let a=n.slice(0,o);n=n.slice(o+2);let c="",u="",d="";for(let p of a.split(`
|
|
8
|
-
`))p.startsWith("id:")?c=p.slice(3).trim():p.startsWith("event:")?u=p.slice(6).trim():p.startsWith("data:")&&(d+=p.slice(5).trim());if(!u&&!d)continue;let g=d;try{g=JSON.parse(d)}catch{}yield{id:c,kind:u,data:g}}}}function Vt(r){return Array.from(r,e=>e.toString(16).padStart(2,"0")).join("")}function Lt(){return`node:c-${T(crypto.getRandomValues(new Uint8Array(16)))}`}var bn={retries:6,baseDelayMs:200,maxDelayMs:2e3};function En(r,e){return Math.min(e.baseDelayMs*2**r,e.maxDelayMs)}function Ht(r){return r==="auth/refresh"||r.startsWith("auth/passkey/")}var et=class{constructor(e){this.at=0;this.channels=new Map;this.networkFailures=new WeakSet;let t=s=>s.replace(/\/+$/,"");this.nodeUrls=[...new Set([e.baseUrl,...e.nodes??[]].map(t))],this.policy=e.policy,this.retry={...bn,...e.retry};let n=e.fetch??((s,o)=>fetch(s,o)),i=async(s,o)=>{try{return await n(s,o)}catch(a){throw a instanceof TypeError&&this.networkFailures.add(a),a}};this.raw=i}get nodeUrl(){return this.nodeUrls[this.at]}channel(e){let t=this.channels.get(e);return t||(t=Ve({baseUrl:e,transportPublicKey:()=>Ze(e,this.policy,this.raw),fetch:this.raw}),this.channels.set(e,t)),t}moveOn(e){return this.nodeUrls.length<2?!1:(this.at===e&&(this.at=(e+1)%this.nodeUrls.length),!0)}useApiKey(e){this.auth=e,this.current=void 0}useSession(e){this.auth=e.sessionToken,this.current=e}get session(){return this.current}async request(e,t,n,i,s="application/wasm",o){let a={};this.auth&&(a.authorization=`Bearer ${this.auth}`);let c;i?(a["content-type"]=s,c=i):n!==void 0&&(a["content-type"]="application/json",c=JSON.stringify(n));let u=this.nodeUrl;try{return await this.channel(u)(`${u}/${t}`,{method:e,headers:a,body:c,signal:o})}catch(d){throw wn(d)}}async send(e,t,n,i,s,o){let a=!1,c=!1;for(;;){let[u,d]=[this.auth,this.at],g=await this.request(e,t,n,i,s,o);if(g.ok)return g;let p=await Kt(g);if(p instanceof $&&!c){if(c=!0,this.moveOn(d)&&!Ht(t))continue}else if(p instanceof J&&!a&&this.mayRefresh(u,t)){a=!0,await this.renew(u);continue}throw p}}mayRefresh(e,t){return e!==void 0&&this.current!==void 0&&!Ht(t)}async renew(e){this.auth===e&&await this.refresh()}async json(e,t,n,i,s){let a=await(await this.send(e,t,n,i,s)).text();return a?JSON.parse(a):{}}async retried(e,t,n,i=this.retry.retries){for(let s=0;;s++){let o;try{return await this.json(e,t,n)}catch(c){if(c instanceof B)o=c;else if(c instanceof TypeError&&this.networkFailures.has(c))o=new B("NETWORK",`the node could not be reached: ${c.message}`,{},void 0,c);else throw c}if(s>=i)throw o;let a=En(s,this.retry);await new Promise(c=>setTimeout(c,Math.max(a,(o.retryAfter??0)*1e3)))}}post(e,t={}){return this.json("POST",e,t)}get(e){return this.json("GET",e)}put(e,t={}){return this.json("PUT",e,t)}delete(e,t){return this.json("DELETE",e,t)}async signUp(e,t){let n=await this.post("auth/passkey/register/begin",{name:t}),i=await e.create(n.options),s=await this.post("auth/passkey/register/finish",{challengeId:n.challengeId,registration:i});return this.useSession(s),s}async signIn(e){let t=await this.post("auth/passkey/login/begin"),n=await e.get(C(t.options.challenge),t.options.rpId),i=await this.post("auth/passkey/login/finish",{challengeId:t.challengeId,assertion:n});return this.useSession(i),i}refresh(){if(!this.refreshing){let e=this.exchangeRefresh();this.refreshing=e;let t=()=>{this.refreshing===e&&(this.refreshing=void 0)};e.then(t,t)}return this.refreshing}async exchangeRefresh(){let e=this.current;if(!e)throw new Error("no session to refresh");let t;for(let n=1;t===void 0;n++)try{t=await this.post("auth/refresh",{refreshToken:e.refreshToken})}catch(i){if(!(i instanceof $)||n>=this.nodeUrls.length)throw i}return this.current===e&&this.useSession(t),t}async signOut(){await this.post("auth/logout"),this.auth=void 0,this.current=void 0}async signOutEverywhere(){await this.post("auth/logout-all"),this.auth=void 0,this.current=void 0}me(){return this.get("auth/me")}async addPasskey(e){let t=await this.post("auth/passkeys/add/begin"),n=await e.create(t.options),{credentialId:i}=await this.post("auth/passkeys/add/finish",{challengeId:t.challengeId,registration:n});return i}async removePasskey(e){await this.delete(`auth/passkeys/${l(e)}`)}async labelPasskey(e,t){await this.post(`auth/passkeys/${l(e)}`,{label:t})}usage(){return this.get("auth/usage")}async attestation(){let e=Vt(crypto.getRandomValues(new Uint8Array(32))),t=await this.raw(`${this.nodeUrl}/attestation?nonce=${e}`);if(!t.ok)throw await Kt(t);return await t.json()}async listApiKeys(){let{keys:e}=await this.get("auth/apikeys");return e}async revokeApiKey(e){await this.delete(`auth/apikeys/${l(e)}`)}createApiKey(e){return this.post("auth/apikeys",e)}async uploadBundle(e){let{hash:t}=await this.json("POST","bundles",void 0,e);return t}uploadBlob(e,t){return this.json("POST",`apps/${l(e)}/blobs`,void 0,t)}async downloadBlob(e,t){let n=await this.send("GET",`apps/${l(e)}/blobs/${l(t)}`);return new Uint8Array(await n.arrayBuffer())}async listBlobs(e){let{blobs:t}=await this.get(`apps/${l(e)}/blobs`);return t}blobInfo(e,t){return this.get(`apps/${l(e)}/blobs/${l(t)}/info`)}async deleteBlob(e,t){await this.delete(`apps/${l(e)}/blobs/${l(t)}`)}uploadPackage(e){return this.json("POST","packages",void 0,e,"application/octet-stream")}installPackage(e,t){return this.post("packages/install",{package:e,version:t})}async packages(){let{packages:e}=await this.get("packages");return e}package(e){return this.get(`packages/${l(e)}`)}uninstallPackage(e,t){return this.delete(t===void 0?`packages/${l(e)}`:`packages/${l(e)}/${l(t)}`)}async listApps(e={}){let t=new URLSearchParams;e.package&&t.set("package",e.package),e.bundle&&t.set("bundle",e.bundle);let n=t.toString(),{apps:i}=await this.get(n?`apps?${n}`:"apps");return i}getApp(e){return this.get(`apps/${l(e)}`)}async deleteApp(e){await this.delete(`apps/${l(e)}`)}async setAccess(e,t){await this.post(`apps/${l(e)}/access`,{access:t})}async setAppMetadata(e,t){await this.post(`apps/${l(e)}/metadata`,{metadata:t})}appStorage(e){return this.get(`apps/${l(e)}/storage`)}appAbi(e){return this.get(`apps/${l(e)}/abi`)}async transferApp(e,t,n){await this.postConfirmed(`apps/${l(e)}/transfer`,{to:t},n)}upgradeApp(e,t,n){let i=`apps/${l(e)}/upgrade`;return n?this.postConfirmed(i,t,n):this.post(i,t)}postConfirmed(e,t,n){return this.confirmed("POST",e,t,n)}deleteConfirmed(e,t,n={}){return this.confirmed("DELETE",e,n,t)}async confirmed(e,t,n,i,s=o=>this.json(e,t,o)){try{return await s(n)}catch(o){if(!(o instanceof z))throw o;let a=o.details,c;try{c=await i.get(C(a.challenge),a.rpId,a.allowCredentials)}catch(u){let d=u?.name;throw d==="NotAllowedError"||d==="AbortError"?new ie(u):u}return s({...n,confirm:{challengeId:a.challengeId,assertion:c}})}}async createApp(e,t,n={}){let i=typeof t=="string"?{bundle:t}:t,{appId:s}=await this.post("apps",{name:e,...i,...n});return s}call(e,t,n={},i){let s=i??Lt();return this.retried("POST",`apps/${l(e)}/intents`,{method:t,args:n,idempotencyKey:s})}async callConfirmed(e,t,n,i,s){let o=`apps/${l(e)}/intents`,a=s??Lt();return this.confirmed("POST",o,{method:t,args:n,idempotencyKey:a},i,c=>this.retried("POST",o,c,c.confirm===void 0?this.retry.retries:0))}view(e,t,n={},i={}){return this.retried("POST",`apps/${l(e)}/views`,{method:t,args:n,consistency:i.stale?"stale":"strong",minIndex:i.minIndex??0})}events(e,t=0,n){return this.stream(`apps/${l(e)}/events?from=${t}`,n)}async*stream(e,t){let n=await this.send("GET",e,void 0,void 0,void 0,t);if(!n.body)throw new w(n.status,"EVENTS","the event stream has no body");yield*An(n.body)}async publishPresence(e,t,n){await this.post(`apps/${l(e)}/presence`,{seq:t,state:n===null?null:Vt(n)})}async presence(e){let{present:t}=await this.get(`apps/${l(e)}/presence`);return t}presenceStream(e,t){return this.stream(`apps/${l(e)}/presence/stream`,t)}async setAlias(e,t){await this.put(`auth/aliases/${l(e)}`,{app:t})}async aliases(){let{aliases:e}=await this.get("auth/aliases");return e}async alias(e){let{appId:t}=await this.get(`auth/aliases/${l(e)}`);return t}async deleteAlias(e){await this.delete(`auth/aliases/${l(e)}`)}async createOrg(e){let{orgId:t}=await this.post("orgs",{name:e});return t}getOrg(e){return this.get(`orgs/${l(e)}`)}async deleteOrg(e,t){await this.deleteConfirmed(`orgs/${l(e)}`,t)}async setOrgMetadata(e,t){await this.post(`orgs/${l(e)}/metadata`,{metadata:t})}async setMemberMetadata(e,t,n){await this.post(`orgs/${l(e)}/members/${l(t)}/metadata`,{metadata:n})}upgradeOrg(e,t,n){return this.postConfirmed(`orgs/${l(e)}/upgrade`,{...t},n)}upgradeRun(e,t){return this.get(`orgs/${l(e)}/upgrades/${l(t)}`)}retryUpgradeRun(e,t,n){return this.postConfirmed(`orgs/${l(e)}/upgrades/${l(t)}/retry`,{},n)}async approveRelease(e,t,n,i=!0){let s=e===null?"auth/releases":`orgs/${l(e)}/releases`;return this.postConfirmed(s,{version:t,approved:i},n)}async approveOutbound(e,t,n,i={}){let s=e===null?"auth/outbound":`orgs/${l(e)}/outbound`;return this.postConfirmed(s,{package:t,prefixes:i.prefixes??"manifest",replace:i.replace??!1},n)}appsReport(e,t={}){let n=e===null?"auth/apps":`orgs/${l(e)}/apps`;return this.get(`${n}${ae(t)}`)}async appsReportAll(e){let t=await this.appsReport(e),n=[...t.apps],i=t.next;for(;i!==null;){let s=await this.appsReport(e,{after:i});n.push(...s.apps),i=s.next}return{...t,apps:n,next:null}}releaseRules(){return this.get("releases")}async pendingApprovals(e=null){let[t,n]=await Promise.all([this.appsReportAll(e),this.releaseRules()]);return Xe(t,n)}requestConsent(e){return this.post("consent/requests",e)}async openConsentPage(e,t=n=>{let i=globalThis.window;if(!i)throw new Error("no window to open the consent page in; pass `navigate`");i.location.assign(n)}){let n=await this.requestConsent(e);return t(n.url),n}consentResult(e){return this.get(`consent/${l(e)}/result`)}async waitForConsent(e,t={}){let n=t.intervalMs??2e3;for(;;){let i=await this.consentResult(e);if(i.status!=="pending"||t.signal?.aborted||t.expiresAt!==void 0&&Date.now()/1e3>=t.expiresAt)return i;await new Promise(s=>setTimeout(s,n))}}publisherBinding(e){return this.get(`publishers/${l(e)}`)}bindPublisher(e,t,n){return this.postConfirmed(`orgs/${l(e)}/publishers`,{...t},n)}upgradePublished(e,t,n,i){return this.postConfirmed(`orgs/${l(e)}/packages/${l(t)}/upgrade`,{...n},i)}opsApps(e={}){return this.get(`ops/apps${ae(e)}`)}opsOrgs(e={}){return this.get(`ops/orgs${ae(e)}`)}async setReleaseDeadline(e,t){let n=typeof t=="string"?t:t.toISOString();await this.post(`ops/releases/${l(e)}/deadline`,{after:n})}async liftReleaseDeadline(e){await this.delete(`ops/releases/${l(e)}/deadline`)}async setMember(e,t,n){await this.post(`orgs/${l(e)}/members`,{account:t,role:n})}removeMember(e,t){return this.delete(`orgs/${l(e)}/members/${l(t)}`)}async setCapabilities(e,t,n={}){await this.post(`orgs/${l(e)}/capabilities`,{capabilities:t,...n})}async createTeam(e,t,n,i){let{teamId:s}=await this.post(`orgs/${l(e)}/teams`,{name:t,join:n,parent:i});return s}getTeam(e,t){return this.get(`orgs/${l(e)}/teams/${l(t)}`)}async updateTeam(e,t,n){await this.post(`orgs/${l(e)}/teams/${l(t)}`,n)}async deleteTeam(e,t){await this.delete(`orgs/${l(e)}/teams/${l(t)}`)}async setTeamMember(e,t,n,i={}){await this.post(`orgs/${l(e)}/teams/${l(t)}/members`,{account:n,...i})}async removeTeamMember(e,t,n){await this.delete(`orgs/${l(e)}/teams/${l(t)}/members/${l(n)}`)}async invite(e,t,n=[],i={}){let{token:s}=await this.post(`orgs/${l(e)}/invites`,{role:t,teams:n,...i});return s}redeemInvite(e){return this.post(`invites/${l(e)}/redeem`)}};var tt={CREATE_APP:1,INVITE_MEMBERS:2,JOIN_OPEN_TEAMS:4,MANAGE_MEMBERS:8,MANAGE_APPLICATION:16,CREATE_TEAM:32,DELETE_TEAM:64,MANAGE_VISIBILITY:128,MANAGE_METADATA:256,APPROVE_RELEASES:1024},Rn=tt.JOIN_OPEN_TEAMS;function Pn(...r){return r.reduce((e,t)=>e|tt[t],0)}function Se(r,e){return(r<<e|r>>>32-e)>>>0}function I(r,e,t,n,i){r[e]=r[e]+r[t]>>>0,r[i]=Se(r[i]^r[e],16),r[n]=r[n]+r[i]>>>0,r[t]=Se(r[t]^r[n],12),r[e]=r[e]+r[t]>>>0,r[i]=Se(r[i]^r[e],8),r[n]=r[n]+r[i]>>>0,r[t]=Se(r[t]^r[n],7)}function Gt(r,e){return(r[e]|r[e+1]<<8|r[e+2]<<16|r[e+3]<<24)>>>0}function Qt(r,e,t){let n=new Uint32Array(16);n[0]=1634760805,n[1]=857760878,n[2]=2036477234,n[3]=1797285236;for(let o=0;o<8;o+=1)n[4+o]=Gt(r,o*4);n[12]=e>>>0;for(let o=0;o<3;o+=1)n[13+o]=Gt(t,o*4);let i=n.slice();for(let o=0;o<10;o+=1)I(i,0,4,8,12),I(i,1,5,9,13),I(i,2,6,10,14),I(i,3,7,11,15),I(i,0,5,10,15),I(i,1,6,11,12),I(i,2,7,8,13),I(i,3,4,9,14);let s=new Uint8Array(64);for(let o=0;o<16;o+=1){let a=i[o]+n[o]>>>0;s[o*4]=a&255,s[o*4+1]=a>>>8&255,s[o*4+2]=a>>>16&255,s[o*4+3]=a>>>24&255}return s}function Un(r,e,t,n){let i=new Uint8Array(n.length);for(let s=0,o=e;s<n.length;s+=64,o+=1){let a=Qt(r,o,t),c=Math.min(s+64,n.length);for(let u=s;u<c;u+=1)i[u]=n[u]^a[u-s]}return i}function rt(r){let e=0n;for(let t=r.length-1;t>=0;t-=1)e=e<<8n|BigInt(r[t]);return e}var xn=(1n<<130n)-5n;function Tn(r,e){let t=rt(r.subarray(0,16))&0x0ffffffc0ffffffc0ffffffc0fffffffn,n=rt(r.subarray(16,32)),i=0n;for(let a=0;a<e.length;a+=16){let c=e.subarray(a,Math.min(a+16,e.length)),u=rt(c)+(1n<<BigInt(8*c.length));i=(i+u)*t%xn}let s=i+n&(1n<<128n)-1n,o=new Uint8Array(16);for(let a=0;a<16;a+=1)o[a]=Number(s&0xffn),s>>=8n;return o}function Ft(r){return new Uint8Array((16-r%16)%16)}function jt(r){let e=new Uint8Array(8);return new DataView(e.buffer).setBigUint64(0,BigInt(r),!0),e}function Sn(r,e){let t=[r,Ft(r.length),e,Ft(e.length),jt(r.length),jt(e.length)],n=new Uint8Array(t.reduce((s,o)=>s+o.length,0)),i=0;for(let s of t)n.set(s,i),i+=s.length;return n}function vn(r,e){if(r.length!==32)throw new Error("ChaCha20-Poly1305 needs a 32-byte key");if(e.length!==12)throw new Error("ChaCha20-Poly1305 needs a 12-byte nonce")}function qt(r,e,t,n=new Uint8Array(0)){vn(r,e);let i=Qt(r,0,e).subarray(0,32),s=Un(r,1,e,t),o=Tn(i,Sn(n,s)),a=new Uint8Array(s.length+16);return a.set(s),a.set(o,s.length),a}var zt=32,kn=1,Cn=3,In=2,On=32,Nn=32,Dn=12,Y=r=>new TextEncoder().encode(r),le=r=>new Uint8Array([r>>8&255,r&255]),Jt=y(Y("KEM"),le(zt)),ce=y(Y("HPKE"),le(zt),le(kn),le(Cn));async function Yt(r,e){let t=r.length===0?new Uint8Array(32):r,n=await crypto.subtle.importKey("raw",t,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return new Uint8Array(await crypto.subtle.sign("HMAC",n,e))}async function Mn(r,e,t){let n=new Uint8Array(t),i=new Uint8Array(0);for(let s=1,o=0;o<t;s+=1)i=await Yt(r,y(i,e,new Uint8Array([s]))),n.set(i.subarray(0,Math.min(i.length,t-o)),o),o+=i.length;return n}function ve(r,e,t,n){return Yt(e,y(Y("HPKE-v1"),r,Y(t),n))}function nt(r,e,t,n,i){return Mn(e,y(le(i),Y("HPKE-v1"),r,Y(t),n),i)}async function _n(r,e){let t=await ve(Jt,new Uint8Array(0),"eae_prk",r);return nt(Jt,t,"shared_secret",e,On)}async function $n(r,e){let t=new Uint8Array(0),n=await ve(ce,t,"psk_id_hash",t),i=await ve(ce,t,"info_hash",e),s=y(new Uint8Array([In]),n,i),o=await ve(ce,r,"secret",t);return{key:await nt(ce,o,"key",s,Nn),nonce:await nt(ce,o,"base_nonce",s,Dn)}}async function Zt(r,e,t,n,i=new Uint8Array(0),s){if(r.length!==32)throw new Error("The recipient key is not 32 bytes of X25519");let o=await G(s),a=await G(e),c=y(await W(o.privateKey,r),await W(a.privateKey,r)),u=await _n(c,y(o.publicKey,r,a.publicKey)),{key:d,nonce:g}=await $n(u,t);return{enc:o.publicKey,ciphertext:qt(d,g,n,i)}}var er="mero-agent-gate/attest/v3",tr="mero-agent-gate/provision/v2",Bn=/^[a-z0-9][a-z0-9-]{0,62}$/,Kn=/^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/,Wt=64,Xt=64*1024,O=class extends Error{constructor(t,n,i){super(t);this.status=n;this.code=i;this.name="AgentGateError"}};function rr(r){if(!Bn.test(r))throw new Error(`Agent id ${JSON.stringify(r)} must match [a-z0-9][a-z0-9-]{0,62}`)}function ue(r){return new TextEncoder().encode(r)}function nr(r){let e=ue(r);return y(new Uint8Array([e.length]),e)}function K(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e)}function ke(r,e,t){let n;try{n=Uint8Array.from(atob(r.trim()),i=>i.charCodeAt(0))}catch{throw new Error(`${e} is not base64`)}if(t!==void 0&&n.length!==t)throw new Error(`${e} is not ${t} bytes`);return n}async function ir(r,e,t,n){let i=new Uint8Array(32),s=y(ue(er),r,nr(e),t??i,n??i);return new Uint8Array(await crypto.subtle.digest("SHA-256",s))}function sr(r,e){return y(ue(tr),r,nr(e))}async function Vn(){let r=crypto.getRandomValues(new Uint8Array(32));return{secret:r,publicKey:await Ce(r)}}async function Ce(r){if(r.length!==32)throw new Error("An owner key is 32 bytes");return K((await G(r)).publicKey)}function or(r,e){return`${r.replace(/\/+$/,"")}${e}`}async function ar(r,e,t){let n=await r(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)}),i=await n.text(),s;try{s=i?JSON.parse(i):void 0}catch{}if(!n.ok){let o=s;throw new O(`The gate answered ${n.status}${o?.error?` ${o.error}`:""}: ${o?.details??i.slice(0,200)}`,n.status,o?.error)}return s}async function it(r){let e=r.agentId??"";e&&rr(e);let t=crypto.getRandomValues(new Uint8Array(32)),n=await ar(r.fetch??fetch,or(r.gateUrl,"/attest"),{nonceB64:K(t),...e?{agentId:e}:{}});if((n?.agentId??"")!==e)throw new Error(`Asked about agent ${JSON.stringify(e)}, the gate answered for ${JSON.stringify(n?.agentId)}`);let i=ke(n.provisioningPublicKeyB64??"","provisioningPublicKeyB64",32),s=n.signingPublicKeyB64?ke(n.signingPublicKeyB64,"signingPublicKeyB64",32):void 0,o=n.ownerPublicKeyB64?ke(n.ownerPublicKeyB64,"ownerPublicKeyB64",32):void 0;if(!s!=!o)throw new Error("A claimed agent has both a signing key and an owner; the gate named one");let a=await ir(i,e,s,o);return await r.verifier({quoteB64:n.quoteB64,nonce:R(t),reportDataSuffix:R(a)}),{agentId:e,provisioningPublicKey:K(i),...s?{signingPublicKey:K(s)}:{},...o?{ownerPublicKey:K(o)}:{}}}async function cr(r,e){let t=await Ce(e);if(r.ownerPublicKey&&r.ownerPublicKey!==t)throw new O(`This agent is claimed by another key (${r.ownerPublicKey}); it is not yours. Send it nothing and do not authorize its signing key`,void 0,"not_yours");return t}function Ln(r){let e=Object.keys(r);if(e.length===0)throw new Error("There are no secrets to provision");if(e.length>Wt)throw new Error(`At most ${Wt} secrets at once`);for(let t of e){if(!Kn.test(t))throw new Error(`Secret name ${JSON.stringify(t)} must match [A-Za-z0-9][A-Za-z0-9_.-]{0,63}`);if(typeof r[t]!="string")throw new Error(`Secret ${t} is not a string`);if(ue(r[t]).length>Xt)throw new Error(`Secret ${t} is over ${Xt} bytes`)}}async function lr(r,e,t,n,i,s){if(!n.agentId)throw new Error("This quote names no agent; attest with the agent id");let o=await cr(n,i),a=ke(n.provisioningPublicKey,"provisioningPublicKey",32),c=await Zt(a,i,sr(a,n.agentId),ue(JSON.stringify(s)));return ar(r,or(e,t),{agentId:n.agentId,provisioningPublicKeyB64:n.provisioningPublicKey,senderPublicKeyB64:o,encappedKeyB64:K(c.enc),ciphertextB64:K(c.ciphertext)})}async function Hn(r){Ln(r.secrets);let e=r.fetch??fetch,t=await lr(e,r.gateUrl,"/provision",r.agent,r.ownerSecret,{secrets:r.secrets}),n=await it({gateUrl:r.gateUrl,agentId:r.agent.agentId,verifier:r.verifier,fetch:e}),i=await Ce(r.ownerSecret);if(n.ownerPublicKey!==i||!n.signingPublicKey)throw new O("The gate accepted the secrets, but its quote does not name your key as owner");if(r.agent.signingPublicKey&&r.agent.signingPublicKey!==n.signingPublicKey)throw new O("The agent's signing key changed while provisioning");return{agentId:n.agentId,provisioningPublicKey:n.provisioningPublicKey,signingPublicKey:n.signingPublicKey,ownerPublicKey:i,written:t?.written??[],claimed:t?.claimed===!0}}async function Gn(r){if(!r.agent.ownerPublicKey)throw new Error("This agent is not claimed; there is nothing to release");let e=r.fetch??fetch;if(await lr(e,r.gateUrl,"/release",r.agent,r.ownerSecret,{release:!0}),(await it({gateUrl:r.gateUrl,agentId:r.agent.agentId,verifier:r.verifier,fetch:e})).ownerPublicKey)throw new O("The gate says it released the agent, but its quote still names an owner")}var st=Object.freeze({identity:"https://github.com/calimero-network/mero-tee/.github/workflows/release-kms.yaml@refs/heads/master",issuer:"https://token.actions.githubusercontent.com"}),Fn=["allowed_tcb_statuses","allowed_mrtd","allowed_rtmr0","allowed_rtmr1","allowed_rtmr2","allowed_rtmr3"];async function jn(r,e,t={}){let n=typeof r=="string"?new TextEncoder().encode(r):r;await he(n,e,{identity:t.identity??st.identity,issuer:t.issuer??st.issuer});let i;try{i=JSON.parse(new TextDecoder().decode(n))}catch{throw new Error("The signed agent policy is not JSON")}let s=t.role??"agent";if(i?.role!==s)throw new Error(`The signed file is a ${JSON.stringify(i?.role)} policy, not an ${s} one`);let o=t.profile??M;if(i.profile!==o)throw new Error(`The signed agent policy is for the ${JSON.stringify(i.profile)} profile, not ${o}`);if(t.expectedVersion!==void 0&&i.version!==t.expectedVersion)throw new Error(`The signed agent policy is release ${JSON.stringify(i.version)}, not ${t.expectedVersion}`);return ur(i),i}function ur(r){for(let e of Fn)if(!Array.isArray(r?.[e])||r[e].length===0)throw new Error(`The agent policy's ${e} is empty, so no agent would be accepted`)}var Qn=["UpToDate","SWHardeningNeeded","ConfigurationNeeded","ConfigurationAndSWHardeningNeeded","OutOfDate","OutOfDateConfigurationNeeded"];function qn(r){let e=Qn.find(t=>t.toLowerCase()===r.trim().toLowerCase());if(!e)throw new Error(`The agent policy allows an unknown TCB status ${JSON.stringify(r)}`);return e}var de=r=>r.trim().replace(/^0x/i,"");function Jn(r,e){return ur(r),_({dcapVerify:e.dcapVerify,fetchCollateral:e.fetchCollateral,now:e.now,allowedTcbStatuses:r.allowed_tcb_statuses.map(qn),allowedMrtd:r.allowed_mrtd.map(de),allowedRtmr0:r.allowed_rtmr0.map(de),allowedRtmr1:r.allowed_rtmr1.map(de),allowedRtmr2:r.allowed_rtmr2.map(de),allowedRtmr3:r.allowed_rtmr3.map(de)})}export{er as AGENT_ATTEST_DOMAIN,tr as AGENT_PROVISION_INFO_DOMAIN,O as AgentGateError,Pe as AppError,Ae as ArgsTooLarge,et as CalimeroClient,w as CalimeroError,ie as ConfirmCancelled,z as ConfirmRequired,Re as ConsentStale,Rn as DEFAULT_ORG_CAPABILITIES,Qe as DEFAULT_RELEASE_MIRROR,Tt as GITHUB_RELEASES,gt as HANDSHAKE_PATH,be as IdempotencyMismatch,st as KMS_RELEASE_SIGNER,J as LoginRequired,We as MAX_REPORT_PAGE,Ct as MOCK_QUOTE_HEADER,je as NODE_RELEASE_SIGNER,we as NotFound,tt as ORG_CAPABILITIES,M as PRODUCTION_PROFILE,Mt as RELEASE_VERIFIER,Ee as ReleaseDeadlineError,ee as SEALED_CONTENT_TYPE,pt as SEALED_PATH,S as SealedTransportError,te as StaleTransportKeyError,Ue as TrapError,B as UnavailableError,$ as WrongNode,ir as agentKeyBinding,Jn as agentQuoteVerifier,it as attestAgent,T as b64url,pn as browserPasskey,cr as checkOwner,It as claimedRelease,ze as cloudNodeReleaseUrl,oe as compareVersions,yn as consentReturn,_ as createQuoteVerifier,Ve as createSealedFetch,an as createSignedReleaseVerifier,Te as errorFrom,Ze as fetchAttestedKey,Je as fetchGithubNodeRelease,qe as fetchNodeRelease,C as fromB64url,Vn as generateOwnerKey,Pn as orgCapabilities,Ce as ownerPublicKey,ae as pageQuery,Xe as pendingApprovalsFrom,Hn as provisionAgent,sr as provisionInfo,fn as publisherBindingBytes,Dt as publisherBindingMessage,Gn as releaseAgent,Bt as releaseConsent,_t as releaseNotesUrl,Nt as stalledBy,Ke as transportKeyBinding,me as trustSignedRelease,Fe as trustedMeasurementsFromReleases,mn as upgradeConsent,rr as validateAgentId,$t as verifyReleaseUrl,jn as verifySignedAgentPolicy,xt as verifySignedNodeRelease,hn as withdrawConsent};
|
|
8
|
+
`))p.startsWith("id:")?c=p.slice(3).trim():p.startsWith("event:")?u=p.slice(6).trim():p.startsWith("data:")&&(d+=p.slice(5).trim());if(!u&&!d)continue;let g=d;try{g=JSON.parse(d)}catch{}yield{id:c,kind:u,data:g}}}}function Ht(r){return Array.from(r,e=>e.toString(16).padStart(2,"0")).join("")}function Lt(){return`node:c-${T(crypto.getRandomValues(new Uint8Array(16)))}`}var Rn={retries:6,baseDelayMs:200,maxDelayMs:2e3};function Pn(r,e){return Math.min(e.baseDelayMs*2**r,e.maxDelayMs)}function Gt(r){return r==="auth/refresh"||r.startsWith("auth/passkey/")}var tt=class{constructor(e){this.at=0;this.channels=new Map;this.networkFailures=new WeakSet;let t=s=>s.replace(/\/+$/,"");this.nodeUrls=[...new Set([e.baseUrl,...e.nodes??[]].map(t))],this.policy=e.policy,this.retry={...Rn,...e.retry};let n=e.fetch??((s,o)=>fetch(s,o)),i=async(s,o)=>{try{return await n(s,o)}catch(a){throw a instanceof TypeError&&this.networkFailures.add(a),a}};this.raw=i}get nodeUrl(){return this.nodeUrls[this.at]}channel(e){let t=this.channels.get(e);return t||(t=Ve({baseUrl:e,transportPublicKey:()=>Ze(e,this.policy,this.raw),fetch:this.raw}),this.channels.set(e,t)),t}moveOn(e){return this.nodeUrls.length<2?!1:(this.at===e&&(this.at=(e+1)%this.nodeUrls.length),!0)}useApiKey(e){this.auth=e,this.current=void 0}useSession(e){this.auth=e.sessionToken,this.current=e}get session(){return this.current}async request(e,t,n,i,s="application/wasm",o){let a={};this.auth&&(a.authorization=`Bearer ${this.auth}`);let c;i?(a["content-type"]=s,c=i):n!==void 0&&(a["content-type"]="application/json",c=JSON.stringify(n));let u=this.nodeUrl;try{return await this.channel(u)(`${u}/${t}`,{method:e,headers:a,body:c,signal:o})}catch(d){throw bn(d)}}async send(e,t,n,i,s,o){let a=!1,c=!1;for(;;){let[u,d]=[this.auth,this.at],g=await this.request(e,t,n,i,s,o);if(g.ok)return g;let p=await Vt(g);if(p instanceof $&&!c){if(c=!0,this.moveOn(d)&&!Gt(t))continue}else if(p instanceof J&&!a&&this.mayRefresh(u,t)){a=!0,await this.renew(u);continue}throw p}}mayRefresh(e,t){return e!==void 0&&this.current!==void 0&&!Gt(t)}async renew(e){this.auth===e&&await this.refresh()}async json(e,t,n,i,s){let a=await(await this.send(e,t,n,i,s)).text();return a?JSON.parse(a):{}}async retried(e,t,n,i=this.retry.retries){for(let s=0;;s++){let o;try{return await this.json(e,t,n)}catch(c){if(c instanceof B)o=c;else if(c instanceof TypeError&&this.networkFailures.has(c))o=new B("NETWORK",`the node could not be reached: ${c.message}`,{},void 0,c);else throw c}if(s>=i)throw o;let a=Pn(s,this.retry);await new Promise(c=>setTimeout(c,Math.max(a,(o.retryAfter??0)*1e3)))}}post(e,t={}){return this.json("POST",e,t)}get(e){return this.json("GET",e)}put(e,t={}){return this.json("PUT",e,t)}delete(e,t){return this.json("DELETE",e,t)}async signUp(e,t){let n=await this.post("auth/passkey/register/begin",{name:t}),i=await e.create(n.options),s=await this.post("auth/passkey/register/finish",{challengeId:n.challengeId,registration:i});return this.useSession(s),s}async signIn(e){let t=await this.post("auth/passkey/login/begin"),n=await e.get(C(t.options.challenge),t.options.rpId),i=await this.post("auth/passkey/login/finish",{challengeId:t.challengeId,assertion:n});return this.useSession(i),i}refresh(){if(!this.refreshing){let e=this.exchangeRefresh();this.refreshing=e;let t=()=>{this.refreshing===e&&(this.refreshing=void 0)};e.then(t,t)}return this.refreshing}async exchangeRefresh(){let e=this.current;if(!e)throw new Error("no session to refresh");let t;for(let n=1;t===void 0;n++)try{t=await this.post("auth/refresh",{refreshToken:e.refreshToken})}catch(i){if(!(i instanceof $)||n>=this.nodeUrls.length)throw i}return this.current===e&&this.useSession(t),t}async signOut(){await this.post("auth/logout"),this.auth=void 0,this.current=void 0}async signOutEverywhere(){await this.post("auth/logout-all"),this.auth=void 0,this.current=void 0}me(){return this.get("auth/me")}async addPasskey(e){let t=await this.post("auth/passkeys/add/begin"),n=await e.create(t.options),{credentialId:i}=await this.post("auth/passkeys/add/finish",{challengeId:t.challengeId,registration:n});return i}async removePasskey(e){await this.delete(`auth/passkeys/${l(e)}`)}async labelPasskey(e,t){await this.post(`auth/passkeys/${l(e)}`,{label:t})}usage(){return this.get("auth/usage")}async attestation(){let e=Ht(crypto.getRandomValues(new Uint8Array(32))),t=await this.raw(`${this.nodeUrl}/attestation?nonce=${e}`);if(!t.ok)throw await Vt(t);return await t.json()}async listApiKeys(){let{keys:e}=await this.get("auth/apikeys");return e}async revokeApiKey(e){await this.delete(`auth/apikeys/${l(e)}`)}createApiKey(e){return this.post("auth/apikeys",e)}async uploadBundle(e){let{hash:t}=await this.json("POST","bundles",void 0,e);return t}uploadBlob(e,t){return this.json("POST",`apps/${l(e)}/blobs`,void 0,t)}async downloadBlob(e,t){let n=await this.send("GET",`apps/${l(e)}/blobs/${l(t)}`);return new Uint8Array(await n.arrayBuffer())}async listBlobs(e){let{blobs:t}=await this.get(`apps/${l(e)}/blobs`);return t}blobInfo(e,t){return this.get(`apps/${l(e)}/blobs/${l(t)}/info`)}async deleteBlob(e,t){await this.delete(`apps/${l(e)}/blobs/${l(t)}`)}uploadPackage(e){return this.json("POST","packages",void 0,e,"application/octet-stream")}installPackage(e,t){return this.post("packages/install",{package:e,version:t})}async packages(){let{packages:e}=await this.get("packages");return e}package(e){return this.get(`packages/${l(e)}`)}uninstallPackage(e,t){return this.delete(t===void 0?`packages/${l(e)}`:`packages/${l(e)}/${l(t)}`)}async listApps(e={}){let t=new URLSearchParams;e.package&&t.set("package",e.package),e.bundle&&t.set("bundle",e.bundle);let n=t.toString(),{apps:i}=await this.get(n?`apps?${n}`:"apps");return i}getApp(e){return this.get(`apps/${l(e)}`)}async deleteApp(e){await this.delete(`apps/${l(e)}`)}async setAccess(e,t){await this.post(`apps/${l(e)}/access`,{access:t})}async setAppMetadata(e,t){await this.post(`apps/${l(e)}/metadata`,{metadata:t})}appStorage(e){return this.get(`apps/${l(e)}/storage`)}appAbi(e){return this.get(`apps/${l(e)}/abi`)}async transferApp(e,t,n){await this.postConfirmed(`apps/${l(e)}/transfer`,{to:t},n)}upgradeApp(e,t,n){let i=`apps/${l(e)}/upgrade`;return n?this.postConfirmed(i,t,n):this.post(i,t)}postConfirmed(e,t,n){return this.confirmed("POST",e,t,n)}deleteConfirmed(e,t,n={}){return this.confirmed("DELETE",e,n,t)}async confirmed(e,t,n,i,s=o=>this.json(e,t,o)){try{return await s(n)}catch(o){if(!(o instanceof Y))throw o;let a=o.details,c;try{c=await i.get(C(a.challenge),a.rpId,a.allowCredentials)}catch(u){let d=u?.name;throw d==="NotAllowedError"||d==="AbortError"?new ie(u):u}return s({...n,confirm:{challengeId:a.challengeId,assertion:c}})}}async createApp(e,t,n={}){let i=typeof t=="string"?{bundle:t}:t,{appId:s}=await this.post("apps",{name:e,...i,...n});return s}call(e,t,n={},i){let s=i??Lt();return this.retried("POST",`apps/${l(e)}/intents`,{method:t,args:n,idempotencyKey:s})}async callConfirmed(e,t,n,i,s){let o=`apps/${l(e)}/intents`,a=s??Lt();return this.confirmed("POST",o,{method:t,args:n,idempotencyKey:a},i,c=>this.retried("POST",o,c,c.confirm===void 0?this.retry.retries:0))}view(e,t,n={},i={}){return this.retried("POST",`apps/${l(e)}/views`,{method:t,args:n,consistency:i.stale?"stale":"strong",minIndex:i.minIndex??0})}events(e,t=0,n){return this.stream(`apps/${l(e)}/events?from=${t}`,n)}async*stream(e,t){let n=await this.send("GET",e,void 0,void 0,void 0,t);if(!n.body)throw new w(n.status,"EVENTS","the event stream has no body");yield*En(n.body)}async publishPresence(e,t,n){await this.post(`apps/${l(e)}/presence`,{seq:t,state:n===null?null:Ht(n)})}async presence(e){let{present:t}=await this.get(`apps/${l(e)}/presence`);return t}presenceStream(e,t){return this.stream(`apps/${l(e)}/presence/stream`,t)}async setAlias(e,t){await this.put(`auth/aliases/${l(e)}`,{app:t})}async aliases(){let{aliases:e}=await this.get("auth/aliases");return e}async alias(e){let{appId:t}=await this.get(`auth/aliases/${l(e)}`);return t}async deleteAlias(e){await this.delete(`auth/aliases/${l(e)}`)}async createOrg(e){let{orgId:t}=await this.post("orgs",{name:e});return t}getOrg(e){return this.get(`orgs/${l(e)}`)}async deleteOrg(e,t){await this.deleteConfirmed(`orgs/${l(e)}`,t)}async setOrgMetadata(e,t){await this.post(`orgs/${l(e)}/metadata`,{metadata:t})}async setMemberMetadata(e,t,n){await this.post(`orgs/${l(e)}/members/${l(t)}/metadata`,{metadata:n})}upgradeOrg(e,t,n){return this.postConfirmed(`orgs/${l(e)}/upgrade`,{...t},n)}upgradeRun(e,t){return this.get(`orgs/${l(e)}/upgrades/${l(t)}`)}retryUpgradeRun(e,t,n){return this.postConfirmed(`orgs/${l(e)}/upgrades/${l(t)}/retry`,{},n)}async approveRelease(e,t,n,i=!0){let s=e===null?"auth/releases":`orgs/${l(e)}/releases`;return this.postConfirmed(s,{version:t,approved:i},n)}async approveOutbound(e,t,n,i={}){let s=e===null?"auth/outbound":`orgs/${l(e)}/outbound`;return this.postConfirmed(s,{package:t,prefixes:i.prefixes??"manifest",replace:i.replace??!1},n)}appsReport(e,t={}){let n=e===null?"auth/apps":`orgs/${l(e)}/apps`;return this.get(`${n}${ae(t)}`)}async appsReportAll(e){let t=await this.appsReport(e),n=[...t.apps],i=t.next;for(;i!==null;){let s=await this.appsReport(e,{after:i});n.push(...s.apps),i=s.next}return{...t,apps:n,next:null}}releaseRules(){return this.get("releases")}async pendingApprovals(e=null){let[t,n]=await Promise.all([this.appsReportAll(e),this.releaseRules()]);return et(t,n)}requestConsent(e){return this.post("consent/requests",e)}async openConsentPage(e,t={}){let n=typeof t=="function"?{navigate:t}:t,i=n.navigate??(o=>{let a=globalThis.window;if(!a)throw new Error("no window to open the consent page in; pass `navigate`");a.location.assign(o)}),s=await this.requestConsent(e);if(s.code!==void 0){let o=await Xe(s.requestId);if(s.code!==o)throw new w(200,"CONSENT_CODE_MISMATCH","the consent page code does not match the request",{requestId:s.requestId,code:s.code,expected:o})}return n.confirm&&!await n.confirm(s)||i(s.url),s}consentResult(e){return this.get(`consent/${l(e)}/result`)}async waitForConsent(e,t={}){let n=t.intervalMs??2e3;for(;;){let i=await this.consentResult(e);if(i.status!=="pending"||t.signal?.aborted||t.expiresAt!==void 0&&Date.now()/1e3>=t.expiresAt)return i;await new Promise(s=>setTimeout(s,n))}}publisherBinding(e){return this.get(`publishers/${l(e)}`)}bindPublisher(e,t,n){return this.postConfirmed(`orgs/${l(e)}/publishers`,{...t},n)}upgradePublished(e,t,n,i){return this.postConfirmed(`orgs/${l(e)}/packages/${l(t)}/upgrade`,{...n},i)}opsApps(e={}){return this.get(`ops/apps${ae(e)}`)}opsOrgs(e={}){return this.get(`ops/orgs${ae(e)}`)}async setReleaseDeadline(e,t){let n=typeof t=="string"?t:t.toISOString();await this.post(`ops/releases/${l(e)}/deadline`,{after:n})}async liftReleaseDeadline(e){await this.delete(`ops/releases/${l(e)}/deadline`)}async setMember(e,t,n){await this.post(`orgs/${l(e)}/members`,{account:t,role:n})}removeMember(e,t){return this.delete(`orgs/${l(e)}/members/${l(t)}`)}async setCapabilities(e,t,n={}){await this.post(`orgs/${l(e)}/capabilities`,{capabilities:t,...n})}async createTeam(e,t,n,i){let{teamId:s}=await this.post(`orgs/${l(e)}/teams`,{name:t,join:n,parent:i});return s}getTeam(e,t){return this.get(`orgs/${l(e)}/teams/${l(t)}`)}async updateTeam(e,t,n){await this.post(`orgs/${l(e)}/teams/${l(t)}`,n)}async deleteTeam(e,t){await this.delete(`orgs/${l(e)}/teams/${l(t)}`)}async setTeamMember(e,t,n,i={}){await this.post(`orgs/${l(e)}/teams/${l(t)}/members`,{account:n,...i})}async removeTeamMember(e,t,n){await this.delete(`orgs/${l(e)}/teams/${l(t)}/members/${l(n)}`)}async invite(e,t,n=[],i={}){let{token:s}=await this.post(`orgs/${l(e)}/invites`,{role:t,teams:n,...i});return s}redeemInvite(e){return this.post(`invites/${l(e)}/redeem`)}};var rt={CREATE_APP:1,INVITE_MEMBERS:2,JOIN_OPEN_TEAMS:4,MANAGE_MEMBERS:8,MANAGE_APPLICATION:16,CREATE_TEAM:32,DELETE_TEAM:64,MANAGE_VISIBILITY:128,MANAGE_METADATA:256,APPROVE_RELEASES:1024},Un=rt.JOIN_OPEN_TEAMS;function xn(...r){return r.reduce((e,t)=>e|rt[t],0)}function Se(r,e){return(r<<e|r>>>32-e)>>>0}function I(r,e,t,n,i){r[e]=r[e]+r[t]>>>0,r[i]=Se(r[i]^r[e],16),r[n]=r[n]+r[i]>>>0,r[t]=Se(r[t]^r[n],12),r[e]=r[e]+r[t]>>>0,r[i]=Se(r[i]^r[e],8),r[n]=r[n]+r[i]>>>0,r[t]=Se(r[t]^r[n],7)}function Ft(r,e){return(r[e]|r[e+1]<<8|r[e+2]<<16|r[e+3]<<24)>>>0}function qt(r,e,t){let n=new Uint32Array(16);n[0]=1634760805,n[1]=857760878,n[2]=2036477234,n[3]=1797285236;for(let o=0;o<8;o+=1)n[4+o]=Ft(r,o*4);n[12]=e>>>0;for(let o=0;o<3;o+=1)n[13+o]=Ft(t,o*4);let i=n.slice();for(let o=0;o<10;o+=1)I(i,0,4,8,12),I(i,1,5,9,13),I(i,2,6,10,14),I(i,3,7,11,15),I(i,0,5,10,15),I(i,1,6,11,12),I(i,2,7,8,13),I(i,3,4,9,14);let s=new Uint8Array(64);for(let o=0;o<16;o+=1){let a=i[o]+n[o]>>>0;s[o*4]=a&255,s[o*4+1]=a>>>8&255,s[o*4+2]=a>>>16&255,s[o*4+3]=a>>>24&255}return s}function Tn(r,e,t,n){let i=new Uint8Array(n.length);for(let s=0,o=e;s<n.length;s+=64,o+=1){let a=qt(r,o,t),c=Math.min(s+64,n.length);for(let u=s;u<c;u+=1)i[u]=n[u]^a[u-s]}return i}function nt(r){let e=0n;for(let t=r.length-1;t>=0;t-=1)e=e<<8n|BigInt(r[t]);return e}var Sn=(1n<<130n)-5n;function vn(r,e){let t=nt(r.subarray(0,16))&0x0ffffffc0ffffffc0ffffffc0fffffffn,n=nt(r.subarray(16,32)),i=0n;for(let a=0;a<e.length;a+=16){let c=e.subarray(a,Math.min(a+16,e.length)),u=nt(c)+(1n<<BigInt(8*c.length));i=(i+u)*t%Sn}let s=i+n&(1n<<128n)-1n,o=new Uint8Array(16);for(let a=0;a<16;a+=1)o[a]=Number(s&0xffn),s>>=8n;return o}function jt(r){return new Uint8Array((16-r%16)%16)}function Qt(r){let e=new Uint8Array(8);return new DataView(e.buffer).setBigUint64(0,BigInt(r),!0),e}function kn(r,e){let t=[r,jt(r.length),e,jt(e.length),Qt(r.length),Qt(e.length)],n=new Uint8Array(t.reduce((s,o)=>s+o.length,0)),i=0;for(let s of t)n.set(s,i),i+=s.length;return n}function Cn(r,e){if(r.length!==32)throw new Error("ChaCha20-Poly1305 needs a 32-byte key");if(e.length!==12)throw new Error("ChaCha20-Poly1305 needs a 12-byte nonce")}function Jt(r,e,t,n=new Uint8Array(0)){Cn(r,e);let i=qt(r,0,e).subarray(0,32),s=Tn(r,1,e,t),o=vn(i,kn(n,s)),a=new Uint8Array(s.length+16);return a.set(s),a.set(o,s.length),a}var zt=32,In=1,On=3,Nn=2,Dn=32,Mn=32,_n=12,z=r=>new TextEncoder().encode(r),le=r=>new Uint8Array([r>>8&255,r&255]),Yt=y(z("KEM"),le(zt)),ce=y(z("HPKE"),le(zt),le(In),le(On));async function Zt(r,e){let t=r.length===0?new Uint8Array(32):r,n=await crypto.subtle.importKey("raw",t,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return new Uint8Array(await crypto.subtle.sign("HMAC",n,e))}async function $n(r,e,t){let n=new Uint8Array(t),i=new Uint8Array(0);for(let s=1,o=0;o<t;s+=1)i=await Zt(r,y(i,e,new Uint8Array([s]))),n.set(i.subarray(0,Math.min(i.length,t-o)),o),o+=i.length;return n}function ve(r,e,t,n){return Zt(e,y(z("HPKE-v1"),r,z(t),n))}function it(r,e,t,n,i){return $n(e,y(le(i),z("HPKE-v1"),r,z(t),n),i)}async function Bn(r,e){let t=await ve(Yt,new Uint8Array(0),"eae_prk",r);return it(Yt,t,"shared_secret",e,Dn)}async function Kn(r,e){let t=new Uint8Array(0),n=await ve(ce,t,"psk_id_hash",t),i=await ve(ce,t,"info_hash",e),s=y(new Uint8Array([Nn]),n,i),o=await ve(ce,r,"secret",t);return{key:await it(ce,o,"key",s,Mn),nonce:await it(ce,o,"base_nonce",s,_n)}}async function Wt(r,e,t,n,i=new Uint8Array(0),s){if(r.length!==32)throw new Error("The recipient key is not 32 bytes of X25519");let o=await G(s),a=await G(e),c=y(await W(o.privateKey,r),await W(a.privateKey,r)),u=await Bn(c,y(o.publicKey,r,a.publicKey)),{key:d,nonce:g}=await Kn(u,t);return{enc:o.publicKey,ciphertext:Jt(d,g,n,i)}}var tr="mero-agent-gate/attest/v3",rr="mero-agent-gate/provision/v2",Vn=/^[a-z0-9][a-z0-9-]{0,62}$/,Hn=/^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/,Xt=64,er=64*1024,O=class extends Error{constructor(t,n,i){super(t);this.status=n;this.code=i;this.name="AgentGateError"}};function nr(r){if(!Vn.test(r))throw new Error(`Agent id ${JSON.stringify(r)} must match [a-z0-9][a-z0-9-]{0,62}`)}function ue(r){return new TextEncoder().encode(r)}function ir(r){let e=ue(r);return y(new Uint8Array([e.length]),e)}function K(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e)}function ke(r,e,t){let n;try{n=Uint8Array.from(atob(r.trim()),i=>i.charCodeAt(0))}catch{throw new Error(`${e} is not base64`)}if(t!==void 0&&n.length!==t)throw new Error(`${e} is not ${t} bytes`);return n}async function sr(r,e,t,n){let i=new Uint8Array(32),s=y(ue(tr),r,ir(e),t??i,n??i);return new Uint8Array(await crypto.subtle.digest("SHA-256",s))}function or(r,e){return y(ue(rr),r,ir(e))}async function Ln(){let r=crypto.getRandomValues(new Uint8Array(32));return{secret:r,publicKey:await Ce(r)}}async function Ce(r){if(r.length!==32)throw new Error("An owner key is 32 bytes");return K((await G(r)).publicKey)}function ar(r,e){return`${r.replace(/\/+$/,"")}${e}`}async function cr(r,e,t){let n=await r(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)}),i=await n.text(),s;try{s=i?JSON.parse(i):void 0}catch{}if(!n.ok){let o=s;throw new O(`The gate answered ${n.status}${o?.error?` ${o.error}`:""}: ${o?.details??i.slice(0,200)}`,n.status,o?.error)}return s}async function st(r){let e=r.agentId??"";e&&nr(e);let t=crypto.getRandomValues(new Uint8Array(32)),n=await cr(r.fetch??fetch,ar(r.gateUrl,"/attest"),{nonceB64:K(t),...e?{agentId:e}:{}});if((n?.agentId??"")!==e)throw new Error(`Asked about agent ${JSON.stringify(e)}, the gate answered for ${JSON.stringify(n?.agentId)}`);let i=ke(n.provisioningPublicKeyB64??"","provisioningPublicKeyB64",32),s=n.signingPublicKeyB64?ke(n.signingPublicKeyB64,"signingPublicKeyB64",32):void 0,o=n.ownerPublicKeyB64?ke(n.ownerPublicKeyB64,"ownerPublicKeyB64",32):void 0;if(!s!=!o)throw new Error("A claimed agent has both a signing key and an owner; the gate named one");let a=await sr(i,e,s,o);return await r.verifier({quoteB64:n.quoteB64,nonce:R(t),reportDataSuffix:R(a)}),{agentId:e,provisioningPublicKey:K(i),...s?{signingPublicKey:K(s)}:{},...o?{ownerPublicKey:K(o)}:{}}}async function lr(r,e){let t=await Ce(e);if(r.ownerPublicKey&&r.ownerPublicKey!==t)throw new O(`This agent is claimed by another key (${r.ownerPublicKey}); it is not yours. Send it nothing and do not authorize its signing key`,void 0,"not_yours");return t}function Gn(r){let e=Object.keys(r);if(e.length===0)throw new Error("There are no secrets to provision");if(e.length>Xt)throw new Error(`At most ${Xt} secrets at once`);for(let t of e){if(!Hn.test(t))throw new Error(`Secret name ${JSON.stringify(t)} must match [A-Za-z0-9][A-Za-z0-9_.-]{0,63}`);if(typeof r[t]!="string")throw new Error(`Secret ${t} is not a string`);if(ue(r[t]).length>er)throw new Error(`Secret ${t} is over ${er} bytes`)}}async function ur(r,e,t,n,i,s){if(!n.agentId)throw new Error("This quote names no agent; attest with the agent id");let o=await lr(n,i),a=ke(n.provisioningPublicKey,"provisioningPublicKey",32),c=await Wt(a,i,or(a,n.agentId),ue(JSON.stringify(s)));return cr(r,ar(e,t),{agentId:n.agentId,provisioningPublicKeyB64:n.provisioningPublicKey,senderPublicKeyB64:o,encappedKeyB64:K(c.enc),ciphertextB64:K(c.ciphertext)})}async function Fn(r){Gn(r.secrets);let e=r.fetch??fetch,t=await ur(e,r.gateUrl,"/provision",r.agent,r.ownerSecret,{secrets:r.secrets}),n=await st({gateUrl:r.gateUrl,agentId:r.agent.agentId,verifier:r.verifier,fetch:e}),i=await Ce(r.ownerSecret);if(n.ownerPublicKey!==i||!n.signingPublicKey)throw new O("The gate accepted the secrets, but its quote does not name your key as owner");if(r.agent.signingPublicKey&&r.agent.signingPublicKey!==n.signingPublicKey)throw new O("The agent's signing key changed while provisioning");return{agentId:n.agentId,provisioningPublicKey:n.provisioningPublicKey,signingPublicKey:n.signingPublicKey,ownerPublicKey:i,written:t?.written??[],claimed:t?.claimed===!0}}async function jn(r){if(!r.agent.ownerPublicKey)throw new Error("This agent is not claimed; there is nothing to release");let e=r.fetch??fetch;if(await ur(e,r.gateUrl,"/release",r.agent,r.ownerSecret,{release:!0}),(await st({gateUrl:r.gateUrl,agentId:r.agent.agentId,verifier:r.verifier,fetch:e})).ownerPublicKey)throw new O("The gate says it released the agent, but its quote still names an owner")}var ot=Object.freeze({identity:"https://github.com/calimero-network/mero-tee/.github/workflows/release-kms.yaml@refs/heads/master",issuer:"https://token.actions.githubusercontent.com"}),Qn=["allowed_tcb_statuses","allowed_mrtd","allowed_rtmr0","allowed_rtmr1","allowed_rtmr2","allowed_rtmr3"];async function qn(r,e,t={}){let n=typeof r=="string"?new TextEncoder().encode(r):r;await he(n,e,{identity:t.identity??ot.identity,issuer:t.issuer??ot.issuer});let i;try{i=JSON.parse(new TextDecoder().decode(n))}catch{throw new Error("The signed agent policy is not JSON")}let s=t.role??"agent";if(i?.role!==s)throw new Error(`The signed file is a ${JSON.stringify(i?.role)} policy, not an ${s} one`);let o=t.profile??M;if(i.profile!==o)throw new Error(`The signed agent policy is for the ${JSON.stringify(i.profile)} profile, not ${o}`);if(t.expectedVersion!==void 0&&i.version!==t.expectedVersion)throw new Error(`The signed agent policy is release ${JSON.stringify(i.version)}, not ${t.expectedVersion}`);return dr(i),i}function dr(r){for(let e of Qn)if(!Array.isArray(r?.[e])||r[e].length===0)throw new Error(`The agent policy's ${e} is empty, so no agent would be accepted`)}var Jn=["UpToDate","SWHardeningNeeded","ConfigurationNeeded","ConfigurationAndSWHardeningNeeded","OutOfDate","OutOfDateConfigurationNeeded"];function Yn(r){let e=Jn.find(t=>t.toLowerCase()===r.trim().toLowerCase());if(!e)throw new Error(`The agent policy allows an unknown TCB status ${JSON.stringify(r)}`);return e}var de=r=>r.trim().replace(/^0x/i,"");function zn(r,e){return dr(r),_({dcapVerify:e.dcapVerify,fetchCollateral:e.fetchCollateral,now:e.now,allowedTcbStatuses:r.allowed_tcb_statuses.map(Yn),allowedMrtd:r.allowed_mrtd.map(de),allowedRtmr0:r.allowed_rtmr0.map(de),allowedRtmr1:r.allowed_rtmr1.map(de),allowedRtmr2:r.allowed_rtmr2.map(de),allowedRtmr3:r.allowed_rtmr3.map(de)})}export{tr as AGENT_ATTEST_DOMAIN,rr as AGENT_PROVISION_INFO_DOMAIN,O as AgentGateError,Pe as AppError,Ae as ArgsTooLarge,tt as CalimeroClient,w as CalimeroError,ie as ConfirmCancelled,Y as ConfirmRequired,Re as ConsentStale,Un as DEFAULT_ORG_CAPABILITIES,Qe as DEFAULT_RELEASE_MIRROR,St as GITHUB_RELEASES,pt as HANDSHAKE_PATH,be as IdempotencyMismatch,ot as KMS_RELEASE_SIGNER,J as LoginRequired,We as MAX_REPORT_PAGE,It as MOCK_QUOTE_HEADER,je as NODE_RELEASE_SIGNER,we as NotFound,rt as ORG_CAPABILITIES,M as PRODUCTION_PROFILE,_t as RELEASE_VERIFIER,Ee as ReleaseDeadlineError,ee as SEALED_CONTENT_TYPE,ft as SEALED_PATH,S as SealedTransportError,te as StaleTransportKeyError,Ue as TrapError,B as UnavailableError,$ as WrongNode,sr as agentKeyBinding,zn as agentQuoteVerifier,st as attestAgent,T as b64url,fn as browserPasskey,lr as checkOwner,Ot as claimedRelease,Ye as cloudNodeReleaseUrl,oe as compareVersions,Xe as confirmationCode,mn as consentReturn,_ as createQuoteVerifier,Ve as createSealedFetch,cn as createSignedReleaseVerifier,Te as errorFrom,Ze as fetchAttestedKey,Je as fetchGithubNodeRelease,qe as fetchNodeRelease,C as fromB64url,Ln as generateOwnerKey,xn as orgCapabilities,Ce as ownerPublicKey,ae as pageQuery,et as pendingApprovalsFrom,Fn as provisionAgent,or as provisionInfo,yn as publisherBindingBytes,Mt as publisherBindingMessage,jn as releaseAgent,Kt as releaseConsent,$t as releaseNotesUrl,Dt as stalledBy,Ke as transportKeyBinding,me as trustSignedRelease,Fe as trustedMeasurementsFromReleases,An as upgradeConsent,nr as validateAgentId,Bt as verifyReleaseUrl,qn as verifySignedAgentPolicy,Tt as verifySignedNodeRelease,wn as withdrawConsent};
|
|
9
9
|
//# sourceMappingURL=index.browser.mjs.map
|