@calimero-network/mero-js 26.7.0 → 26.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { HttpClient } from '../http-client/index.js';
2
- import type { HealthStatus, ReadinessStatus, AdminAuthStatus, InstallApplicationRequest, InstallApplicationResponseData, InstallDevApplicationRequest, UninstallApplicationResponseData, ListApplicationsResponseData, GetApplicationResponseData, ApplicationVersionEntry, GetApplicationAbiResponseData, GetLatestVersionResponseData, ListPackagesResponseData, ListVersionsResponseData, CreateContextRequest, CreateContextResponseData, DeleteContextResponseData, GetContextsResponseData, Context, GenerateContextIdentityResponseData, GetContextIdentitiesResponseData, JoinContextResponseData, JoinSubgroupInheritanceResponseData, ContextGroupResponseData, ContextStorageResponseData, UpdateContextApplicationRequest, ResyncContextRequest, ResyncContextResponseData, ContextsWithExecutorsResponseData, UploadBlobRequest, UploadBlobResponseData, DeleteBlobResponseData, ListBlobsResponseData, GetBlobInfoResponseData, BlobReadOptions, CreateContextAliasRequest, CreateApplicationAliasRequest, CreateDeviceAliasRequest, CreateAliasResponseData, LookupAliasResponseData, DeleteAliasResponseData, ListAliasesResponseData, ListNamespacesResponseData, CreateNamespaceRequest, CreateNamespaceResponseData, DeleteNamespaceResponseData, CreateNamespaceInvitationRequest, CreateNamespaceInvitationResponseData, CreateRecursiveInvitationResponseData, JoinNamespaceRequest, JoinNamespaceResponseData, CreateGroupInNamespaceRequest, CreateGroupInNamespaceResponseData, SubgroupEntry, Namespace, NodeIdentity, AccountPairInitRequest, AccountPairInitResponseData, AccountPairCompleteRequest, AccountPairCompleteResponseData, AccountSignWithRootRequest, AccountSignWithRootResponseData, RelinkDeviceRequest, RelinkDeviceResponseData, RescopeDeviceRequest, RescopeDeviceResponseData, LabelDeviceRequest, LabelDeviceResponseData, AccountDeviceEntry, AccountApplicationEntry, RevokeAccountDeviceRequest, LinkAccountDeviceRequest, LinkAccountDeviceResponseData, RevokeAccountDeviceResponseData, MemberDevicesEntry, ListMemberDevicesOptions, GroupInfoResponseData, CreateGroupRequest, CreateGroupResponseData, DeleteGroupResponseData, ListGroupMembersResponseData, ListGroupContextsResponseData, AddGroupMembersRequest, RemoveGroupMembersRequest, UpdateMemberRoleRequest, MemberCapabilities, SetMemberCapabilitiesRequest, SetDefaultCapabilitiesRequest, SetMemberAutoFollowRequest, SetSubgroupVisibilityRequest, SetTeeAdmissionPolicyRequest, GetTeeAdmissionPolicyResponseData, SetTeeAuthoringPolicyRequest, TransferOwnershipRequest, ChangeNamespaceAdminRequest, OwnerDeleteGroupRequest, RootGuardedOpRequest, SetGroupMetadataRequest, SetMemberMetadataRequest, SetContextMetadataRequest, MetadataRecord, SyncGroupResponseData, ActivateGroupUpgradeRequest, ActivateGroupUpgradeResponseData, UpgradeGroupRequest, UpgradeGroupResponseData, GroupUpgradeStatusResponseData, MigrationStatus, NamespaceRevokedDevices, CascadeStatusEntry, RetryGroupUpgradeResponseData, ReparentGroupRequest, ReparentGroupResponseData, IssueOwnershipProofRequest, IssueNamespaceOwnershipProofRequest, IssueOwnershipProofResponseData, CreateGroupInvitationRequest, CreateGroupInvitationResponseData, CreateRecursiveGroupInvitationResponseData, JoinGroupRequest, JoinGroupResponseData, TeeInfoResponseData, TeeAttestRequest, TeeAttestResponseData, PerformIntentRequest, PerformIntentResponseData, IntentRelayInfo, QueryContextRequest, QueryContextResponseData, ListMemberDevicesResponseData, SealToAccountRequest, SealedEnvelope, AdmitJoinRequest, AdmitJoinResponseData } from './admin-types.js';
2
+ import type { HealthStatus, ReadinessStatus, AdminAuthStatus, InstallApplicationRequest, InstallApplicationResponseData, InstallDevApplicationRequest, UninstallApplicationResponseData, ListApplicationsResponseData, GetApplicationResponseData, ApplicationVersionEntry, GetApplicationAbiResponseData, GetLatestVersionResponseData, ListPackagesResponseData, ListVersionsResponseData, CreateContextRequest, CreateContextResponseData, DeleteContextResponseData, GetContextsResponseData, Context, GenerateContextIdentityResponseData, GetContextIdentitiesResponseData, JoinContextResponseData, JoinSubgroupInheritanceResponseData, ContextGroupResponseData, ContextStorageResponseData, UpdateContextApplicationRequest, ResyncContextRequest, ResyncContextResponseData, ContextsWithExecutorsResponseData, UploadBlobRequest, UploadBlobResponseData, DeleteBlobResponseData, ListBlobsResponseData, GetBlobInfoResponseData, BlobReadOptions, CreateContextAliasRequest, CreateApplicationAliasRequest, CreateDeviceAliasRequest, CreateAliasResponseData, LookupAliasResponseData, DeleteAliasResponseData, ListAliasesResponseData, ListNamespacesResponseData, CreateNamespaceRequest, CreateNamespaceResponseData, DeleteNamespaceResponseData, CreateNamespaceInvitationRequest, CreateNamespaceInvitationResponseData, CreateRecursiveInvitationResponseData, JoinNamespaceRequest, JoinNamespaceResponseData, CreateGroupInNamespaceRequest, CreateGroupInNamespaceResponseData, SubgroupEntry, Namespace, NodeIdentity, AccountPairInitRequest, AccountPairInitResponseData, AccountPairCompleteRequest, AccountPairCompleteResponseData, AccountSignWithRootRequest, AccountSignWithRootResponseData, RelinkDeviceRequest, RelinkDeviceResponseData, RescopeDeviceRequest, RescopeDeviceResponseData, LabelDeviceRequest, LabelDeviceResponseData, AccountDeviceEntry, AccountApplicationEntry, RevokeAccountDeviceRequest, LinkAccountDeviceRequest, LinkAccountDeviceResponseData, RevokeAccountDeviceResponseData, MemberDevicesEntry, ListMemberDevicesOptions, GroupInfoResponseData, CreateGroupRequest, CreateGroupResponseData, DeleteGroupResponseData, ListGroupMembersResponseData, ListGroupContextsResponseData, AddGroupMembersRequest, RemoveGroupMembersRequest, UpdateMemberRoleRequest, MemberCapabilities, SetMemberCapabilitiesRequest, SetDefaultCapabilitiesRequest, SetMemberAutoFollowRequest, SetSubgroupVisibilityRequest, SetTeeAdmissionPolicyRequest, GetTeeAdmissionPolicyResponseData, SetTeeAuthoringPolicyRequest, TransferOwnershipRequest, ChangeNamespaceAdminRequest, OwnerDeleteGroupRequest, RootGuardedOpRequest, SetGroupMetadataRequest, SetMemberMetadataRequest, SetContextMetadataRequest, MetadataRecord, SyncGroupResponseData, ActivateGroupUpgradeRequest, ActivateGroupUpgradeResponseData, UpgradeGroupRequest, UpgradeGroupResponseData, GroupUpgradeStatusResponseData, MigrationStatus, NamespaceRevokedDevices, CascadeStatusEntry, RetryGroupUpgradeResponseData, ReparentGroupRequest, ReparentGroupResponseData, IssueOwnershipProofRequest, IssueNamespaceOwnershipProofRequest, IssueOwnershipProofResponseData, CreateGroupInvitationRequest, CreateGroupInvitationResponseData, CreateRecursiveGroupInvitationResponseData, JoinGroupRequest, JoinGroupResponseData, TeeInfoResponseData, TeeAttestRequest, TeeAttestResponseData, PerformIntentRequest, PerformIntentResponseData, IntentRelayInfo, QueryContextRequest, QueryContextResponseData, ListMemberDevicesResponseData, SealToAccountRequest, SealedEnvelope, AdmitJoinRequest, AdmitJoinResponseData, CreateAccessGrantRequest, AccessGrant, CreatedAccessGrant, RevokeAccessGrantResponseData, AccessGrantCallRequest, AccessGrantCallResponseData } from './admin-types.js';
3
3
  import { type RedeemOutcome } from './redeem-invitation.js';
