@calimero-network/mero-js 18.0.0 → 18.1.1

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.
@@ -110,9 +110,6 @@ export interface CreateContextResponseData {
110
110
  groupId?: string;
111
111
  groupCreated?: boolean;
112
112
  }
113
- export interface DeleteContextRequest {
114
- requester?: string;
115
- }
116
113
  export interface DeleteContextResponseData {
117
114
  isDeleted: boolean;
118
115
  }
@@ -441,6 +438,18 @@ export interface NodeIdentity {
441
438
  * claim something the node the caller chose may not report.
442
439
  */
443
440
  accountRootPublicKey?: string;
441
+ /**
442
+ * Whether this node holds the root key of the account it speaks for. `false`
443
+ * means it runs on a delegate device key, so it cannot certify another device
444
+ * into the account — which is what a pairing invite needs to know before
445
+ * offering the option.
446
+ *
447
+ * Optional for the same reason as `accountRootPublicKey`: a node at or below
448
+ * `0.11.0-rc.30` does not send it. `undefined` is therefore "this node is too
449
+ * old to say", which is not the same answer as `false`, and a caller gating an
450
+ * invite on it should not collapse the two.
451
+ */
452
+ holdsAccountRoot?: boolean;
444
453
  }
445
454
  /**
446
455
  * @deprecated Use {@link AdminApiClient.getNodeIdentity} instead. Nothing here
@@ -468,14 +477,10 @@ export interface CreateNamespaceRequest {
468
477
  export interface CreateNamespaceResponseData {
469
478
  namespaceId: string;
470
479
  }
471
- export interface DeleteNamespaceRequest {
472
- requester?: string;
473
- }
474
480
  export interface DeleteNamespaceResponseData {
475
481
  isDeleted: boolean;
476
482
  }
477
483
  export interface CreateNamespaceInvitationRequest {
478
- requester?: string;
479
484
  expirationTimestamp?: number;
480
485
  recursive?: boolean;
481
486
  }
@@ -520,8 +525,9 @@ export interface JoinNamespaceResponseData {
520
525
  memberAccount: string;
521
526
  }
522
527
  export interface CreateGroupInNamespaceRequest {
523
- groupId?: string;
524
- name?: string;
528
+ groupName?: string;
529
+ /** Subgroup visibility at birth. Absent means `'restricted'`. */
530
+ visibility?: 'open' | 'restricted';
525
531
  }
