@calimero-network/mero-js 27.0.1 → 27.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,8 @@
11
11
  */
12
12
  import { type AttestationDoc, type CloudPolicy } from './attestation.js';
13
13
  import { type PasskeyProvider } from './passkey.js';
14
- export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, NotFound, TrapError, UnavailableError, errorFrom, } from './errors.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';
15
+ export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, errorFrom, } from './errors.js';
15
16
  export type { Committed } from './errors.js';
16
17
  export interface CalimeroSession {
17
18
  accountId: string;
@@ -112,6 +113,23 @@ export interface OrgUpgradeTarget {
112
113
  cascade?: boolean;
113
114
  migrate?: string;
114
115
  }
116
+ /**
117
+ * `GET /orgs/{org}`: the organization as the caller sees it. Besides its
118
+ * members, teams and metadata, who may approve its releases, the package
119
+ * signing keys it publishes, and whether a passed release deadline has
120
+ * stopped new work on its own set.
121
+ */
122
+ export interface OrgInfo extends Record<string, unknown> {
123
+ /** Accounts holding `APPROVE_RELEASES` there (owner and admins included). */
124
+ releaseApprovers: string[];
125
+ /** The signer ids (`did:key`) bound to it as publisher. */
126
+ publishes: string[];
127
+ /** `null` unless a deadline stopped new work: approve `release` (or newer) to lift it. */
128
+ newWorkStopped: {
129
+ release: string;
130
+ after: string;
131
+ } | null;
132
+ }
115
133
  /**
116
134
  * How a call or a view is sent again while the node is unavailable (D70): with
117
135
  * the same key, after a backoff that starts at `baseDelayMs` and doubles up to
@@ -266,8 +284,11 @@ export declare class CalimeroClient {
266
284
  * Move an app to another release of its package (`{ version }`), another
267
285
  * package, or a bundle hash, running its migration. Answers the upgrade's
268
286
  * entry; a failed migration rejects with code `UPGRADE_FAILED` (422).
269
- * Where the owner holds app upgrades, the node asks for the owner's approval
270
- * (`412 CONFIRM_REQUIRED`), which `passkey` gives.
287
+ * Where owners hold app upgrades, the node asks for the approval of
288
+ * whoever the package's manifest names (`412 CONFIRM_REQUIRED`), which
289
+ * `passkey` gives. Refused (`403`) to a session opened on an app's
290
+ * frontend: an app asks its user with {@link requestConsent} instead. Past
291
+ * a release deadline its approver has not met: {@link ReleaseDeadlineError}.
271
292
  */
272
293
  upgradeApp(app: string, target: {
273
294
  version?: string;
@@ -346,7 +367,7 @@ export declare class CalimeroClient {
346
367
  deleteAlias(alias: string): Promise<void>;
347
368
  createOrg(name: string): Promise<string>;
348
369
  /** The organization, with the teams this caller reaches or manages. */
349
- getOrg(org: string): Promise<Record<string, unknown>>;
370
+ getOrg(org: string): Promise<OrgInfo>;
350
371
  /**
351
372
  * Delete an organization with its teams, invites and apps (its owner only).
352
373
  * The node asks for the owner's passkey (`412 CONFIRM_REQUIRED`), which `passkey` gives.
@@ -370,8 +391,11 @@ export declare class CalimeroClient {
370
391
  /**
371
392
  * Approve a mero-tee release to hold the apps of `org`, or of this account
372
393
  * outside any organization (`org` `null`); `approved: false` withdraws it.
373
- * Until then, nodes on that release get none of those apps' data. The owner
374
- * approves with `passkey`.
394
+ * Until then, nodes on that release get none of those apps' data. For an
395
+ * organization, a member holding `APPROVE_RELEASES` approves with `passkey`;
396
+ * the node binds the release's measurements itself. Refused (`403`) to a
397
+ * session opened on an app's frontend: an app asks its user with
398
+ * {@link requestConsent} instead.
375
399
  */
376
400
  approveRelease(org: string | null, version: string, passkey: PasskeyProvider, approved?: boolean): Promise<Record<string, unknown>>;
377
401
  /**
@@ -379,12 +403,95 @@ export declare class CalimeroClient {
379
403
  * `org`'s apps or this account's own (`org` `null`). `prefixes` `'manifest'`
380
404
  * (the default) approves every prefix the package's latest release declares;
381
405
  * `replace` sets exactly `prefixes`, which is how one is revoked. Approved
382
- * with `passkey`.
406
+ * with `passkey`. Refused (`403`) to a session opened on an app's frontend:
407
+ * an app asks with {@link requestConsent} (`kind: 'outbound'`) instead.
383
408
  */
384
409
  approveOutbound(org: string | null, pkg: string, passkey: PasskeyProvider, options?: {
385
410
  prefixes?: string[] | 'manifest';
386
411
  replace?: boolean;
387
412
  }): Promise<Record<string, unknown>>;
413
+ /**
414
+ * One page of the report of a scope's apps: an organization's (any member;
415
+ * `404` to anyone else) or, with `org` `null`, the account's own outside any
416
+ * organization (a session bound to an app's frontend: that package's apps).
417
+ * The governance, the scope's approved releases, the releases the cluster's
418
+ * nodes run and whether each is approved, and per app its release, newer
419
+ * releases it may move to, last upgrade and replicas.
420
+ */
421
+ appsReport(org: string | null, page?: PageOptions): Promise<AppsReport>;
422
+ /** {@link appsReport}, every page, with the apps of all of them in `apps`. */
423
+ appsReportAll(org: string | null): Promise<AppsReport>;
424
+ /** `GET /releases`: the cluster's governance and every release deadline. Public. */
425
+ releaseRules(): Promise<ReleaseRules>;
426
+ /**
427
+ * What waits for a decision in a scope (`org`, or the account's own apps
428
+ * with `null`): mero-tee releases the cluster's nodes run that the scope has
429
+ * not approved, apps with newer releases of their package, and whether a
430
+ * passed deadline stops new work. Read over the sealed channel; act on an
431
+ * item by sending the user to the consent page ({@link requestConsent},
432
+ * `releaseConsent`, `upgradeConsent`).
433
+ */
434
+ pendingApprovals(org?: string | null): Promise<PendingApprovals>;
435
+ /**
436
+ * Ask the node to ask the user: a release, upgrade or outbound approval
437
+ * that only the account holder may make, decided on the node's own consent
438
+ * page, never in the app. Needs a passkey session (a session bound to the
439
+ * app's frontend is fine). Send the person to the answer's `url`; the page
440
+ * sends them back to `returnTo?request_id=…&result=approved|declined`
441
+ * (`consentReturn`), and {@link consentResult} confirms the decision.
442
+ */
443
+ requestConsent(request: ConsentRequest): Promise<ConsentStarted>;
444
+ /**
445
+ * {@link requestConsent}, then send the browser to the consent page
446
+ * (`navigate`, by default `window.location.assign`). Answers the request
447
+ * once `navigate` returns: with a popup (`url => window.open(url)`), poll it
448
+ * with {@link waitForConsent}.
449
+ */
450
+ openConsentPage(request: ConsentRequest, navigate?: (url: string) => void): Promise<ConsentStarted>;
451
+ /** The decision on a consent request (any node answers, for the account that asked). */
452
+ consentResult(requestId: string): Promise<ConsentResult>;
453
+ /**
454
+ * Poll {@link consentResult} until the request is decided, every
455
+ * `intervalMs` (2 s), until `signal` aborts or `expiresAt` (Unix seconds)
456
+ * passes, when it answers the last `pending` result.
457
+ */
458
+ waitForConsent(requestId: string, options?: {
459
+ intervalMs?: number;
460
+ signal?: AbortSignal;
461
+ expiresAt?: number;
462
+ }): Promise<ConsentResult>;
463
+ /** `GET /publishers/{signerId}`: the cluster name and binding generation a key signs to bind it next. */
464
+ publisherBinding(signerId: string): Promise<PublisherBindingInfo>;
465
+ /**
466
+ * Bind a package signing key to `org`, which then approves the node images
467
+ * every instance of the key's packages runs on, and upgrades those whose
468
+ * package declares `upgrades: publisher`. `proof` is the key's signature
469
+ * over `publisherBindingMessage(cluster, org, signerId, generation)`; a
470
+ * member holding `APPROVE_RELEASES` sends it with `passkey`.
471
+ */
472
+ bindPublisher(org: string, proof: PublisherProof, passkey: PasskeyProvider): Promise<Record<string, unknown>>;
473
+ /**
474
+ * Upgrade every instance of `pkg` whose release declares `upgrades:
475
+ * publisher`, whoever owns it, as its publisher `org` (a
476
+ * `MANAGE_APPLICATION` holder there), with one passkey approval. Answers
477
+ * the run, kept on the publisher.
478
+ */
479
+ upgradePublished(org: string, pkg: string, target: {
480
+ version: string;
481
+ migrate?: string;
482
+ }, passkey: PasskeyProvider): Promise<UpgradeRun>;
483
+ /** `GET /ops/apps`: what every app runs, without names or accounts. Operator token (`useApiKey`). */
484
+ opsApps(page?: PageOptions): Promise<OpsAppsReport>;
485
+ /** `GET /ops/orgs`: each organization's approved releases. Operator token. */
486
+ opsOrgs(page?: PageOptions): Promise<OpsOrgsReport>;
487
+ /**
488
+ * Announce when work on images older than `version` ends: from `after` on,
489
+ * a scope that has not approved it (or newer) starts no new work. Operator
490
+ * token.
491
+ */
492
+ setReleaseDeadline(version: string, after: Date | string): Promise<void>;
493
+ /** Lift a release's deadline. Operator token. */
494
+ liftReleaseDeadline(version: string): Promise<void>;
388
495
  /** Add a member, or change their role. */
389
496
  setMember(org: string, account: string, role: 'guest' | 'member' | 'admin' | 'owner'): Promise<void>;
390
497
  removeMember(org: string, account: string): Promise<Record<string, unknown>>;
@@ -13,7 +13,8 @@ import { SealedTransportError, createSealedFetch } from '../sealed/sealed.js';
13
13
  import { fetchAttestedKey } from './attestation.js';
14
14
  import { CalimeroError, ConfirmCancelled, ConfirmRequired, UnavailableError, errorFrom } from './errors.js';
15
15
  import { b64url, fromB64url } from './passkey.js';
16
- export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, NotFound, TrapError, UnavailableError, errorFrom, } from './errors.js';
16
+ import { pageQuery, pendingApprovalsFrom, } from './approvals.js';
17
+ export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, errorFrom, } from './errors.js';
17
18
  /** One URL path segment, so an id cannot reach another route. */
18
19
  function seg(value) {
19
20
  return encodeURIComponent(value);
@@ -399,8 +400,11 @@ export class CalimeroClient {
399
400
  * Move an app to another release of its package (`{ version }`), another
400
401
  * package, or a bundle hash, running its migration. Answers the upgrade's
401
402
  * entry; a failed migration rejects with code `UPGRADE_FAILED` (422).
402
- * Where the owner holds app upgrades, the node asks for the owner's approval
403
- * (`412 CONFIRM_REQUIRED`), which `passkey` gives.
403
+ * Where owners hold app upgrades, the node asks for the approval of
404
+ * whoever the package's manifest names (`412 CONFIRM_REQUIRED`), which
405
+ * `passkey` gives. Refused (`403`) to a session opened on an app's
406
+ * frontend: an app asks its user with {@link requestConsent} instead. Past
407
+ * a release deadline its approver has not met: {@link ReleaseDeadlineError}.
404
408
  */
405
409
  upgradeApp(app, target, passkey) {
406
410
  const path = `apps/${seg(app)}/upgrade`;
@@ -578,8 +582,11 @@ export class CalimeroClient {
578
582
  /**
579
583
  * Approve a mero-tee release to hold the apps of `org`, or of this account
580
584
  * outside any organization (`org` `null`); `approved: false` withdraws it.
581
- * Until then, nodes on that release get none of those apps' data. The owner
582
- * approves with `passkey`.
585
+ * Until then, nodes on that release get none of those apps' data. For an
586
+ * organization, a member holding `APPROVE_RELEASES` approves with `passkey`;
587
+ * the node binds the release's measurements itself. Refused (`403`) to a
588
+ * session opened on an app's frontend: an app asks its user with
589
+ * {@link requestConsent} instead.
583
590
  */
584
591
  async approveRelease(org, version, passkey, approved = true) {
585
592
  const path = org === null ? 'auth/releases' : `orgs/${seg(org)}/releases`;
@@ -590,12 +597,148 @@ export class CalimeroClient {
590
597
  * `org`'s apps or this account's own (`org` `null`). `prefixes` `'manifest'`
591
598
  * (the default) approves every prefix the package's latest release declares;
592
599
  * `replace` sets exactly `prefixes`, which is how one is revoked. Approved
593
- * with `passkey`.
600
+ * with `passkey`. Refused (`403`) to a session opened on an app's frontend:
601
+ * an app asks with {@link requestConsent} (`kind: 'outbound'`) instead.
594
602
  */
595
603
  async approveOutbound(org, pkg, passkey, options = {}) {
596
604
  const path = org === null ? 'auth/outbound' : `orgs/${seg(org)}/outbound`;
597
605
  return this.postConfirmed(path, { package: pkg, prefixes: options.prefixes ?? 'manifest', replace: options.replace ?? false }, passkey);
598
606
  }
607
+ // ---------------------------------------------------------------- approvals
608
+ /**
609
+ * One page of the report of a scope's apps: an organization's (any member;
610
+ * `404` to anyone else) or, with `org` `null`, the account's own outside any
611
+ * organization (a session bound to an app's frontend: that package's apps).
612
+ * The governance, the scope's approved releases, the releases the cluster's
613
+ * nodes run and whether each is approved, and per app its release, newer
614
+ * releases it may move to, last upgrade and replicas.
615
+ */
616
+ appsReport(org, page = {}) {
617
+ const path = org === null ? 'auth/apps' : `orgs/${seg(org)}/apps`;
618
+ return this.get(`${path}${pageQuery(page)}`);
619
+ }
620
+ /** {@link appsReport}, every page, with the apps of all of them in `apps`. */
621
+ async appsReportAll(org) {
622
+ const first = await this.appsReport(org);
623
+ const apps = [...first.apps];
624
+ let next = first.next;
625
+ while (next !== null) {
626
+ const page = await this.appsReport(org, { after: next });
627
+ apps.push(...page.apps);
628
+ next = page.next;
629
+ }
630
+ return { ...first, apps, next: null };
631
+ }
632
+ /** `GET /releases`: the cluster's governance and every release deadline. Public. */
633
+ releaseRules() {
634
+ return this.get('releases');
635
+ }
636
+ /**
637
+ * What waits for a decision in a scope (`org`, or the account's own apps
638
+ * with `null`): mero-tee releases the cluster's nodes run that the scope has
639
+ * not approved, apps with newer releases of their package, and whether a
640
+ * passed deadline stops new work. Read over the sealed channel; act on an
641
+ * item by sending the user to the consent page ({@link requestConsent},
642
+ * `releaseConsent`, `upgradeConsent`).
643
+ */
644
+ async pendingApprovals(org = null) {
645
+ const [report, rules] = await Promise.all([this.appsReportAll(org), this.releaseRules()]);
646
+ return pendingApprovalsFrom(report, rules);
647
+ }
648
+ /**
649
+ * Ask the node to ask the user: a release, upgrade or outbound approval
650
+ * that only the account holder may make, decided on the node's own consent
651
+ * page, never in the app. Needs a passkey session (a session bound to the
652
+ * app's frontend is fine). Send the person to the answer's `url`; the page
653
+ * sends them back to `returnTo?request_id=…&result=approved|declined`
654
+ * (`consentReturn`), and {@link consentResult} confirms the decision.
655
+ */
656
+ requestConsent(request) {
657
+ return this.post('consent/requests', request);
658
+ }
659
+ /**
660
+ * {@link requestConsent}, then send the browser to the consent page
661
+ * (`navigate`, by default `window.location.assign`). Answers the request
662
+ * once `navigate` returns: with a popup (`url => window.open(url)`), poll it
663
+ * with {@link waitForConsent}.
664
+ */
665
+ async openConsentPage(request, navigate = (url) => {
666
+ const w = globalThis.window;
667
+ if (!w)
668
+ throw new Error('no window to open the consent page in; pass `navigate`');
669
+ w.location.assign(url);
670
+ }) {
671
+ const started = await this.requestConsent(request);
672
+ navigate(started.url);
673
+ return started;
674
+ }
675
+ /** The decision on a consent request (any node answers, for the account that asked). */
676
+ consentResult(requestId) {
677
+ return this.get(`consent/${seg(requestId)}/result`);
678
+ }
679
+ /**
680
+ * Poll {@link consentResult} until the request is decided, every
681
+ * `intervalMs` (2 s), until `signal` aborts or `expiresAt` (Unix seconds)
682
+ * passes, when it answers the last `pending` result.
683
+ */
684
+ async waitForConsent(requestId, options = {}) {
685
+ const interval = options.intervalMs ?? 2000;
686
+ for (;;) {
687
+ const result = await this.consentResult(requestId);
688
+ if (result.status !== 'pending')
689
+ return result;
690
+ if (options.signal?.aborted)
691
+ return result;
692
+ if (options.expiresAt !== undefined && Date.now() / 1000 >= options.expiresAt)
693
+ return result;
694
+ await new Promise((resolve) => setTimeout(resolve, interval));
695
+ }
696
+ }
697
+ /** `GET /publishers/{signerId}`: the cluster name and binding generation a key signs to bind it next. */
698
+ publisherBinding(signerId) {
699
+ return this.get(`publishers/${seg(signerId)}`);
700
+ }
701
+ /**
702
+ * Bind a package signing key to `org`, which then approves the node images
703
+ * every instance of the key's packages runs on, and upgrades those whose
704
+ * package declares `upgrades: publisher`. `proof` is the key's signature
705
+ * over `publisherBindingMessage(cluster, org, signerId, generation)`; a
706
+ * member holding `APPROVE_RELEASES` sends it with `passkey`.
707
+ */
708
+ bindPublisher(org, proof, passkey) {
709
+ return this.postConfirmed(`orgs/${seg(org)}/publishers`, { ...proof }, passkey);
710
+ }
711
+ /**
712
+ * Upgrade every instance of `pkg` whose release declares `upgrades:
713
+ * publisher`, whoever owns it, as its publisher `org` (a
714
+ * `MANAGE_APPLICATION` holder there), with one passkey approval. Answers
715
+ * the run, kept on the publisher.
716
+ */
717
+ upgradePublished(org, pkg, target, passkey) {
718
+ return this.postConfirmed(`orgs/${seg(org)}/packages/${seg(pkg)}/upgrade`, { ...target }, passkey);
719
+ }
720
+ // ---------------------------------------------------------------- operator
721
+ /** `GET /ops/apps`: what every app runs, without names or accounts. Operator token (`useApiKey`). */
722
+ opsApps(page = {}) {
723
+ return this.get(`ops/apps${pageQuery(page)}`);
724
+ }
725
+ /** `GET /ops/orgs`: each organization's approved releases. Operator token. */
726
+ opsOrgs(page = {}) {
727
+ return this.get(`ops/orgs${pageQuery(page)}`);
728
+ }
729
+ /**
730
+ * Announce when work on images older than `version` ends: from `after` on,
731
+ * a scope that has not approved it (or newer) starts no new work. Operator
732
+ * token.
733
+ */
734
+ async setReleaseDeadline(version, after) {
735
+ const at = typeof after === 'string' ? after : after.toISOString();
736
+ await this.post(`ops/releases/${seg(version)}/deadline`, { after: at });
737
+ }
738
+ /** Lift a release's deadline. Operator token. */
739
+ async liftReleaseDeadline(version) {
740
+ await this.delete(`ops/releases/${seg(version)}/deadline`);
741
+ }
599
742
  /** Add a member, or change their role. */
600
743
  async setMember(org, account, role) {
601
744
  await this.post(`orgs/${seg(org)}/members`, { account, role });
@@ -52,6 +52,29 @@ export declare class ArgsTooLarge extends CalimeroError {
52
52
  export declare class IdempotencyMismatch extends CalimeroError {
53
53
  constructor(message: string, details?: Record<string, unknown>);
54
54
  }
55
+ /**
56
+ * `409 RELEASE_DEADLINE`: a mero-tee release's deadline has passed and the
57
+ * set that governs this work (the app's publisher's, or its owner's) has not
58
+ * approved it or a newer one, so new work (creating an app, installing a
59
+ * release, upgrading an app) is refused. Apps already running keep running.
60
+ * Approving `release` lifts it at once.
61
+ */
62
+ export declare class ReleaseDeadlineError extends CalimeroError {
63
+ /** The release to approve. */
64
+ readonly release: string;
65
+ /** Its deadline, RFC 3339 (`''` when the node did not say). */
66
+ readonly after: string;
67
+ constructor(message: string, details?: Record<string, unknown>);
68
+ }
69
+ /**
70
+ * `409 CONSENT_STALE`: what a consent page showed (the app's bundle, the
71
+ * target release, the release's measurements) changed before the person
72
+ * approved. Nothing was approved; ask for a new consent request so they see
73
+ * the new facts.
74
+ */
75
+ export declare class ConsentStale extends CalimeroError {
76
+ constructor(message: string, details?: Record<string, unknown>);
77
+ }
55
78
  /**
56
79
  * `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared
57
80
  * error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was
@@ -73,6 +73,33 @@ export class IdempotencyMismatch extends CalimeroError {
73
73
  this.name = 'IdempotencyMismatch';
74
74
  }
75
75
  }
76
+ /**
77
+ * `409 RELEASE_DEADLINE`: a mero-tee release's deadline has passed and the
78
+ * set that governs this work (the app's publisher's, or its owner's) has not
79
+ * approved it or a newer one, so new work (creating an app, installing a
80
+ * release, upgrading an app) is refused. Apps already running keep running.
81
+ * Approving `release` lifts it at once.
82
+ */
83
+ export class ReleaseDeadlineError extends CalimeroError {
84
+ constructor(message, details = {}) {
85
+ super(409, 'RELEASE_DEADLINE', message, details);
86
+ this.name = 'ReleaseDeadlineError';
87
+ this.release = typeof details.release === 'string' ? details.release : '';
88
+ this.after = typeof details.after === 'string' ? details.after : '';
89
+ }
90
+ }
91
+ /**
92
+ * `409 CONSENT_STALE`: what a consent page showed (the app's bundle, the
93
+ * target release, the release's measurements) changed before the person
94
+ * approved. Nothing was approved; ask for a new consent request so they see
95
+ * the new facts.
96
+ */
97
+ export class ConsentStale extends CalimeroError {
98
+ constructor(message, details = {}) {
99
+ super(409, 'CONSENT_STALE', message, details);
100
+ this.name = 'ConsentStale';
101
+ }
102
+ }
76
103
  /**
77
104
  * `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared
78
105
  * error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was
@@ -151,6 +178,10 @@ export function errorFrom(status, body, retryAfterHeader) {
151
178
  return new NotFound(message, details);
152
179
  case '409 IDEMPOTENCY_MISMATCH':
153
180
  return new IdempotencyMismatch(message, details);
181
+ case '409 RELEASE_DEADLINE':
182
+ return new ReleaseDeadlineError(message, details);
183
+ case '409 CONSENT_STALE':
184
+ return new ConsentStale(message, details);
154
185
  case '412 CONFIRM_REQUIRED':
155
186
  return new ConfirmRequired(message, details);
156
187
  case '413 ARGS_TOO_LARGE':
@@ -1,10 +1,12 @@
1
1
  export { CalimeroClient } from './client.js';
2
- export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, NotFound, TrapError, UnavailableError, errorFrom, } from './errors.js';
2
+ export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, errorFrom, } from './errors.js';
3
3
  export type { Committed } from './errors.js';
4
- export type { AppInfo, BlobInfo, CallResult, CalimeroClientOptions, CloudEvent, CalimeroSession, PackageInfo, PackageInstalled, CloudRetryOptions, OrgUpgradeTarget, PresenceEntry, UpgradeRun, ViewResult, } from './client.js';
4
+ export type { AppInfo, BlobInfo, CallResult, CalimeroClientOptions, CloudEvent, CalimeroSession, PackageInfo, PackageInstalled, CloudRetryOptions, OrgInfo, OrgUpgradeTarget, PresenceEntry, UpgradeRun, ViewResult, } from './client.js';
5
5
  export { claimedRelease, fetchAttestedKey, MOCK_QUOTE_HEADER } from './attestation.js';
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
11
  export { DEFAULT_ORG_CAPABILITIES, ORG_CAPABILITIES, orgCapabilities } from './capabilities.js';
10
12
  export type { OrgCapability } from './capabilities.js';
@@ -1,5 +1,6 @@
1
1
  export { CalimeroClient } from './client.js';
2
- export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, NotFound, TrapError, UnavailableError, errorFrom, } from './errors.js';
2
+ export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, 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
6
  export { DEFAULT_ORG_CAPABILITIES, ORG_CAPABILITIES, orgCapabilities } from './capabilities.js';