4
4
  /**
5
5
  * Compare two version strings by SemVer 2.0 precedence, ascending: negative if
@@ -174,6 +174,27 @@ export declare class AdminApiClient {
174
174
  * {@link performIntent}).
175
175
  */
176
176
  queryContext(contextId: string, request: QueryContextRequest): Promise<QueryContextResponseData>;
177
+ /**
178
+ * Issue an access grant: a token whose holder may call `request.methods` in
179
+ * `contextId`, as this node, with no session of its own.
180
+ *
181
+ * A grant only narrows: each method must be one this session's own token may
182
+ * execute in the context (`403` otherwise), and an account session is refused
183
+ * (`403`), since a granted call runs as the node. The token is in the answer
184
+ * once and never again; the node keeps only its hash.
185
+ */
186
+ createAccessGrant(contextId: string, request: CreateAccessGrantRequest): Promise<CreatedAccessGrant>;
187
+ /** The access grants of `contextId` this session could have issued. */
188
+ listAccessGrants(contextId: string): Promise<AccessGrant[]>;
189
+ /** Revoke an access grant. A grant this session cannot see is a `404`. */
190
+ revokeAccessGrant(contextId: string, grantId: string): Promise<RevokeAccessGrantResponseData>;
191
+ /**
192
+ * Call one method under an access grant. The token is the whole credential:
193
+ * the route is public on every node, so this works from a client holding no
194
+ * session at all. A method the grant does not name, an unknown or revoked
195
+ * token, and an expired grant are each a `403`.
196
+ */
197
+ callWithAccessGrant(contextId: string, request: AccessGrantCallRequest): Promise<AccessGrantCallResponseData>;
177
198
  /**
178
199
  * Ask what this node can do for a member in `contextId`, before they sign
179
200
  * anything.
@@ -448,6 +448,35 @@ export class AdminApiClient {
448
448
  async queryContext(contextId, request) {
449
449
  return unwrap(await this.httpClient.post(`/admin-api/contexts/${pathSegment(contextId)}/query`, request));
450
450
  }
451
+ /**
452
+ * Issue an access grant: a token whose holder may call `request.methods` in
453
+ * `contextId`, as this node, with no session of its own.
454
+ *
455
+ * A grant only narrows: each method must be one this session's own token may
456
+ * execute in the context (`403` otherwise), and an account session is refused
457
+ * (`403`), since a granted call runs as the node. The token is in the answer
458
+ * once and never again; the node keeps only its hash.
459
+ */
460
+ async createAccessGrant(contextId, request) {
461
+ return unwrap(await this.httpClient.post(`/admin-api/contexts/${pathSegment(contextId)}/grants`, { methods: request.methods, label: request.label ?? '', notAfter: request.notAfter ?? null }));
462
+ }
463
+ /** The access grants of `contextId` this session could have issued. */
464
+ async listAccessGrants(contextId) {
465
+ return unwrap(await this.httpClient.get(`/admin-api/contexts/${pathSegment(contextId)}/grants`));
466
+ }
467
+ /** Revoke an access grant. A grant this session cannot see is a `404`. */
468
+ async revokeAccessGrant(contextId, grantId) {
469
+ return unwrap(await this.httpClient.delete(`/admin-api/contexts/${pathSegment(contextId)}/grants/${pathSegment(grantId)}`));
470
+ }
471
+ /**
472
+ * Call one method under an access grant. The token is the whole credential:
473
+ * the route is public on every node, so this works from a client holding no
474
+ * session at all. A method the grant does not name, an unknown or revoked
475
+ * token, and an expired grant are each a `403`.
476
+ */
477
+ async callWithAccessGrant(contextId, request) {
478
+ return unwrap(await this.httpClient.post(`/admin-api/contexts/${pathSegment(contextId)}/grant-calls`, request));
479
+ }
451
480
  /**
452
481
  * Ask what this node can do for a member in `contextId`, before they sign
453
482
  * anything.
@@ -475,6 +475,55 @@ export interface QueryContextRequest {
475
475
  /** Its arguments, as the JSON the guest will receive. */