526
532
  export interface CreateGroupInNamespaceResponseData {
527
533
  groupId: string;
@@ -530,6 +536,330 @@ export interface SubgroupEntry {
530
536
  groupId: string;
531
537
  name?: string;
532
538
  }
539
+ /**
540
+ * Adopt an account that already lives on another device, and mint this node a
541
+ * device of its own for it.
542
+ *
543
+ * The first half of pairing, run on the joining node. It publishes nothing and
544
+ * needs no key: it produces the values the account holder's
545
+ * {@link AdminApiClient.completeAccountPairing} certifies, plus a confirmation
546
+ * code to read out to them.
547
+ *
548
+ * Account-level, and that is the whole point of it: both credentials pairing
549
+ * mints were always account-wide - the certificate is root-signed and the
550
+ * endorsement node-level, so neither ever named a namespace - while the older
551
+ * per-namespace route still made the caller name one, and the device then
552
+ * listened on that one topic while its holder's link fanned out across all of
553
+ * them.
554
+ */
555
+ export interface AccountPairInitRequest {
556
+ /**
557
+ * The epoch-0 root **public** key of the account to join, 64 hex characters -
558
+ * exactly what {@link NodeIdentity.accountRootPublicKey} reports on the node
559
+ * that already holds the account.
560
+ *
561
+ * Named for the half it carries. An ed25519 private and public key are both 32
562
+ * bytes and both hex, so nothing but the name tells them apart; the private
563
+ * root never crosses this boundary at all.
564
+ */
565
+ accountRootPublicKey: string;
566
+ /**
567
+ * Ids of the namespaces to enroll into, 64 hex characters each. At least one:
568
+ * a device certified into nothing listens on no topic.
569
+ *
570
+ * The caller has to supply these, because the joining node cannot discover
571
+ * them - it is a member of nothing and holds no scope key, so it can neither
572
+ * read the account's namespace set off a DAG nor derive it. The device that
573
+ * already holds the account is the only party that knows it.
574
+ *
575
+ * This decides what the new device *listens* on, and it does not have to agree
576
+ * with the applications the holder scopes `pair-complete` to: a binding
577
+ * published where the device is not listening is picked up whenever it does
578
+ * subscribe, and a subscription the holder never reaches costs nothing.
579
+ */
580
+ namespaces: string[];
581
+ }
582
+ /**
583
+ * What the joining device minted, for the account holder to certify.
584
+ *
585
+ * These are round-trip tokens: a caller copies them verbatim into
586
+ * {@link AdminApiClient.completeAccountPairing}. The signing key is the NEW
587
+ * device's, so it appears in no member listing yet and there is nothing here to
588
+ * compare it against.
589
+ *
590
+ * One device is minted however many namespaces were named, so there is one of
591
+ * each of these to hand over, not one per namespace.
592
+ */
593
+ export interface AccountPairInitResponseData {
594
+ /** The account this device will speak for once linked, 64 hex characters. */
595
+ accountId: string;
596
+ /** The device that was minted, 64 hex characters. */
597
+ deviceId: string;
598
+ /** X25519 agreement key a scope key must be wrapped under to reach this device, hex. */
599
+ kemPublicKey: string;
600
+ /**
601
+ * The Ed25519 key this device signs its ops with, hex.
602
+ *
603
+ * The account holder cannot derive this - it is minted here - and the
604
+ * certificate names it, so it has to travel with the other two.
605
+ */
606
+ signPublicKey: string;
607
+ /**
608
+ * Ed25519 signature over the account, the device id and both keys above, hex.
609
+ *
610
+ * Carried so the three values arrive as a statement by the device that minted
611
+ * them rather than as assertions by whoever relayed them; `pair-complete`
612
+ * refuses without it.
613
+ */
614
+ statement: string;
615
+ /**
616
+ * The value to read out to the account holder, who compares it against what
617
+ * their `pair-complete` reports.
618
+ *
619
+ * The part a substituting attacker cannot fake: it can re-sign its own
620
+ * statement, but it would have to make its own keys derive the code the other
621
+ * side is already reading.
622
+ */
623
+ confirmationCode: string;
624
+ }
625
+ /**
626
+ * Certify a device another node minted, link it, and deliver its scope keys.
627
+ *
628
+ * The second half of pairing, run on the node that holds the account root - the
629
+ * only party that can sign the certificate that makes the device real. Every
630
+ * field but `applications` is copied verbatim from that other node's
631
+ * {@link AccountPairInitResponseData}.
632
+ */
633
+ export interface AccountPairCompleteRequest {
634
+ /** The `deviceId` the other node minted, 64 hex characters. */
635
+ deviceId: string;
636
+ /** That device's X25519 agreement key, 64 hex characters. */
637
+ kemPublicKey: string;
638
+ /** That device's Ed25519 signing key, 64 hex characters. */
639
+ signPublicKey: string;
640
+ /**
641
+ * The signature from that node's pair-init, 128 hex characters (64 bytes).
642
+ *
643
+ * Not optional: without it the three values above are only claims by whoever
644
+ * sent them, and certifying those would make attacker-supplied keys a trusted
645
+ * device of this account.
646
+ */
647
+ statement: string;
648
+ /**
649
+ * The code the account holder read off the pairing device, e.g.
650
+ * `7BC0-DAAC-CCB4-84A4`. Grouping and case are ignored.
651
+ *
652
+ * Required so the comparison cannot be skipped: this side re-derives the code
653
+ * for the key material that actually arrived and refuses a mismatch. Its value
654
+ * rests on the code reaching the holder independently of this payload - sent
655
+ * beside the keys, it proves nothing. One code covers the whole pairing,
656
+ * because one device was minted for it.
657
+ */
658
+ confirmationCode: string;
659
+ /**
660
+ * Which applications this device may speak for, 64 hex each. Omitted or empty means
661
+ * every one of them.
662
+ *
663
+ * Scoped by application rather than by namespace because a person can answer
664
+ * "which apps may this device use" and cannot answer "which namespaces" - a
665
+ * namespace is an implementation unit they never named. The node resolves
666
+ * these to namespaces through the same lookup
667
+ * {@link AdminApiClient.listNamespacesForApplication} reads.
668
+ */
669
+ applications?: string[];
670
+ }
671
+ /** What pairing established. */
672
+ export interface AccountPairCompleteResponseData {
673
+ /** The account the device now speaks for, 64 hex characters. */
674
+ accountId: string;
675
+ /** The device that was linked, 64 hex characters. */
676
+ deviceId: string;
677
+ /**
678
+ * Whether the current scope key was wrapped and published for the device.
679
+ *
680
+ * `false` does not mean pairing failed - the link is what confers authority,
681
+ * and the device's own sync pull re-requests the key. It does mean the device
682
+ * cannot read until that lands.
683
+ */
684
+ keyDelivered: boolean;
685
+ /**
686
+ * The code for the key material this certified - the same value the request
687
+ * carried, echoed so the operator can see what the certificate names.
688
+ */
689
+ confirmationCode: string;
690
+ /**
691
+ * The `AccountProof<DeviceCert>` this pairing minted, hex-encoded borsh.
692
+ *
693
+ * The certified device needs this to present itself as a device of the
694
+ * account, and cannot read it off the DAG: doing so means being a member of a
695
+ * group the account speaks in, which a thin client never is. Not a secret - a
696
+ * certificate is public and proves nothing without the device key it names.
697
+ */
698
+ credential: string;
699
+ }
700
+ /**
701
+ * Repair or widen the reach of a device this account already certified.
702
+ *
703
+ * Pairing is a snapshot: it bound the device wherever this node took part at the
704
+ * time, so a namespace created or joined afterwards holds no binding for it and
705
+ * the paired device silently never sees that namespace. This re-runs the fan-out
706
+ * against the namespaces this node takes part in now. The device need not be
707
+ * online, and nothing but its id is required - the certificate is already held
708
+ * here, root-signed and naming no namespace, so a fresh endorsement and a key
709
+ * wrap are all a later namespace is missing.
710
+ */
711
+ export interface RelinkDeviceRequest {
712
+ /**
713
+ * Applications to add to the device's stored scope, 64 hex each.
714
+ *
715
+ * **Omitted or empty changes nothing** and repairs against the scope already
716
+ * stored, which is the request an operator makes to heal drift. Note that this
717
+ * is the one place an empty list does not mean "all": widening a narrow scope
718
+ * to every application is deliberately not expressible here, because
719
+ * overloading the empty list would make the accidental request the widest one.
720
+ */
721
+ applications?: string[];
722
+ }
723
+ /** One namespace the relink published the device's link into. */
724
+ export interface RelinkOutcomeEntry {
725
+ /** The namespace id, 64 hex characters. */
726
+ namespaceId: string;
727
+ /**
728
+ * Whether the scope key was wrapped and published for the device here.
729
+ *
730
+ * `false` means the link landed and the delivery did not; the link is what
731
+ * confers authority, and the device's own sync pull re-requests the key.
732
+ */
733
+ keyDelivered: boolean;
734
+ }
735
+ /** One namespace the relink published nothing into, and why. */
736
+ export interface RelinkSkipEntry {
737
+ /** The namespace id, 64 hex characters. */
738
+ namespaceId: string;
739
+ /**
740
+ * Why nothing was published there. Currently one of `outOfScope`,
741
+ * `alreadyBound`, `noScopeKey`, `revoked`, `ownDevice`, `failed`; left as a
742
+ * string because a node may report a reason newer than this SDK.
743
+ */
744
+ reason: string;
745
+ }
746
+ /** What the relink repaired, and what it left alone. */
747
+ export interface RelinkDeviceResponseData {
748
+ /** The account the device speaks for, 64 hex characters. */
749
+ accountId: string;
750
+ /** The device that was repaired, 64 hex characters. */
751
+ deviceId: string;
752
+ /**
753
+ * The device's scope after the request, 64 hex each. Empty means every
754
+ * application, which is what a pairing that named none asked for.
755
+ */
756
+ applications: string[];
757
+ /**
758
+ * Namespaces the link was published into by this call. Reported per namespace
759
+ * because publication is per-DAG, so which namespaces a device actually
760
+ * reached is a state the caller has to be able to see.
761
+ */
762
+ linkedIn: RelinkOutcomeEntry[];
763
+ /** Namespaces nothing was published into. */
764
+ skipped: RelinkSkipEntry[];
765
+ }
766
+ /**
767
+ * One device of this account, joined from the node-local certificate cache and
768
+ * the live bindings of every namespace this node takes part in.
769
+ */
770
+ export interface AccountDeviceEntry {
771
+ /** This device's id, 64 hex characters. */
772
+ deviceId: string;
773
+ /** The key this device signs its ops with, 64 hex. */
774
+ signingKey: string;
775
+ /** Set only on the device this node itself presents. */
776
+ isSelf: boolean;
777
+ revoked: boolean;
778
+ /**
779
+ * Applications this device may speak for, 64 hex each. **Empty means every
780
+ * application**, the same convention the stored certificate uses - and the
781
+ * opposite of what an empty {@link RelinkDeviceRequest.applications} asks for.
782
+ * Empty also for a device this node holds no cached certificate for: one bound
783
+ * before the cache existed, or certified by another holder.
784
+ */
785
+ applications: string[];
786
+ /**
787
+ * Ids of the namespaces currently holding a live binding for this device, 64
788
+ * hex characters each. Empty for a certified device not yet bound anywhere.
789
+ */
790
+ namespaces: string[];
791
+ }
792
+ /**
793
+ * One application this account speaks in, derived from the namespaces this node
794
+ * takes part in that target it.
795
+ *
796
+ * An application installed with no namespace yet is absent here: it has no
797
+ * cross-device meaning until a namespace exists, so there is nothing to scope a
798
+ * device to.
799
+ */
800
+ export interface AccountApplicationEntry {
801
+ /** The application id, 64 hex. */
802
+ applicationId: string;
803
+ /** Ids of the namespaces targeting it, 64 hex characters each. */
804
+ namespaces: string[];
805
+ }
806
+ /** Withdraw a device from an account, terminally. */
807
+ export interface RevokeAccountDeviceRequest {
808
+ /** The device to withdraw, 64 hex. */
809
+ deviceId: string;
810
+ /**
811
+ * A hex-encoded, borsh-serialized signed revocation minted elsewhere -
812
+ * the output of `merod account revoke-proof`.
813
+ *
814
+ * The lost-device path: the account root that owns the device is not on this
815
+ * node, so the proof is signed offline and this node only publishes it. Omit
816
+ * it and the node mints its own proof if it owns the account, and otherwise
817
+ * revokes as an admin.
818
+ *
819
+ * Not a credential and not a secret - it authorises this one revocation of
820
+ * this one device, and only alongside a stored binding naming the same
821
+ * account.
822
+ */
823
+ proof?: string;
824
+ }
825
+ /** What a revocation withdrew in one namespace. */
826
+ export interface RevocationOutcome {
827
+ /** The namespace, 64 hex. */
828
+ namespaceId: string;
829
+ /**
830
+ * Whether the scope key rotated in the same op, in THIS namespace.
831
+ *
832
+ * `false` means the device stopped writing there at once but still holds the
833
+ * key it had, so it can keep READING until an admin rotates. Only an admin
834
+ * may rotate and an account holder revoking their own device usually is not
835
+ * one, so this is commonly owed rather than exceptional.
836
+ */
837
+ keyRotated: boolean;
838
+ }
839
+ export interface RevokeAccountDeviceResponseData {
840
+ /** The account the device spoke for, 64 hex. */
841
+ accountId: string;
842
+ /** The device that was withdrawn, 64 hex. */
843
+ deviceId: string;
844
+ /**
845
+ * Whether the scope key rotated in the namespace named in the request.
846
+ *
847
+ * {@link revokedIn} is the full picture; prefer it. This reports only the one
848
+ * namespace the caller asked about and is retained because core keeps it for
849
+ * a released `calimero-client-py` wheel that requires the field.
850
+ */
851
+ keyRotated: boolean;
852
+ /**
853
+ * Every namespace the revocation was published into.
854
+ *
855
+ * A device belongs to an account rather than to a scope, so revoking it
856
+ * withdraws it from every namespace holding a binding for it - not only the
857
+ * one named in the request. Per namespace because publication is per-DAG: a
858
+ * namespace absent here did not receive the op, and a partially propagated
859
+ * revocation is a state the caller has to be able to see.
860
+ */
861
+ revokedIn: RevocationOutcome[];
862
+ }
533
863
  export interface CreateGroupRequest {
534
864
  applicationId: string;
535
865
  groupId?: string;
@@ -665,9 +995,6 @@ export interface GroupContextEntry {
665
995
  name?: string;
666
996
  }
667
997
  export type ListGroupContextsResponseData = GroupContextEntry[];
668
- export interface DeleteGroupRequest {
669
- requester?: string;
670
- }
671
998
  export interface DeleteGroupResponseData {
672
999
  isDeleted: boolean;
673
1000
  }
@@ -685,7 +1012,6 @@ export interface GroupMemberInput {
685
1012
  }
686
1013
  export interface AddGroupMembersRequest {
687
1014
  members: GroupMemberInput[];
688
- requester?: string;
689
1015
  }
690
1016
  export type AddGroupMembersResponseData = Record<string, never>;
691
1017
  export interface RemoveGroupMembersRequest {
@@ -695,12 +1021,10 @@ export interface RemoveGroupMembersRequest {
695
1021
  * {@link GroupMemberInput.identity} took to add them.
696
1022
  */
697
1023
  members: string[];
698
- requester?: string;
699
1024
  }
700
1025
  export type RemoveGroupMembersResponseData = Record<string, never>;
701
1026
  export interface UpdateMemberRoleRequest {
702
1027
  role: string;
703
- requester?: string;
704
1028
  }
705
1029
  export type UpdateMemberRoleResponseData = Record<string, never>;
706
1030
  export interface MemberCapabilities {
@@ -708,17 +1032,21 @@ export interface MemberCapabilities {
708
1032
  }
709
1033
  export interface SetMemberCapabilitiesRequest {
710
1034
  capabilities: number;
711
- requester?: string;
712
1035
  }
713
1036
  export type SetMemberCapabilitiesResponseData = Record<string, never>;
714
1037
  export interface SetDefaultCapabilitiesRequest {
715
1038
  defaultCapabilities: number;
716
- requester?: string;
717
1039
  }
718
1040
  export type SetDefaultCapabilitiesResponseData = Record<string, never>;
1041
+ export interface SetMemberAutoFollowRequest {
1042
+ /** Auto-join contexts registered in this group. */
1043
+ autoFollowContexts: boolean;
1044
+ /** Self-admit into subgroups nested under this group. */
1045
+ autoFollowSubgroups: boolean;
1046
+ }
1047
+ export type SetMemberAutoFollowResponseData = Record<string, never>;
719
1048
  export interface SetSubgroupVisibilityRequest {
720
1049
  subgroupVisibility: string;
721
- requester?: string;
722
1050
  }
723
1051
  export type SetSubgroupVisibilityResponseData = Record<string, never>;
724
1052
  export interface SetTeeAdmissionPolicyRequest {
@@ -729,7 +1057,6 @@ export interface SetTeeAdmissionPolicyRequest {
729
1057
  allowedRtmr3: string[];
730
1058
  allowedTcbStatuses: string[];
731
1059
  acceptMock: boolean;
732
- requester?: string;
733
1060
  }
734
1061
  export type SetTeeAdmissionPolicyResponseData = Record<string, never>;
735
1062
  export interface GetTeeAdmissionPolicyResponseData {
@@ -766,7 +1093,6 @@ export interface MetadataRecord {
766
1093
  export interface SetMetadataRequest {
767
1094
  name?: string;
768
1095
  data?: Record<string, string>;
769
- requester?: string;
770
1096
  }
771
1097
  export type SetGroupMetadataRequest = SetMetadataRequest;
772
1098
  export type SetMemberMetadataRequest = SetMetadataRequest;
@@ -779,9 +1105,6 @@ export type SetMetadataResponseData = Record<string, never>;
779
1105
  export interface GetMetadataResponseData {
780
1106
  data: MetadataRecord | null;
781
1107
  }
782
- export interface SyncGroupRequest {
783
- requester?: string;
784
- }
785
1108
  export interface SyncGroupResponseData {
786
1109
  groupId: string;
787
1110
  appKey: string;
@@ -791,7 +1114,6 @@ export interface SyncGroupResponseData {
791
1114
  }
792
1115
  export interface UpgradeGroupRequest {
793
1116
  targetApplicationId: string;
794
- requester?: string;
795
1117
  /** Fan the upgrade out to every descendant subgroup running the same app
796
1118
  * (one atomic cascade op). Without it the upgrade applies to the target
797
1119
  * group only - members' subgroups never learn the migration. Server
@@ -812,24 +1134,41 @@ export interface UpgradeGroupResponseData {
812
1134
  localContextsFailed?: number;
813
1135
  }
814
1136
  export type GroupUpgradeStatusResponseData = GroupUpgradeStatus | null;
815
- export interface RetryGroupUpgradeRequest {
816
- requester?: string;
817
- }
818
1137
  export type RetryGroupUpgradeResponseData = UpgradeGroupResponseData;
819
1138
  export interface ReparentGroupRequest {
820
1139
  /** 64-char id of the destination parent group. */
821
1140
  newParentId: string;
822
- requester?: string;
823
1141
  }
824
1142
  export interface ReparentGroupResponseData {
825
1143
  reparented: boolean;
826
1144
  }
827
- export interface DetachContextFromGroupRequest {
828
- requester?: string;
829
- }
830
1145
  export type DetachContextFromGroupResponseData = Record<string, never>;
1146
+ export interface IssueOwnershipProofRequest {
1147
+ /** Who the proof is for. Non-empty, <= 256 characters. */
1148
+ audience: string;
1149
+ /** 64-hex context id the proof is scoped to. */
1150
+ contextId: string;
1151
+ /** What is being claimed. Non-empty, <= 512 characters. */
1152
+ subject: string;
1153
+ /** Caller-chosen hex nonce, 32-128 characters (even length). */
1154
+ nonce: string;
1155
+ /** Requested expiry, unix ms. Core clamps it to issue time + 5 minutes. */
1156
+ expiresAtMs: number;
1157
+ }
1158
+ /** Namespace-scoped sibling: identical minus `contextId`. */
1159
+ export type IssueNamespaceOwnershipProofRequest = Omit<IssueOwnershipProofRequest, 'contextId'>;
1160
+ export interface IssueOwnershipProofResponseData {
1161
+ /** Hex 32-byte ed25519 public key of the signer. */
1162
+ signerPublicKey: string;
1163
+ /**
1164
+ * Base64 opaque UTF-8 JSON bytes of the claim. Verifiers re-parse these exact
1165
+ * bytes and sign over `"calimero.ownership-claim.v1\0" || signedPayload`.
1166
+ */
1167
+ signedPayload: string;
1168
+ /** Base64 64-byte ed25519 signature. */
1169
+ signature: string;
1170
+ }
831
1171
  export interface CreateGroupInvitationRequest {
832
- requester?: string;
833
1172
  expirationTimestamp?: number;
834
1173
  recursive?: boolean;
835
1174
  /**