@calimero-network/mero-js 29.0.0 → 29.2.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 +2 -1
- package/dist/cloud-v2/client.d.ts +110 -7
- package/dist/cloud-v2/client.js +78 -10
- package/dist/cloud-v2/errors.d.ts +30 -0
- package/dist/cloud-v2/errors.js +53 -0
- 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 +124 -11
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +124 -11
- package/dist/index.mjs.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,6 +98,7 @@ Pinned measurements go through `policy.verifyQuote` (`createQuoteVerifier`).
|
|
|
98
98
|
## The API
|
|
99
99
|
|
|
100
100
|
- **Credentials**: `signUp`, `signIn`, `refresh`, `signOut`, `signOutEverywhere`, `useSession`, `useApiKey`, `me`, `usage`, `addPasskey`, `labelPasskey`, `removePasskey`, `createApiKey`, `listApiKeys`, `revokeApiKey`. Adding or removing a passkey and creating an API key are approved with a passkey the account already has.
|
|
101
|
+
- **Package origins**: `packageOrigins.list`, `packageOrigins.add`, `packageOrigins.remove`. A package's managers register the web origins of a frontend they host themselves (approved with a passkey); `signUp` and `signIn` on such a page send its origin, sign for that origin's relying-party id, and open a session bound to the package (`me()` answers its `app` and `origin`). An unregistered origin is refused with `OriginNotRegistered`.
|
|
101
102
|
- **Packages**: `installPackage`, `uploadPackage`, `packages`, `package`, `uninstallPackage`; `uploadBundle` (raw WASM, development clusters only).
|
|
102
103
|
- **Apps**: `createApp`, `listApps`, `getApp`, `deleteApp`, `setAccess`, `setAppMetadata`, `appStorage`, `appAbi`, `upgradeApp`, `transferApp`.
|
|
103
104
|
- **Calls**: `call`, `callConfirmed`, `view`, `events`. A call always carries an idempotency key, and is sent again with it while the node answers `503`, then to the next node.
|
|
@@ -110,7 +111,7 @@ Pinned measurements go through `policy.verifyQuote` (`createQuoteVerifier`).
|
|
|
110
111
|
|
|
111
112
|
Refusals are typed (`LoginRequired`, `WrongNode`, `NotFound`, `ConfirmRequired`, `ConfirmCancelled`,
|
|
112
113
|
`ArgsTooLarge`, `IdempotencyMismatch`, `ReleaseDeadlineError`, `ConsentStale`, `AppError`, `TrapError`,
|
|
113
|
-
`UnavailableError`),
|
|
114
|
+
`UnavailableError`, `OriginNotRegistered`, `BadOrigin`, `OriginTaken`, `QuotaExceeded`),
|
|
114
115
|
all extending `CalimeroError` with the node's `status` and `code`. A `401` once
|
|
115
116
|
the node that issued the session is replaced or out of reach is answered by one
|
|
116
117
|
refresh and a repeat; a `421 WRONG_NODE` by moving to the next of the `nodes` the client was
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { type AttestationDoc, type CloudPolicy } from './attestation.js';
|
|
13
13
|
import { type PasskeyProvider } from './passkey.js';
|
|
14
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
|
-
export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
15
|
+
export { AppError, ArgsTooLarge, BadOrigin, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, OriginNotRegistered, OriginTaken, QuotaExceeded, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
16
16
|
export type { Committed } from './errors.js';
|
|
17
17
|
export interface CalimeroSession {
|
|
18
18
|
accountId: string;
|
|
@@ -271,6 +271,73 @@ export declare function frontendManifest(origin?: string, fetcher?: typeof fetch
|
|
|
271
271
|
* not opened through a deployment. `href` defaults to `window.location.href`.
|
|
272
272
|
*/
|
|
273
273
|
export declare function pageDeployment(href?: string): string | null;
|
|
274
|
+
/** `GET /auth/me`: who the credential is. */
|
|
275
|
+
export interface MeInfo extends Record<string, unknown> {
|
|
276
|
+
accountId?: string;
|
|
277
|
+
/** `session` or `apikey`. */
|
|
278
|
+
via?: string;
|
|
279
|
+
/**
|
|
280
|
+
* The package the session is bound to: opened on an app's frontend or on
|
|
281
|
+
* an origin its manager registered ({@link CalimeroClient.packageOrigins}).
|
|
282
|
+
* `null` (or absent, on an older node) for an unbound session.
|
|
283
|
+
*/
|
|
284
|
+
app?: string | null;
|
|
285
|
+
/** The web origin the session was opened on, when the node recorded one. */
|
|
286
|
+
origin?: string | null;
|
|
287
|
+
}
|
|
288
|
+
/** One web origin registered for a package (`GET /package-origins/{package}`). */
|
|
289
|
+
export interface PackageOrigin {
|
|
290
|
+
/** `scheme://host[:port]`. */
|
|
291
|
+
origin: string;
|
|
292
|
+
/** The WebAuthn relying-party id passkeys made there are bound to. */
|
|
293
|
+
rpId: string;
|
|
294
|
+
/** The account that registered it. */
|
|
295
|
+
addedBy: string;
|
|
296
|
+
addedAt: string | number;
|
|
297
|
+
}
|
|
298
|
+
/** What registering an origin answers. */
|
|
299
|
+
export interface PackageOriginAdded extends PackageOrigin {
|
|
300
|
+
package: string;
|
|
301
|
+
}
|
|
302
|
+
/** What removing an origin answers. */
|
|
303
|
+
export interface PackageOriginRemoved {
|
|
304
|
+
package: string;
|
|
305
|
+
origin: string;
|
|
306
|
+
removed: true;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* The web origins a package's frontend may sign users in from besides the
|
|
310
|
+
* cluster's own, so a developer can host it themselves. A session opened on
|
|
311
|
+
* one is bound to the package. For the package's managers.
|
|
312
|
+
*/
|
|
313
|
+
export interface PackageOrigins {
|
|
314
|
+
/** The origins registered for `pkg`. `NotFound` for an unknown package; `403` to anyone not managing it. */
|
|
315
|
+
list(pkg: string): Promise<PackageOrigin[]>;
|
|
316
|
+
/**
|
|
317
|
+
* Register `origin` for `pkg`, approved with `passkey` (`412
|
|
318
|
+
* CONFIRM_REQUIRED` over `__add_origin`; without a passkey it reaches the
|
|
319
|
+
* caller as {@link ConfirmRequired}). `rpId` defaults to the node's choice
|
|
320
|
+
* for the origin (its host). Refusals: {@link BadOrigin} (`BAD_ORIGIN`,
|
|
321
|
+
* `BAD_RP_ID`), {@link OriginTaken}, {@link QuotaExceeded}.
|
|
322
|
+
*/
|
|
323
|
+
add(pkg: string, origin: string, passkey?: PasskeyProvider, options?: {
|
|
324
|
+
rpId?: string;
|
|
325
|
+
}): Promise<PackageOriginAdded>;
|
|
326
|
+
/**
|
|
327
|
+
* Remove `origin` from `pkg`, approved with `passkey` (`__remove_origin`).
|
|
328
|
+
* Sessions opened there stop working (`401`). `NotFound` if it was not registered.
|
|
329
|
+
*/
|
|
330
|
+
remove(pkg: string, origin: string, passkey?: PasskeyProvider): Promise<PackageOriginRemoved>;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Where a sign-up or sign-in says it runs. By default the page's origin
|
|
334
|
+
* (`window.location.origin`) when it is not the origin of a node the client
|
|
335
|
+
* talks to; nothing outside a browser. A string sends that origin; `null`
|
|
336
|
+
* sends none (the cluster's own origins).
|
|
337
|
+
*/
|
|
338
|
+
export interface SignInOptions {
|
|
339
|
+
origin?: string | null;
|
|
340
|
+
}
|
|
274
341
|
/**
|
|
275
342
|
* How a call or a view is sent again while the node is unavailable (D70): with
|
|
276
343
|
* the same key, after a backoff that starts at `baseDelayMs` and doubles up to
|
|
@@ -447,12 +514,29 @@ export declare class CalimeroClient {
|
|
|
447
514
|
delete<T = Record<string, unknown>>(path: string, body?: unknown): Promise<T>;
|
|
448
515
|
/**
|
|
449
516
|
* Create an account with a new passkey, and sign in. The node then asks the
|
|
450
|
-
* new passkey to sign the account it creates (`412 CONFIRM_REQUIRED
|
|
451
|
-
*
|
|
517
|
+
* new passkey to sign the account it creates (`412 CONFIRM_REQUIRED`), so a
|
|
518
|
+
* sign-up prompts twice: create, then sign. On a page whose origin is not
|
|
519
|
+
* the cluster's ({@link SignInOptions}), the node makes the passkey for that
|
|
520
|
+
* origin's relying party (the confirmation's `rpId` is that origin's too)
|
|
521
|
+
* and binds the session to the package the origin is registered for; an
|
|
522
|
+
* unregistered origin is refused with {@link OriginNotRegistered}.
|
|
523
|
+
*/
|
|
524
|
+
signUp(passkey: PasskeyProvider, name: string, options?: SignInOptions): Promise<CalimeroSession>;
|
|
525
|
+
/**
|
|
526
|
+
* Sign in with an existing passkey. On a page whose origin is not the
|
|
527
|
+
* cluster's ({@link SignInOptions}), the assertion is made for that
|
|
528
|
+
* origin's relying-party id, as the node answers it, and the session is
|
|
529
|
+
* bound to the origin's package; an unregistered origin is refused with
|
|
530
|
+
* {@link OriginNotRegistered}.
|
|
452
531
|
*/
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
|
|
532
|
+
signIn(passkey: PasskeyProvider, options?: SignInOptions): Promise<CalimeroSession>;
|
|
533
|
+
/**
|
|
534
|
+
* The origin a sign-up or sign-in sends: the one given, or the page's own
|
|
535
|
+
* when it is not a node's origin; `undefined` for none.
|
|
536
|
+
*/
|
|
537
|
+
private pageOrigin;
|
|
538
|
+
/** POST a ceremony's `begin`, naming the page's `origin` in an {@link OriginNotRegistered} the node leaves it out of. */
|
|
539
|
+
private begin;
|
|
456
540
|
/**
|
|
457
541
|
* Swap the refresh token for a new session, on whichever node the client
|
|
458
542
|
* uses: any node of the cluster takes it. A refresh token is used once, so
|
|
@@ -464,7 +548,8 @@ export declare class CalimeroClient {
|
|
|
464
548
|
signOut(): Promise<void>;
|
|
465
549
|
/** End every session of the signed-in account, on every device, this one too. */
|
|
466
550
|
signOutEverywhere(): Promise<void>;
|
|
467
|
-
|
|
551
|
+
/** Who the credential is: the account, how it signed in, and the package (`app`) and `origin` a session is bound to. */
|
|
552
|
+
me(): Promise<MeInfo>;
|
|
468
553
|
/**
|
|
469
554
|
* Add another passkey (another device, `passkey`) to the signed-in account;
|
|
470
555
|
* answers its credential id. The node asks for the approval of a passkey
|
|
@@ -491,6 +576,12 @@ export declare class CalimeroClient {
|
|
|
491
576
|
* Create an API key for an agent or server, approved with the account's
|
|
492
577
|
* `passkey` (`412 CONFIRM_REQUIRED`); needs a passkey session (an API key
|
|
493
578
|
* is refused `403`). The key is returned once.
|
|
579
|
+
*
|
|
580
|
+
* `upgrades: { app, package? }` makes an upgrade key, for CI: it upgrades
|
|
581
|
+
* that one app to signed releases of its package (default: the one the app
|
|
582
|
+
* runs, by that package's pinned signer) with {@link upgradeApp} and no
|
|
583
|
+
* passkey, and every other request with it is refused
|
|
584
|
+
* `403 UPGRADE_KEY_ONLY`. It takes no other scope field.
|
|
494
585
|
*/
|
|
495
586
|
createApiKey(options: {
|
|
496
587
|
label?: string;
|
|
@@ -499,6 +590,10 @@ export declare class CalimeroClient {
|
|
|
499
590
|
readOnly?: boolean;
|
|
500
591
|
allowConfirm?: boolean;
|
|
501
592
|
ttlSecs?: number;
|
|
593
|
+
upgrades?: {
|
|
594
|
+
app: string;
|
|
595
|
+
package?: string;
|
|
596
|
+
};
|
|
502
597
|
}, passkey: PasskeyProvider): Promise<{
|
|
503
598
|
keyId: string;
|
|
504
599
|
key: string;
|
|
@@ -588,6 +683,8 @@ export declare class CalimeroClient {
|
|
|
588
683
|
* `passkey` gives. Refused (`403`) to a session opened on an app's
|
|
589
684
|
* frontend: an app asks its user with {@link requestConsent} instead. Past
|
|
590
685
|
* a release deadline its approver has not met: {@link ReleaseDeadlineError}.
|
|
686
|
+
* With an upgrade key ({@link createApiKey} `upgrades`) pass no passkey and
|
|
687
|
+
* a `version` of the key's package: the key's own proof stands in for it.
|
|
591
688
|
*/
|
|
592
689
|
upgradeApp(app: string, target: {
|
|
593
690
|
version?: string;
|
|
@@ -861,6 +958,12 @@ export declare class CalimeroClient {
|
|
|
861
958
|
uses?: number;
|
|
862
959
|
}): Promise<string>;
|
|
863
960
|
redeemInvite(token: string): Promise<Record<string, unknown>>;
|
|
961
|
+
/**
|
|
962
|
+
* The web origins `{package}`'s managers registered so a frontend they host
|
|
963
|
+
* themselves can sign users in with passkeys ({@link PackageOrigins}).
|
|
964
|
+
* Adding and removing one is approved with a passkey.
|
|
965
|
+
*/
|
|
966
|
+
readonly packageOrigins: PackageOrigins;
|
|
864
967
|
/**
|
|
865
968
|
* Let an account or organization install apps where the cluster's
|
|
866
969
|
* deployments are `granted`, until `until` (RFC 3339 or a `Date`; absent,
|
package/dist/cloud-v2/client.js
CHANGED
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
import { SealedTransportError, createSealedFetch } from '../sealed/sealed.js';
|
|
13
13
|
import { fetchAttestedKey } from './attestation.js';
|
|
14
14
|
import { DEFAULT_DIRECTORY, orderNodes, readDirectory } from './directory.js';
|
|
15
|
-
import { CalimeroError, ConfirmCancelled, ConfirmRequired, LoginRequired, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
15
|
+
import { CalimeroError, ConfirmCancelled, ConfirmRequired, LoginRequired, OriginNotRegistered, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
16
16
|
import { b64url, fromB64url } from './passkey.js';
|
|
17
17
|
import { confirmationCode, pageQuery, pendingApprovalsFrom, } from './approvals.js';
|
|
18
|
-
export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
18
|
+
export { AppError, ArgsTooLarge, BadOrigin, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, OriginNotRegistered, OriginTaken, QuotaExceeded, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
19
19
|
/** A deployer's key, as `GET /deployers` lists it and `DELETE /deployers/{key}` takes it. */
|
|
20
20
|
export function deployerKey(deployer) {
|
|
21
21
|
return 'account' in deployer ? `account:${deployer.account}` : `org:${deployer.org}`;
|
|
@@ -186,6 +186,20 @@ export class CalimeroClient {
|
|
|
186
186
|
this.channels = new Map();
|
|
187
187
|
/** Rejections of the underlying `fetch` itself: the node could not be reached or dropped the connection. */
|
|
188
188
|
this.networkFailures = new WeakSet();
|
|
189
|
+
// ---------------------------------------------------------------- package origins
|
|
190
|
+
/**
|
|
191
|
+
* The web origins `{package}`'s managers registered so a frontend they host
|
|
192
|
+
* themselves can sign users in with passkeys ({@link PackageOrigins}).
|
|
193
|
+
* Adding and removing one is approved with a passkey.
|
|
194
|
+
*/
|
|
195
|
+
this.packageOrigins = {
|
|
196
|
+
list: async (pkg) => {
|
|
197
|
+
const { origins } = await this.get(`package-origins/${seg(pkg)}`);
|
|
198
|
+
return origins ?? [];
|
|
199
|
+
},
|
|
200
|
+
add: (pkg, origin, passkey, options = {}) => this.confirmed('POST', `package-origins/${seg(pkg)}`, options.rpId === undefined ? { origin } : { origin, rpId: options.rpId }, passkey),
|
|
201
|
+
remove: (pkg, origin, passkey) => this.confirmed('DELETE', `package-origins/${seg(pkg)}`, { origin }, passkey),
|
|
202
|
+
};
|
|
189
203
|
const trim = (url) => url.replace(/\/+$/, '');
|
|
190
204
|
this.nodeUrls = [...new Set([options.baseUrl, ...(options.nodes ?? [])].map(trim))];
|
|
191
205
|
this.policy = options.policy;
|
|
@@ -442,20 +456,33 @@ export class CalimeroClient {
|
|
|
442
456
|
// ---------------------------------------------------------------- identity
|
|
443
457
|
/**
|
|
444
458
|
* Create an account with a new passkey, and sign in. The node then asks the
|
|
445
|
-
* new passkey to sign the account it creates (`412 CONFIRM_REQUIRED
|
|
446
|
-
*
|
|
459
|
+
* new passkey to sign the account it creates (`412 CONFIRM_REQUIRED`), so a
|
|
460
|
+
* sign-up prompts twice: create, then sign. On a page whose origin is not
|
|
461
|
+
* the cluster's ({@link SignInOptions}), the node makes the passkey for that
|
|
462
|
+
* origin's relying party (the confirmation's `rpId` is that origin's too)
|
|
463
|
+
* and binds the session to the package the origin is registered for; an
|
|
464
|
+
* unregistered origin is refused with {@link OriginNotRegistered}.
|
|
447
465
|
*/
|
|
448
|
-
async signUp(passkey, name) {
|
|
449
|
-
const
|
|
466
|
+
async signUp(passkey, name, options = {}) {
|
|
467
|
+
const origin = this.pageOrigin(options);
|
|
468
|
+
const begin = await this.begin('auth/passkey/register/begin', origin === undefined ? { name } : { name, origin }, origin);
|
|
450
469
|
const registration = await passkey.create(begin.options);
|
|
451
470
|
const session = await this.postConfirmed('auth/passkey/register/finish', { challengeId: begin.challengeId, registration }, passkey);
|
|
452
471
|
this.useSession(session);
|
|
453
472
|
return session;
|
|
454
473
|
}
|
|
455
|
-
/**
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
474
|
+
/**
|
|
475
|
+
* Sign in with an existing passkey. On a page whose origin is not the
|
|
476
|
+
* cluster's ({@link SignInOptions}), the assertion is made for that
|
|
477
|
+
* origin's relying-party id, as the node answers it, and the session is
|
|
478
|
+
* bound to the origin's package; an unregistered origin is refused with
|
|
479
|
+
* {@link OriginNotRegistered}.
|
|
480
|
+
*/
|
|
481
|
+
async signIn(passkey, options = {}) {
|
|
482
|
+
const origin = this.pageOrigin(options);
|
|
483
|
+
const begin = await this.begin('auth/passkey/login/begin', origin === undefined ? undefined : { origin }, origin);
|
|
484
|
+
const rpId = begin.options.rpId ?? begin.options.rp?.id ?? '';
|
|
485
|
+
const assertion = await passkey.get(fromB64url(begin.options.challenge), rpId);
|
|
459
486
|
const session = await this.post('auth/passkey/login/finish', {
|
|
460
487
|
challengeId: begin.challengeId,
|
|
461
488
|
assertion,
|
|
@@ -463,6 +490,38 @@ export class CalimeroClient {
|
|
|
463
490
|
this.useSession(session);
|
|
464
491
|
return session;
|
|
465
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* The origin a sign-up or sign-in sends: the one given, or the page's own
|
|
495
|
+
* when it is not a node's origin; `undefined` for none.
|
|
496
|
+
*/
|
|
497
|
+
pageOrigin(options) {
|
|
498
|
+
if (options.origin !== undefined)
|
|
499
|
+
return options.origin ?? undefined;
|
|
500
|
+
const page = globalThis.location?.origin;
|
|
501
|
+
if (!page || page === 'null')
|
|
502
|
+
return undefined;
|
|
503
|
+
const nodes = new Set(this.nodeUrls.map((url) => {
|
|
504
|
+
try {
|
|
505
|
+
return new URL(url).origin;
|
|
506
|
+
}
|
|
507
|
+
catch {
|
|
508
|
+
return url;
|
|
509
|
+
}
|
|
510
|
+
}));
|
|
511
|
+
return nodes.has(page) ? undefined : page;
|
|
512
|
+
}
|
|
513
|
+
/** POST a ceremony's `begin`, naming the page's `origin` in an {@link OriginNotRegistered} the node leaves it out of. */
|
|
514
|
+
async begin(path, body, origin) {
|
|
515
|
+
try {
|
|
516
|
+
return await this.post(path, body);
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
if (error instanceof OriginNotRegistered && !error.origin && origin !== undefined) {
|
|
520
|
+
throw new OriginNotRegistered(error.nodeMessage, { ...error.details, origin });
|
|
521
|
+
}
|
|
522
|
+
throw error;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
466
525
|
/**
|
|
467
526
|
* Swap the refresh token for a new session, on whichever node the client
|
|
468
527
|
* uses: any node of the cluster takes it. A refresh token is used once, so
|
|
@@ -514,6 +573,7 @@ export class CalimeroClient {
|
|
|
514
573
|
this.auth = undefined;
|
|
515
574
|
this.current = undefined;
|
|
516
575
|
}
|
|
576
|
+
/** Who the credential is: the account, how it signed in, and the package (`app`) and `origin` a session is bound to. */
|
|
517
577
|
me() {
|
|
518
578
|
return this.get('auth/me');
|
|
519
579
|
}
|
|
@@ -565,6 +625,12 @@ export class CalimeroClient {
|
|
|
565
625
|
* Create an API key for an agent or server, approved with the account's
|
|
566
626
|
* `passkey` (`412 CONFIRM_REQUIRED`); needs a passkey session (an API key
|
|
567
627
|
* is refused `403`). The key is returned once.
|
|
628
|
+
*
|
|
629
|
+
* `upgrades: { app, package? }` makes an upgrade key, for CI: it upgrades
|
|
630
|
+
* that one app to signed releases of its package (default: the one the app
|
|
631
|
+
* runs, by that package's pinned signer) with {@link upgradeApp} and no
|
|
632
|
+
* passkey, and every other request with it is refused
|
|
633
|
+
* `403 UPGRADE_KEY_ONLY`. It takes no other scope field.
|
|
568
634
|
*/
|
|
569
635
|
createApiKey(options, passkey) {
|
|
570
636
|
return this.postConfirmed('auth/apikeys', { ...options }, passkey);
|
|
@@ -706,6 +772,8 @@ export class CalimeroClient {
|
|
|
706
772
|
* `passkey` gives. Refused (`403`) to a session opened on an app's
|
|
707
773
|
* frontend: an app asks its user with {@link requestConsent} instead. Past
|
|
708
774
|
* a release deadline its approver has not met: {@link ReleaseDeadlineError}.
|
|
775
|
+
* With an upgrade key ({@link createApiKey} `upgrades`) pass no passkey and
|
|
776
|
+
* a `version` of the key's package: the key's own proof stands in for it.
|
|
709
777
|
*/
|
|
710
778
|
upgradeApp(app, target, passkey) {
|
|
711
779
|
const path = `apps/${seg(app)}/upgrade`;
|
|
@@ -100,6 +100,36 @@ export declare class ReleaseDeadlineError extends CalimeroError {
|
|
|
100
100
|
export declare class ConsentStale extends CalimeroError {
|
|
101
101
|
constructor(message: string, details?: Record<string, unknown>);
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* `403 ORIGIN_NOT_REGISTERED`: a sign-up or sign-in started on a web origin
|
|
105
|
+
* the cluster does not know: neither the cluster's own nor one a package's
|
|
106
|
+
* manager registered (`packageOrigins.add`). `origin` is the page's origin
|
|
107
|
+
* and `package` the package it was expected to be registered for, when known.
|
|
108
|
+
*/
|
|
109
|
+
export declare class OriginNotRegistered extends CalimeroError {
|
|
110
|
+
readonly origin: string;
|
|
111
|
+
readonly package: string;
|
|
112
|
+
/** What the node said, if anything. */
|
|
113
|
+
readonly nodeMessage: string;
|
|
114
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* `400 BAD_ORIGIN` or `400 BAD_RP_ID`: the node does not accept the origin a
|
|
118
|
+
* package's manager tried to register (it must be a bare web origin,
|
|
119
|
+
* `scheme://host[:port]`), or the relying-party id given for it (which must
|
|
120
|
+
* fit the origin's host). `code` says which.
|
|
121
|
+
*/
|
|
122
|
+
export declare class BadOrigin extends CalimeroError {
|
|
123
|
+
constructor(code: 'BAD_ORIGIN' | 'BAD_RP_ID', message: string, details?: Record<string, unknown>);
|
|
124
|
+
}
|
|
125
|
+
/** `409 ORIGIN_TAKEN`: the origin is registered already (for this package or another). */
|
|
126
|
+
export declare class OriginTaken extends CalimeroError {
|
|
127
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
128
|
+
}
|
|
129
|
+
/** `429 QUOTA_EXCEEDED`: the caller holds as many of something (origins, blobs, ...) as it may. */
|
|
130
|
+
export declare class QuotaExceeded extends CalimeroError {
|
|
131
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
132
|
+
}
|
|
103
133
|
/**
|
|
104
134
|
* `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared
|
|
105
135
|
* error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was
|
package/dist/cloud-v2/errors.js
CHANGED
|
@@ -128,6 +128,50 @@ export class ConsentStale extends CalimeroError {
|
|
|
128
128
|
this.name = 'ConsentStale';
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* `403 ORIGIN_NOT_REGISTERED`: a sign-up or sign-in started on a web origin
|
|
133
|
+
* the cluster does not know: neither the cluster's own nor one a package's
|
|
134
|
+
* manager registered (`packageOrigins.add`). `origin` is the page's origin
|
|
135
|
+
* and `package` the package it was expected to be registered for, when known.
|
|
136
|
+
*/
|
|
137
|
+
export class OriginNotRegistered extends CalimeroError {
|
|
138
|
+
constructor(message, details = {}) {
|
|
139
|
+
const origin = typeof details.origin === 'string' ? details.origin : '';
|
|
140
|
+
const pkg = typeof details.package === 'string' ? details.package : '';
|
|
141
|
+
const site = origin ? `this site (${origin})` : 'this site';
|
|
142
|
+
super(403, 'ORIGIN_NOT_REGISTERED', `${site} is not registered for ${pkg || 'any package'}${message ? ` (${message})` : ''}`, details);
|
|
143
|
+
this.name = 'OriginNotRegistered';
|
|
144
|
+
this.origin = origin;
|
|
145
|
+
this.package = pkg;
|
|
146
|
+
this.nodeMessage = message;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* `400 BAD_ORIGIN` or `400 BAD_RP_ID`: the node does not accept the origin a
|
|
151
|
+
* package's manager tried to register (it must be a bare web origin,
|
|
152
|
+
* `scheme://host[:port]`), or the relying-party id given for it (which must
|
|
153
|
+
* fit the origin's host). `code` says which.
|
|
154
|
+
*/
|
|
155
|
+
export class BadOrigin extends CalimeroError {
|
|
156
|
+
constructor(code, message, details = {}) {
|
|
157
|
+
super(400, code, message, details);
|
|
158
|
+
this.name = 'BadOrigin';
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** `409 ORIGIN_TAKEN`: the origin is registered already (for this package or another). */
|
|
162
|
+
export class OriginTaken extends CalimeroError {
|
|
163
|
+
constructor(message, details = {}) {
|
|
164
|
+
super(409, 'ORIGIN_TAKEN', message, details);
|
|
165
|
+
this.name = 'OriginTaken';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/** `429 QUOTA_EXCEEDED`: the caller holds as many of something (origins, blobs, ...) as it may. */
|
|
169
|
+
export class QuotaExceeded extends CalimeroError {
|
|
170
|
+
constructor(message, details = {}) {
|
|
171
|
+
super(429, 'QUOTA_EXCEEDED', message, details);
|
|
172
|
+
this.name = 'QuotaExceeded';
|
|
173
|
+
}
|
|
174
|
+
}
|
|
131
175
|
/**
|
|
132
176
|
* `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared
|
|
133
177
|
* error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was
|
|
@@ -212,6 +256,15 @@ export function errorFrom(status, body, retryAfterHeader) {
|
|
|
212
256
|
return new ReleaseDeadlineError(message, details);
|
|
213
257
|
case '409 CONSENT_STALE':
|
|
214
258
|
return new ConsentStale(message, details);
|
|
259
|
+
case '403 ORIGIN_NOT_REGISTERED':
|
|
260
|
+
return new OriginNotRegistered(message, details);
|
|
261
|
+
case '400 BAD_ORIGIN':
|
|
262
|
+
case '400 BAD_RP_ID':
|
|
263
|
+
return new BadOrigin(code, message, details);
|
|
264
|
+
case '409 ORIGIN_TAKEN':
|
|
265
|
+
return new OriginTaken(message, details);
|
|
266
|
+
case '429 QUOTA_EXCEEDED':
|
|
267
|
+
return new QuotaExceeded(message, details);
|
|
215
268
|
case '412 CONFIRM_REQUIRED':
|
|
216
269
|
return new ConfirmRequired(message, details);
|
|
217
270
|
case '413 ARGS_TOO_LARGE':
|
package/dist/cloud-v2/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { CalimeroClient, deployerKey, frontendManifest, pageDeployment } from './client.js';
|
|
2
2
|
export { DEFAULT_DIRECTORY, DirectoryError } from './directory.js';
|
|
3
3
|
export type { DirectoryFailure } from './directory.js';
|
|
4
|
-
export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
4
|
+
export { AppError, ArgsTooLarge, BadOrigin, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, OriginNotRegistered, OriginTaken, QuotaExceeded, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
5
5
|
export type { Committed } from './errors.js';
|
|
6
|
-
export type { AppInfo, AppXcalls, BlobContent, BlobInfo, DeadLetter, Deployer, DeployerGrant, DeployersInfo, DeploymentInfo, DeploymentOffer, DeploymentOrgs, FrontendManifest, PublicDeployment, CallResult, CalimeroClientOptions, CalimeroConnectOptions, CloudEvent, CalimeroSession, PackageInfo, PackageInstalled, CloudRetryOptions, OrgInfo, OrgUpgradeTarget, PresenceEntry, UpgradeRun, ViewResult, } from './client.js';
|
|
6
|
+
export type { AppInfo, AppXcalls, BlobContent, BlobInfo, DeadLetter, Deployer, DeployerGrant, DeployersInfo, DeploymentInfo, DeploymentOffer, DeploymentOrgs, FrontendManifest, MeInfo, PackageOrigin, PackageOriginAdded, PackageOriginRemoved, PackageOrigins, SignInOptions, PublicDeployment, CallResult, CalimeroClientOptions, CalimeroConnectOptions, CloudEvent, CalimeroSession, PackageInfo, PackageInstalled, CloudRetryOptions, OrgInfo, OrgUpgradeTarget, PresenceEntry, UpgradeRun, ViewResult, } from './client.js';
|
|
7
7
|
export { claimedRelease, fetchAttestedKey, freshCollateral, MOCK_QUOTE_HEADER } from './attestation.js';
|
|
8
8
|
export type { AttestationDoc, CloudPolicy, CloudReleasePolicy } from './attestation.js';
|
|
9
9
|
export { browserPasskey, b64url, fromB64url } from './passkey.js';
|
package/dist/cloud-v2/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { CalimeroClient, deployerKey, frontendManifest, pageDeployment } from './client.js';
|
|
2
2
|
export { DEFAULT_DIRECTORY, DirectoryError } from './directory.js';
|
|
3
|
-
export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
3
|
+
export { AppError, ArgsTooLarge, BadOrigin, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, ConsentStale, NotFound, OriginNotRegistered, OriginTaken, QuotaExceeded, ReleaseDeadlineError, TrapError, UnavailableError, WrongNode, errorFrom, } from './errors.js';
|
|
4
4
|
export { claimedRelease, fetchAttestedKey, freshCollateral, MOCK_QUOTE_HEADER } from './attestation.js';
|
|
5
5
|
export { browserPasskey, b64url, fromB64url } from './passkey.js';
|
|
6
6
|
export { MAX_REPORT_PAGE, RELEASE_VERIFIER, compareVersions, confirmationCode, consentReturn, pageQuery, pendingApprovalsFrom, publisherBindingBytes, publisherBindingMessage, releaseConsent, releaseNotesUrl, stalledBy, upgradeConsent, verifyReleaseUrl, withdrawConsent, } from './approvals.js';
|