476
476
  argsJson: unknown;
477
477
  }
478
+ /**
479
+ * `POST /admin-api/contexts/:contextId/grants` — let whoever holds the returned
480
+ * token call these methods in the context, as the node that issued it.
481
+ */
482
+ export interface CreateAccessGrantRequest {
483
+ /**
484
+ * Bare method names (`[A-Za-z0-9_]`). Each must be one the caller's own token
485
+ * may execute in the context, or the node refuses with `403`.
486
+ */
487
+ methods: string[];
488
+ /** The grantor's own note, for listing. Never shown to the holder. */
489
+ label?: string;
490
+ /** Unix seconds after which the grant is refused. Absent: until revoked. */
491
+ notAfter?: number | null;
492
+ }
493
+ /** One access grant, as its grantor sees it. The token is never in here. */
494
+ export interface AccessGrant {
495
+ /** Hex. What {@link AdminApiClient.revokeAccessGrant} names. */
496
+ grantId: string;
497
+ methods: string[];
498
+ label: string;
499
+ /** Unix seconds. */
500
+ createdAt: number;
501
+ /** Unix seconds; `null` means until revoked. */
502
+ notAfter: number | null;
503
+ }
504
+ export interface CreatedAccessGrant extends AccessGrant {
505
+ /**
506
+ * Hex. The credential the holder presents. The node keeps only its hash, so
507
+ * this is the one time it can be read.
508
+ */
509
+ token: string;
510
+ }
511
+ export interface RevokeAccessGrantResponseData {
512
+ grantId: string;
513
+ }
514
+ /** `POST /admin-api/contexts/:contextId/grant-calls`. */
515
+ export interface AccessGrantCallRequest {
516
+ /** Hex, as {@link AdminApiClient.createAccessGrant} returned it. */
517
+ token: string;
518
+ /** One of the methods the grant names. */
519
+ method: string;
520
+ /** Its arguments, as the JSON the guest will receive. */
521
+ argsJson: unknown;
522
+ }
523
+ export interface AccessGrantCallResponseData {
524
+ /** The method's own return value. */
525
+ returns: unknown | null;
526
+ }
478
527
  export interface QueryContextResponseData {
479
528
  /** The method's own return value. */
480
529
  returns: unknown | null;
@@ -36,11 +36,17 @@ export interface VerifySignedAgentPolicyOptions {
36
36
  identity?: string;
37
37
  /** The OIDC issuer required. Defaults to {@link KMS_RELEASE_SIGNER}'s. */
38
38
  issuer?: string;
39
+ /**
40
+ * The image role the allowlist must be for: `agent` (the default), or
41
+ * `inference`, the release's `kms-inference-attestation-policy.<profile>.json`
42
+ * for its private inference image. Both have the same shape and signer.
43
+ */
44
+ role?: 'agent' | 'inference';
39
45
  }
40
46
  /**
41
47
  * Verify an agent allowlist against its cosign bundle, as `cosign verify-blob`
42
48
  * would, and return it parsed. Rejects unless it was signed by the KMS release
43
- * workflow, it is an agent allowlist (`role: "agent"`) for the profile asked
49
+ * workflow, it is an allowlist for `options.role` (default `agent`) and the profile asked
44
50
  * for, every list in it is non-empty, and `expectedVersion`, when given, is its
45
51
  * `version`.
46
52
  */
@@ -27,7 +27,7 @@ const LISTS = [
27
27
  /**
28
28
  * Verify an agent allowlist against its cosign bundle, as `cosign verify-blob`
29
29
  * would, and return it parsed. Rejects unless it was signed by the KMS release
30
- * workflow, it is an agent allowlist (`role: "agent"`) for the profile asked
30
+ * workflow, it is an allowlist for `options.role` (default `agent`) and the profile asked
31
31
  * for, every list in it is non-empty, and `expectedVersion`, when given, is its
32
32
  * `version`.
33
33
  */
@@ -44,8 +44,9 @@ export async function verifySignedAgentPolicy(policy, bundle, options = {}) {
44
44
  catch {
45
45
  throw new Error('The signed agent policy is not JSON');
46
46
  }
47
- if (parsed?.role !== 'agent') {
48
- throw new Error(`The signed file is a ${JSON.stringify(parsed?.role)} policy, not an agent one`);
47
+ const role = options.role ?? 'agent';
48
+ if (parsed?.role !== role) {
49
+ throw new Error(`The signed file is a ${JSON.stringify(parsed?.role)} policy, not an ${role} one`);
49
50
  }
50
51
  const profile = options.profile ?? PRODUCTION_PROFILE;
51
52
  if (parsed.profile !== profile) {