@calimero-network/mero-js 27.5.0 → 28.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cloud-v2/client.d.ts +46 -17
- package/dist/cloud-v2/client.js +56 -30
- package/dist/index.browser.mjs +3 -3
- package/dist/index.browser.mjs.map +3 -3
- package/dist/index.cjs +64 -30
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +64 -30
- package/dist/index.mjs.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,12 +97,12 @@ Pinned measurements go through `policy.verifyQuote` (`createQuoteVerifier`).
|
|
|
97
97
|
|
|
98
98
|
## The API
|
|
99
99
|
|
|
100
|
-
- **Credentials**: `signUp`, `signIn`, `refresh`, `signOut`, `signOutEverywhere`, `useSession`, `useApiKey`, `me`, `usage`, `addPasskey`, `labelPasskey`, `removePasskey`, `createApiKey`, `listApiKeys`, `revokeApiKey`.
|
|
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
101
|
- **Packages**: `installPackage`, `uploadPackage`, `packages`, `package`, `uninstallPackage`; `uploadBundle` (raw WASM, development clusters only).
|
|
102
102
|
- **Apps**: `createApp`, `listApps`, `getApp`, `deleteApp`, `setAccess`, `setAppMetadata`, `appStorage`, `appAbi`, `upgradeApp`, `transferApp`.
|
|
103
103
|
- **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.
|
|
104
104
|
- **Blobs and presence**: `uploadBlob`, `downloadBlob`, `listBlobs`, `blobInfo`, `deleteBlob`; `publishPresence`, `presence`, `presenceStream`.
|
|
105
|
-
- **Organizations**: `createOrg`, `getOrg`, `deleteOrg`, `setOrgMetadata`, `setMember`, `removeMember`, `setMemberMetadata`, `setCapabilities` (`ORG_CAPABILITIES`), teams, `invite`, `redeemInvite`.
|
|
105
|
+
- **Organizations**: `createOrg`, `getOrg`, `deleteOrg`, `setOrgMetadata`, `setMember`, `removeMember`, `setMemberMetadata`, `setCapabilities` (`ORG_CAPABILITIES`), teams, `invite`, `redeemInvite`. Setting or removing a member or team member, capabilities and invites are approved with the caller's passkey; redeeming an invite is not.
|
|
106
106
|
- **Owner decisions** (passkey approval, never from an app's frontend): `upgradeOrg`, `upgradeRun`, `retryUpgradeRun`, `approveRelease`, `approveOutbound`, `bindPublisher`, `upgradePublished`.
|
|
107
107
|
- **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/).
|
|
108
108
|
- **Operator** (ops token): `opsApps`, `opsOrgs`, `setReleaseDeadline`, `liftReleaseDeadline`.
|
|
@@ -320,10 +320,15 @@ export declare class CalimeroClient {
|
|
|
320
320
|
/** End every session of the signed-in account, on every device, this one too. */
|
|
321
321
|
signOutEverywhere(): Promise<void>;
|
|
322
322
|
me(): Promise<Record<string, unknown>>;
|
|
323
|
-
/**
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
323
|
+
/**
|
|
324
|
+
* Add another passkey (another device, `passkey`) to the signed-in account;
|
|
325
|
+
* answers its credential id. The node asks for the approval of a passkey
|
|
326
|
+
* the account already has (`412 CONFIRM_REQUIRED`, never the new one),
|
|
327
|
+
* which `approver` gives.
|
|
328
|
+
*/
|
|
329
|
+
addPasskey(passkey: PasskeyProvider, approver: PasskeyProvider): Promise<string>;
|
|
330
|
+
/** Remove one of the account's passkeys (not the last), approved with `passkey` (one it has). */
|
|
331
|
+
removePasskey(credentialId: string, passkey: PasskeyProvider): Promise<void>;
|
|
327
332
|
/** Name one of the account's passkeys (a device label); `''` clears the name. */
|
|
328
333
|
labelPasskey(credentialId: string, label: string): Promise<void>;
|
|
329
334
|
/** What this account uses (apps, bundle bytes, API keys, owned orgs), with the cluster's quotas. */
|
|
@@ -336,7 +341,11 @@ export declare class CalimeroClient {
|
|
|
336
341
|
/** The account's API keys (never the keys themselves). */
|
|
337
342
|
listApiKeys(): Promise<Array<Record<string, unknown>>>;
|
|
338
343
|
revokeApiKey(keyId: string): Promise<void>;
|
|
339
|
-
/**
|
|
344
|
+
/**
|
|
345
|
+
* Create an API key for an agent or server, approved with the account's
|
|
346
|
+
* `passkey` (`412 CONFIRM_REQUIRED`); needs a passkey session (an API key
|
|
347
|
+
* is refused `403`). The key is returned once.
|
|
348
|
+
*/
|
|
340
349
|
createApiKey(options: {
|
|
341
350
|
label?: string;
|
|
342
351
|
apps?: string[];
|
|
@@ -344,7 +353,7 @@ export declare class CalimeroClient {
|
|
|
344
353
|
readOnly?: boolean;
|
|
345
354
|
allowConfirm?: boolean;
|
|
346
355
|
ttlSecs?: number;
|
|
347
|
-
}): Promise<{
|
|
356
|
+
}, passkey: PasskeyProvider): Promise<{
|
|
348
357
|
keyId: string;
|
|
349
358
|
key: string;
|
|
350
359
|
}>;
|
|
@@ -418,10 +427,17 @@ export declare class CalimeroClient {
|
|
|
418
427
|
}>;
|
|
419
428
|
/**
|
|
420
429
|
* POST `body` to `path`, answering a `412 CONFIRM_REQUIRED` with `passkey`'s
|
|
421
|
-
* assertion over the node's challenge (deleting an org, approving a release,
|
|
430
|
+
* assertion over the node's challenge (deleting an org, approving a release,
|
|
431
|
+
* adding a member, ...): the same body again, with `confirm`. Without a
|
|
432
|
+
* passkey (a caller in plain JavaScript passing none) the `412` reaches the
|
|
433
|
+
* caller as {@link ConfirmRequired}, carrying the challenge.
|
|
422
434
|
*/
|
|
423
435
|
postConfirmed<T>(path: string, body: Record<string, unknown>, passkey: PasskeyProvider): Promise<T>;
|
|
424
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* {@link postConfirmed} for a DELETE (deleting an organization, removing a
|
|
438
|
+
* member or a passkey): `body` (`{}` by default) goes as JSON, and the
|
|
439
|
+
* confirmed retry carries `confirm` beside it.
|
|
440
|
+
*/
|
|
425
441
|
deleteConfirmed<T>(path: string, passkey: PasskeyProvider, body?: Record<string, unknown>): Promise<T>;
|
|
426
442
|
private confirmed;
|
|
427
443
|
/**
|
|
@@ -612,15 +628,19 @@ export declare class CalimeroClient {
|
|
|
612
628
|
setReleaseDeadline(version: string, after: Date | string): Promise<void>;
|
|
613
629
|
/** Lift a release's deadline. Operator token. */
|
|
614
630
|
liftReleaseDeadline(version: string): Promise<void>;
|
|
615
|
-
/** Add a member, or change their role
|
|
616
|
-
setMember(org: string, account: string, role: 'guest' | 'member' | 'admin' | 'owner'): Promise<void>;
|
|
617
|
-
|
|
631
|
+
/** Add a member, or change their role, approved with the caller's `passkey`. */
|
|
632
|
+
setMember(org: string, account: string, role: 'guest' | 'member' | 'admin' | 'owner', passkey: PasskeyProvider): Promise<void>;
|
|
633
|
+
/**
|
|
634
|
+
* Remove a member, or leave (`account` the caller's own), approved with the
|
|
635
|
+
* caller's `passkey`.
|
|
636
|
+
*/
|
|
637
|
+
removeMember(org: string, account: string, passkey: PasskeyProvider): Promise<Record<string, unknown>>;
|
|
618
638
|
/**
|
|
619
639
|
* Set capability bits ({@link ORG_CAPABILITIES}): for a member (`account`),
|
|
620
640
|
* for a member of one team (`account` and `team`), or the organization's
|
|
621
|
-
* default (neither).
|
|
641
|
+
* default (neither). Approved with the caller's `passkey`.
|
|
622
642
|
*/
|
|
623
|
-
setCapabilities(org: string, capabilities: number, at?: {
|
|
643
|
+
setCapabilities(org: string, capabilities: number, passkey: PasskeyProvider, at?: {
|
|
624
644
|
account?: string;
|
|
625
645
|
team?: string;
|
|
626
646
|
}): Promise<void>;
|
|
@@ -638,14 +658,23 @@ export declare class CalimeroClient {
|
|
|
638
658
|
}): Promise<void>;
|
|
639
659
|
/** Delete a team, the teams below it and their apps. */
|
|
640
660
|
deleteTeam(org: string, team: string): Promise<void>;
|
|
641
|
-
/**
|
|
642
|
-
|
|
661
|
+
/**
|
|
662
|
+
* Add a member to a team, or change their row: role, lead, capability bits.
|
|
663
|
+
* Approved with the caller's `passkey`.
|
|
664
|
+
*/
|
|
665
|
+
setTeamMember(org: string, team: string, account: string, passkey: PasskeyProvider, row?: {
|
|
643
666
|
role?: 'lead' | 'member' | 'readOnly';
|
|
644
667
|
lead?: boolean;
|
|
645
668
|
capabilities?: number;
|
|
646
669
|
}): Promise<void>;
|
|
647
|
-
|
|
648
|
-
|
|
670
|
+
/** Remove a member from a team, approved with the caller's `passkey`. */
|
|
671
|
+
removeTeamMember(org: string, team: string, account: string, passkey: PasskeyProvider): Promise<void>;
|
|
672
|
+
/**
|
|
673
|
+
* Make an invite into `org` (and `teams`), approved with the caller's
|
|
674
|
+
* `passkey`; answers its token, which {@link redeemInvite} takes (no
|
|
675
|
+
* approval there).
|
|
676
|
+
*/
|
|
677
|
+
invite(org: string, role: 'guest' | 'member' | 'admin', passkey: PasskeyProvider, teams?: string[], options?: {
|
|
649
678
|
ttlSecs?: number;
|
|
650
679
|
uses?: number;
|
|
651
680
|
}): Promise<string>;
|
package/dist/cloud-v2/client.js
CHANGED
|
@@ -478,19 +478,21 @@ export class CalimeroClient {
|
|
|
478
478
|
me() {
|
|
479
479
|
return this.get('auth/me');
|
|
480
480
|
}
|
|
481
|
-
/**
|
|
482
|
-
|
|
481
|
+
/**
|
|
482
|
+
* Add another passkey (another device, `passkey`) to the signed-in account;
|
|
483
|
+
* answers its credential id. The node asks for the approval of a passkey
|
|
484
|
+
* the account already has (`412 CONFIRM_REQUIRED`, never the new one),
|
|
485
|
+
* which `approver` gives.
|
|
486
|
+
*/
|
|
487
|
+
async addPasskey(passkey, approver) {
|
|
483
488
|
const begin = await this.post('auth/passkeys/add/begin');
|
|
484
489
|
const registration = await passkey.create(begin.options);
|
|
485
|
-
const { credentialId } = await this.
|
|
486
|
-
challengeId: begin.challengeId,
|
|
487
|
-
registration,
|
|
488
|
-
});
|
|
490
|
+
const { credentialId } = await this.postConfirmed('auth/passkeys/add/finish', { challengeId: begin.challengeId, registration }, approver);
|
|
489
491
|
return credentialId;
|
|
490
492
|
}
|
|
491
|
-
/** Remove one of the account's passkeys (not the last). */
|
|
492
|
-
async removePasskey(credentialId) {
|
|
493
|
-
await this.
|
|
493
|
+
/** Remove one of the account's passkeys (not the last), approved with `passkey` (one it has). */
|
|
494
|
+
async removePasskey(credentialId, passkey) {
|
|
495
|
+
await this.deleteConfirmed(`auth/passkeys/${seg(credentialId)}`, passkey);
|
|
494
496
|
}
|
|
495
497
|
/** Name one of the account's passkeys (a device label); `''` clears the name. */
|
|
496
498
|
async labelPasskey(credentialId, label) {
|
|
@@ -519,9 +521,13 @@ export class CalimeroClient {
|
|
|
519
521
|
async revokeApiKey(keyId) {
|
|
520
522
|
await this.delete(`auth/apikeys/${seg(keyId)}`);
|
|
521
523
|
}
|
|
522
|
-
/**
|
|
523
|
-
|
|
524
|
-
|
|
524
|
+
/**
|
|
525
|
+
* Create an API key for an agent or server, approved with the account's
|
|
526
|
+
* `passkey` (`412 CONFIRM_REQUIRED`); needs a passkey session (an API key
|
|
527
|
+
* is refused `403`). The key is returned once.
|
|
528
|
+
*/
|
|
529
|
+
createApiKey(options, passkey) {
|
|
530
|
+
return this.postConfirmed('auth/apikeys', { ...options }, passkey);
|
|
525
531
|
}
|
|
526
532
|
// ---------------------------------------------------------------- apps
|
|
527
533
|
/** Upload a raw WASM bundle (development clusters only); answers its hash. */
|
|
@@ -631,12 +637,19 @@ export class CalimeroClient {
|
|
|
631
637
|
}
|
|
632
638
|
/**
|
|
633
639
|
* POST `body` to `path`, answering a `412 CONFIRM_REQUIRED` with `passkey`'s
|
|
634
|
-
* assertion over the node's challenge (deleting an org, approving a release,
|
|
640
|
+
* assertion over the node's challenge (deleting an org, approving a release,
|
|
641
|
+
* adding a member, ...): the same body again, with `confirm`. Without a
|
|
642
|
+
* passkey (a caller in plain JavaScript passing none) the `412` reaches the
|
|
643
|
+
* caller as {@link ConfirmRequired}, carrying the challenge.
|
|
635
644
|
*/
|
|
636
645
|
postConfirmed(path, body, passkey) {
|
|
637
646
|
return this.confirmed('POST', path, body, passkey);
|
|
638
647
|
}
|
|
639
|
-
/**
|
|
648
|
+
/**
|
|
649
|
+
* {@link postConfirmed} for a DELETE (deleting an organization, removing a
|
|
650
|
+
* member or a passkey): `body` (`{}` by default) goes as JSON, and the
|
|
651
|
+
* confirmed retry carries `confirm` beside it.
|
|
652
|
+
*/
|
|
640
653
|
deleteConfirmed(path, passkey, body = {}) {
|
|
641
654
|
return this.confirmed('DELETE', path, body, passkey);
|
|
642
655
|
}
|
|
@@ -645,7 +658,7 @@ export class CalimeroClient {
|
|
|
645
658
|
return await send(body);
|
|
646
659
|
}
|
|
647
660
|
catch (error) {
|
|
648
|
-
if (!(error instanceof ConfirmRequired))
|
|
661
|
+
if (!(error instanceof ConfirmRequired) || !passkey)
|
|
649
662
|
throw error;
|
|
650
663
|
const d = error.details;
|
|
651
664
|
let assertion;
|
|
@@ -973,20 +986,24 @@ export class CalimeroClient {
|
|
|
973
986
|
async liftReleaseDeadline(version) {
|
|
974
987
|
await this.delete(`ops/releases/${seg(version)}/deadline`);
|
|
975
988
|
}
|
|
976
|
-
/** Add a member, or change their role
|
|
977
|
-
async setMember(org, account, role) {
|
|
978
|
-
await this.
|
|
989
|
+
/** Add a member, or change their role, approved with the caller's `passkey`. */
|
|
990
|
+
async setMember(org, account, role, passkey) {
|
|
991
|
+
await this.postConfirmed(`orgs/${seg(org)}/members`, { account, role }, passkey);
|
|
979
992
|
}
|
|
980
|
-
|
|
981
|
-
|
|
993
|
+
/**
|
|
994
|
+
* Remove a member, or leave (`account` the caller's own), approved with the
|
|
995
|
+
* caller's `passkey`.
|
|
996
|
+
*/
|
|
997
|
+
removeMember(org, account, passkey) {
|
|
998
|
+
return this.deleteConfirmed(`orgs/${seg(org)}/members/${seg(account)}`, passkey);
|
|
982
999
|
}
|
|
983
1000
|
/**
|
|
984
1001
|
* Set capability bits ({@link ORG_CAPABILITIES}): for a member (`account`),
|
|
985
1002
|
* for a member of one team (`account` and `team`), or the organization's
|
|
986
|
-
* default (neither).
|
|
1003
|
+
* default (neither). Approved with the caller's `passkey`.
|
|
987
1004
|
*/
|
|
988
|
-
async setCapabilities(org, capabilities, at = {}) {
|
|
989
|
-
await this.
|
|
1005
|
+
async setCapabilities(org, capabilities, passkey, at = {}) {
|
|
1006
|
+
await this.postConfirmed(`orgs/${seg(org)}/capabilities`, { capabilities, ...at }, passkey);
|
|
990
1007
|
}
|
|
991
1008
|
async createTeam(org, name, join, parent) {
|
|
992
1009
|
const { teamId } = await this.post(`orgs/${seg(org)}/teams`, { name, join, parent });
|
|
@@ -1006,15 +1023,24 @@ export class CalimeroClient {
|
|
|
1006
1023
|
async deleteTeam(org, team) {
|
|
1007
1024
|
await this.delete(`orgs/${seg(org)}/teams/${seg(team)}`);
|
|
1008
1025
|
}
|
|
1009
|
-
/**
|
|
1010
|
-
|
|
1011
|
-
|
|
1026
|
+
/**
|
|
1027
|
+
* Add a member to a team, or change their row: role, lead, capability bits.
|
|
1028
|
+
* Approved with the caller's `passkey`.
|
|
1029
|
+
*/
|
|
1030
|
+
async setTeamMember(org, team, account, passkey, row = {}) {
|
|
1031
|
+
await this.postConfirmed(`orgs/${seg(org)}/teams/${seg(team)}/members`, { account, ...row }, passkey);
|
|
1012
1032
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1033
|
+
/** Remove a member from a team, approved with the caller's `passkey`. */
|
|
1034
|
+
async removeTeamMember(org, team, account, passkey) {
|
|
1035
|
+
await this.deleteConfirmed(`orgs/${seg(org)}/teams/${seg(team)}/members/${seg(account)}`, passkey);
|
|
1015
1036
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1037
|
+
/**
|
|
1038
|
+
* Make an invite into `org` (and `teams`), approved with the caller's
|
|
1039
|
+
* `passkey`; answers its token, which {@link redeemInvite} takes (no
|
|
1040
|
+
* approval there).
|
|
1041
|
+
*/
|
|
1042
|
+
async invite(org, role, passkey, teams = [], options = {}) {
|
|
1043
|
+
const { token } = await this.postConfirmed(`orgs/${seg(org)}/invites`, { role, teams, ...options }, passkey);
|
|
1018
1044
|
return token;
|
|
1019
1045
|
}
|
|
1020
1046
|
redeemInvite(token) {
|