@calimero-network/mero-js 26.11.0 → 27.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.
Files changed (220) hide show
  1. package/README.md +73 -288
  2. package/dist/cloud-v2/attestation.d.ts +91 -0
  3. package/dist/cloud-v2/attestation.js +135 -0
  4. package/dist/cloud-v2/capabilities.d.ts +30 -0
  5. package/dist/cloud-v2/capabilities.js +31 -0
  6. package/dist/cloud-v2/client.d.ts +426 -0
  7. package/dist/cloud-v2/client.js +646 -0
  8. package/dist/cloud-v2/errors.d.ts +98 -0
  9. package/dist/cloud-v2/errors.js +165 -0
  10. package/dist/cloud-v2/index.d.ts +10 -0
  11. package/dist/cloud-v2/index.js +5 -0
  12. package/dist/cloud-v2/passkey.d.ts +27 -0
  13. package/dist/cloud-v2/passkey.js +73 -0
  14. package/dist/crypto/internal.d.ts +3 -37
  15. package/dist/crypto/internal.js +3 -72
  16. package/dist/index.browser.mjs +4 -2
  17. package/dist/index.browser.mjs.map +4 -4
  18. package/dist/index.cjs +1750 -12772
  19. package/dist/index.cjs.map +4 -4
  20. package/dist/index.d.ts +3 -56
  21. package/dist/index.js +14 -75
  22. package/dist/index.mjs +1750 -12772
  23. package/dist/index.mjs.map +4 -4
  24. package/dist/sealed/index.d.ts +4 -4
  25. package/dist/sealed/index.js +2 -2
  26. package/dist/sealed/release.d.ts +21 -76
  27. package/dist/sealed/release.js +24 -108
  28. package/dist/sealed/sealed.d.ts +8 -56
  29. package/dist/sealed/sealed.js +11 -89
  30. package/dist/sealed/verify.d.ts +7 -13
  31. package/dist/sealed/verify.js +3 -7
  32. package/package.json +8 -13
  33. package/dist/account/account-admin.d.ts +0 -80
  34. package/dist/account/account-admin.js +0 -346
  35. package/dist/account/account.d.ts +0 -196
  36. package/dist/account/account.js +0 -269
  37. package/dist/account/application-id.d.ts +0 -50
  38. package/dist/account/application-id.js +0 -83
  39. package/dist/account/bootstrap-from-invitation.d.ts +0 -110
  40. package/dist/account/bootstrap-from-invitation.js +0 -80
  41. package/dist/account/create-context.d.ts +0 -103
  42. package/dist/account/create-context.js +0 -267
  43. package/dist/account/govern.d.ts +0 -24
  44. package/dist/account/govern.js +0 -50
  45. package/dist/account/index.d.ts +0 -26
  46. package/dist/account/index.js +0 -15
  47. package/dist/account/join-as-account.d.ts +0 -23
  48. package/dist/account/join-as-account.js +0 -34
  49. package/dist/account/join-with-node.d.ts +0 -115
  50. package/dist/account/join-with-node.js +0 -161
  51. package/dist/account/node-admin.d.ts +0 -20
  52. package/dist/account/node-admin.js +0 -33
  53. package/dist/account/relay-from-invitation.d.ts +0 -137
  54. package/dist/account/relay-from-invitation.js +0 -180
  55. package/dist/account/relay-login-error.d.ts +0 -32
  56. package/dist/account/relay-login-error.js +0 -34
  57. package/dist/account/session.d.ts +0 -266
  58. package/dist/account/session.js +0 -915
  59. package/dist/account/wordlist.d.ts +0 -16
  60. package/dist/account/wordlist.js +0 -273
  61. package/dist/admin-api/admin-client.d.ts +0 -688
  62. package/dist/admin-api/admin-client.js +0 -1230
  63. package/dist/admin-api/admin-factory.d.ts +0 -14
  64. package/dist/admin-api/admin-factory.js +0 -22
  65. package/dist/admin-api/admin-types.d.ts +0 -2046
  66. package/dist/admin-api/admin-types.js +0 -12
  67. package/dist/admin-api/index.d.ts +0 -4
  68. package/dist/admin-api/index.js +0 -5
  69. package/dist/admin-api/redeem-invitation.d.ts +0 -101
  70. package/dist/admin-api/redeem-invitation.js +0 -200
  71. package/dist/auth/index.d.ts +0 -34
  72. package/dist/auth/index.js +0 -67
  73. package/dist/auth-api/auth-client.d.ts +0 -31
  74. package/dist/auth-api/auth-client.js +0 -117
  75. package/dist/auth-api/auth-factory.d.ts +0 -7
  76. package/dist/auth-api/auth-factory.js +0 -41
  77. package/dist/auth-api/auth-types.d.ts +0 -130
  78. package/dist/auth-api/auth-types.js +0 -2
  79. package/dist/auth-api/index.d.ts +0 -3
  80. package/dist/auth-api/index.js +0 -4
  81. package/dist/capabilities.d.ts +0 -84
  82. package/dist/capabilities.js +0 -117
  83. package/dist/cloud/account-ownership.d.ts +0 -63
  84. package/dist/cloud/account-ownership.js +0 -87
  85. package/dist/cloud/cloud-client.d.ts +0 -949
  86. package/dist/cloud/cloud-client.js +0 -1068
  87. package/dist/cloud/connect.d.ts +0 -213
  88. package/dist/cloud/connect.js +0 -260
  89. package/dist/cloud/enrol-redirect.d.ts +0 -181
  90. package/dist/cloud/enrol-redirect.js +0 -244
  91. package/dist/cloud/index.d.ts +0 -12
  92. package/dist/cloud/index.js +0 -10
  93. package/dist/cloud/link-redirect.d.ts +0 -95
  94. package/dist/cloud/link-redirect.js +0 -121
  95. package/dist/cloud/link-state.d.ts +0 -36
  96. package/dist/cloud/link-state.js +0 -104
  97. package/dist/cloud/routing-proof.d.ts +0 -113
  98. package/dist/cloud/routing-proof.js +0 -96
  99. package/dist/device-cert/device-cert.d.ts +0 -189
  100. package/dist/device-cert/device-cert.js +0 -239
  101. package/dist/device-cert/device-scope.d.ts +0 -58
  102. package/dist/device-cert/device-scope.js +0 -76
  103. package/dist/device-cert/index.d.ts +0 -4
  104. package/dist/device-cert/index.js +0 -3
  105. package/dist/ephemeral/codec.d.ts +0 -4
  106. package/dist/ephemeral/codec.js +0 -12
  107. package/dist/ephemeral/index.d.ts +0 -57
  108. package/dist/ephemeral/index.js +0 -101
  109. package/dist/ephemeral/types.d.ts +0 -27
  110. package/dist/ephemeral/types.js +0 -1
  111. package/dist/errors/classify.d.ts +0 -65
  112. package/dist/errors/classify.js +0 -117
  113. package/dist/errors/index.d.ts +0 -2
  114. package/dist/errors/index.js +0 -1
  115. package/dist/events/group.d.ts +0 -95
  116. package/dist/events/group.js +0 -10
  117. package/dist/events/index.d.ts +0 -5
  118. package/dist/events/index.js +0 -2
  119. package/dist/events/sse.d.ts +0 -127
  120. package/dist/events/sse.js +0 -469
  121. package/dist/events/ws.d.ts +0 -57
  122. package/dist/events/ws.js +0 -212
  123. package/dist/http-client/api-response.d.ts +0 -15
  124. package/dist/http-client/api-response.js +0 -1
  125. package/dist/http-client/http-factory.d.ts +0 -71
  126. package/dist/http-client/http-factory.js +0 -68
  127. package/dist/http-client/http-types.d.ts +0 -87
  128. package/dist/http-client/http-types.js +0 -1
  129. package/dist/http-client/index.d.ts +0 -7
  130. package/dist/http-client/index.js +0 -11
  131. package/dist/http-client/path-segment.d.ts +0 -1
  132. package/dist/http-client/path-segment.js +0 -8
  133. package/dist/http-client/retry.d.ts +0 -5
  134. package/dist/http-client/retry.js +0 -82
  135. package/dist/http-client/signal-utils.d.ts +0 -2
  136. package/dist/http-client/signal-utils.js +0 -41
  137. package/dist/http-client/web-client.d.ts +0 -80
  138. package/dist/http-client/web-client.js +0 -557
  139. package/dist/invitation/index.d.ts +0 -2
  140. package/dist/invitation/index.js +0 -2
  141. package/dist/invitation/invitation.d.ts +0 -106
  142. package/dist/invitation/invitation.js +0 -104
  143. package/dist/login/index.d.ts +0 -4
  144. package/dist/login/index.js +0 -3
  145. package/dist/login/login.d.ts +0 -111
  146. package/dist/login/login.js +0 -110
  147. package/dist/login/session.d.ts +0 -124
  148. package/dist/login/session.js +0 -141
  149. package/dist/mero-js.d.ts +0 -231
  150. package/dist/mero-js.js +0 -469
  151. package/dist/namespace-op/index.d.ts +0 -2
  152. package/dist/namespace-op/index.js +0 -3
  153. package/dist/namespace-op/namespace-op.d.ts +0 -150
  154. package/dist/namespace-op/namespace-op.js +0 -191
  155. package/dist/nodeDiscovery.d.ts +0 -47
  156. package/dist/nodeDiscovery.js +0 -101
  157. package/dist/owner-op/index.d.ts +0 -2
  158. package/dist/owner-op/index.js +0 -3
  159. package/dist/owner-op/owner-op.d.ts +0 -119
  160. package/dist/owner-op/owner-op.js +0 -214
  161. package/dist/presence/relay-presence.d.ts +0 -56
  162. package/dist/presence/relay-presence.js +0 -107
  163. package/dist/presence/statement.d.ts +0 -12
  164. package/dist/presence/statement.js +0 -17
  165. package/dist/relay/index.d.ts +0 -4
  166. package/dist/relay/index.js +0 -2
  167. package/dist/relay/nonce-source.d.ts +0 -72
  168. package/dist/relay/nonce-source.js +0 -111
  169. package/dist/relay/relay-client.d.ts +0 -472
  170. package/dist/relay/relay-client.js +0 -518
  171. package/dist/relay-attestation/attest-node-key.d.ts +0 -66
  172. package/dist/relay-attestation/attest-node-key.js +0 -110
  173. package/dist/relay-attestation/index.d.ts +0 -1
  174. package/dist/relay-attestation/index.js +0 -1
  175. package/dist/request/caller-proof.d.ts +0 -43
  176. package/dist/request/caller-proof.js +0 -36
  177. package/dist/request/index.d.ts +0 -3
  178. package/dist/request/index.js +0 -3
  179. package/dist/request/proof-signer.d.ts +0 -49
  180. package/dist/request/proof-signer.js +0 -59
  181. package/dist/request/request-sig.d.ts +0 -99
  182. package/dist/request/request-sig.js +0 -95
  183. package/dist/request-proof/authorizer.d.ts +0 -41
  184. package/dist/request-proof/authorizer.js +0 -60
  185. package/dist/request-proof/index.d.ts +0 -4
  186. package/dist/request-proof/index.js +0 -2
  187. package/dist/request-proof/request-proof.d.ts +0 -53
  188. package/dist/request-proof/request-proof.js +0 -95
  189. package/dist/rpc/index.d.ts +0 -64
  190. package/dist/rpc/index.js +0 -78
  191. package/dist/signer/index.d.ts +0 -2
  192. package/dist/signer/index.js +0 -3
  193. package/dist/signer/signer.d.ts +0 -92
  194. package/dist/signer/signer.js +0 -147
  195. package/dist/token-store/index.d.ts +0 -27
  196. package/dist/token-store/index.js +0 -62
  197. package/dist/transport/index.d.ts +0 -6
  198. package/dist/transport/index.js +0 -3
  199. package/dist/transport/mero-client.d.ts +0 -294
  200. package/dist/transport/mero-client.js +0 -386
  201. package/dist/transport/relay-observer.d.ts +0 -152
  202. package/dist/transport/relay-observer.js +0 -173
  203. package/dist/transport/relay-transport.d.ts +0 -73
  204. package/dist/transport/relay-transport.js +0 -94
  205. package/dist/transport/types.d.ts +0 -100
  206. package/dist/transport/types.js +0 -32
  207. package/dist/types/api-response.d.ts +0 -15
  208. package/dist/types/api-response.js +0 -1
  209. package/dist/types/index.d.ts +0 -1
  210. package/dist/types/index.js +0 -1
  211. package/dist/warrant/creation-warrant.d.ts +0 -163
  212. package/dist/warrant/creation-warrant.js +0 -194
  213. package/dist/warrant/governance-op.d.ts +0 -202
  214. package/dist/warrant/governance-op.js +0 -355
  215. package/dist/warrant/governance-warrant.d.ts +0 -124
  216. package/dist/warrant/governance-warrant.js +0 -164
  217. package/dist/warrant/index.d.ts +0 -8
  218. package/dist/warrant/index.js +0 -5
  219. package/dist/warrant/warrant.d.ts +0 -188
  220. package/dist/warrant/warrant.js +0 -202
@@ -1,2046 +0,0 @@
1
- import type { DcapCollateral } from '../sealed/verify.js';
2
- export { ApiResponse } from '../http-client/index.js';
3
- export interface HealthStatus {
4
- status: string;
5
- }
6
- /**
7
- * What `GET /admin-api/ready` reports: `ready` once the node has finished
8
- * starting up and its store answers. A node that is not ready answers `503`
9
- * with its lifecycle stage (or `store_unavailable`) as the status, which the
10
- * client surfaces as an `HTTPError`.
11
- */
12
- export interface ReadinessStatus {
13
- status: string;
14
- }
15
- export interface AdminAuthStatus {
16
- data: {
17
- status: string;
18
- };
19
- }
20
- /**
21
- * Install by coordinates. The node fetches only from its own configured
22
- * `[registry]`, so there is no caller-supplied URL; both halves are required.
23
- */
24
- export interface InstallApplicationRequest {
25
- package: string;
26
- version: string;
27
- }
28
- export interface InstallDevApplicationRequest {
29
- path: string;
30
- }
31
- export interface InstallApplicationResponseData {
32
- applicationId: string;
33
- }
34
- export interface UninstallApplicationResponseData {
35
- applicationId: string;
36
- }
37
- export interface ApplicationBlob {
38
- bytecode: string;
39
- compiled: string;
40
- }
41
- export interface Application {
42
- id: string;
43
- blob: ApplicationBlob;
44
- size: number;
45
- source: string;
46
- metadata: number[];
47
- /** Absent for a raw-wasm install (no signed bundle) and for bootstrap stubs. */
48
- signer_id?: string;
49
- /** Absent on a bootstrap stub row, written before the app's blob arrives. */
50
- package?: string;
51
- /** Absent when the stored version is empty or not valid semver. */
52
- version?: string;
53
- /** Named services of a multi-service bundle; absent for single-service apps. */
54
- services?: Record<string, ApplicationBlob>;
55
- }
56
- export interface ListApplicationsResponseData {
57
- apps: Application[];
58
- }
59
- export interface GetApplicationResponseData {
60
- application: Application | null;
61
- }
62
- /** One installed blob for an application (distinct from the package registry). */
63
- export interface ApplicationVersionEntry {
64
- version: string;
65
- blobId: string;
66
- size: number;
67
- package: string;
68
- }
69
- export interface ListApplicationVersionsResponseData {
70
- data: ApplicationVersionEntry[];
71
- }
72
- /** The application's `wasm-abi/1` manifest, returned verbatim by the node. */
73
- export type GetApplicationAbiResponseData = Record<string, unknown>;
74
- export interface GetLatestVersionResponseData {
75
- applicationId: string | null;
76
- version: string | null;
77
- }
78
- export interface ListPackagesResponseData {
79
- packages: string[];
80
- }
81
- export interface ListVersionsResponseData {
82
- versions: string[];
83
- }
84
- /**
85
- * Per-service migration descriptor carried in a multi-service bundle manifest,
86
- * emitted from the app's `#[app::migrate]` declaration. `toSchemaVersion` is the
87
- * ABI state version the migrate targets (from `#[app::state(version = N)]`,
88
- * the engine's gate) — NOT the bundle semver, which is `toVersion`, the
89
- * user-facing string an admin matches on; `method` is the migrate entrypoint.
90
- */
91
- export interface BundleMigration {
92
- method: string;
93
- toSchemaVersion: number;
94
- toVersion?: string;
95
- }
96
- /**
97
- * The subset of a registry bundle manifest that `getRegistryVersions` consumes.
98
- * The registry serves these at `GET {registry}/api/v2/bundles?package={package}`;
99
- * installation itself needs only the coordinates, which the node resolves.
100
- */
101
- export interface RegistryBundleManifest {
102
- package: string;
103
- appVersion: string;
104
- /** Present when this bundle's app declares a migration. */
105
- migration?: BundleMigration;
106
- }
107
- export interface CreateContextRequest {
108
- applicationId: string;
109
- groupId: string;
110
- serviceName?: string;
111
- contextSeed?: string;
112
- initializationParams?: number[];
113
- identitySecret?: string;
114
- /** Optional human-readable label for the context. */
115
- name?: string;
116
- }
117
- export interface CreateContextResponseData {
118
- contextId: string;
119
- memberPublicKey: string;
120
- groupId?: string;
121
- groupCreated?: boolean;
122
- }
123
- export interface DeleteContextResponseData {
124
- isDeleted: boolean;
125
- }
126
- export interface Context {
127
- id: string;
128
- applicationId: string;
129
- serviceName?: string;
130
- /**
131
- * Context state/root hash. Core's wire key is `contextStateHash` (part of the
132
- * cross-DAG auth three-level naming: contextStateHash / groupStateHash /
133
- * namespaceStateHash). Renamed from `rootHash`, which never populated.
134
- */
135
- contextStateHash: string;
136
- /** Absent while the context has no deltas yet (core omits an empty list). */
137
- dagHeads?: number[][];
138
- /** Bundle semver of the installed application (skew #2). Absent on older nodes. */
139
- applicationVersion?: string;
140
- }
141
- export interface ContextWithGroup extends Context {
142
- groupId?: string;
143
- }
144
- export interface GetContextsResponseData {
145
- contexts: ContextWithGroup[];
146
- }
147
- export interface GenerateContextIdentityResponseData {
148
- publicKey: string;
149
- }
150
- export interface GetContextIdentitiesResponseData {
151
- identities: string[];
152
- }
153
- export interface JoinContextResponseData {
154
- contextId: string;
155
- memberPublicKey: string;
156
- }
157
- export interface JoinSubgroupInheritanceResponseData {
158
- groupId: string;
159
- memberPublicKey: string;
160
- wasInherited: boolean;
161
- }
162
- export type ContextGroupResponseData = string | null;
163
- export interface ContextStorageResponseData {
164
- sizeInBytes: number;
165
- }
166
- export type SyncContextResponseData = null;
167
- export interface UpdateContextApplicationRequest {
168
- applicationId: string;
169
- executorPublicKey: string;
170
- }
171
- export type UpdateContextApplicationResponseData = Record<string, never>;
172
- export interface ResyncContextRequest {
173
- /** Force a full re-pull even if the context is not detected as stranded. */
174
- force?: boolean;
175
- }
176
- export interface ResyncContextResponseData {
177
- contextId: string;
178
- resyncStarted: boolean;
179
- }
180
- export interface ContextWithExecutors {
181
- contextId: string;
182
- executors: string[];
183
- }
184
- export type ContextsWithExecutorsResponseData = ContextWithExecutors[];
185
- export interface UploadBlobRequest {
186
- /** Raw blob bytes; streamed verbatim as the request body (octet-stream). */
187
- data: Uint8Array | ArrayBuffer | Blob;
188
- /** Optional expected blob hash; sent as the `hash` query param for server-side verification. */
189
- hash?: string;
190
- /** Optional context to announce the blob to; sent as the `context_id` query param. */
191
- contextId?: string;
192
- }
193
- export interface BlobInfo {
194
- blobId: string;
195
- size: number;
196
- }
197
- export type UploadBlobResponseData = BlobInfo;
198
- export interface DeleteBlobResponseData {
199
- blobId: string;
200
- deleted: boolean;
201
- }
202
- export interface ListBlobsResponseData {
203
- blobs: BlobInfo[];
204
- }
205
- export type GetBlobResponseData = BlobInfo;
206
- /**
207
- * Optional context for a blob read. Supplying `contextId` sends the
208
- * `context_id` query param (the same one {@link UploadBlobRequest} announces
209
- * with) and opts the read into network discovery instead of a local-only
210
- * lookup — see {@link AdminClient.getBlob}/{@link AdminClient.getBlobInfo} for
211
- * the latency this buys.
212
- */
213
- export interface BlobReadOptions {
214
- /** Context whose peers to probe for the blob; sent as the `context_id` query param. */
215
- contextId?: string;
216
- }
217
- export interface GetBlobInfoResponseData extends BlobInfo {
218
- /** Absent when the answer came from a peer probe, which carries only presence and size. */
219
- hash?: string;
220
- /** Absent when the answer came from a peer probe, which carries only presence and size. */
221
- mimeType?: string;
222
- /**
223
- * Where the node answered from, per the `x-blob-source` response header:
224
- * `'local'` for its own blob store, `'peer'` for a context probe. Undefined
225
- * on nodes that don't send the header.
226
- */
227
- source?: 'local' | 'peer';
228
- }
229
- export interface CreateContextAliasRequest {
230
- alias: string;
231
- contextId: string;
232
- }
233
- export interface CreateApplicationAliasRequest {
234
- alias: string;
235
- applicationId: string;
236
- }
237
- export interface CreateDeviceAliasRequest {
238
- alias: string;
239
- deviceId: string;
240
- }
241
- /**
242
- * Core's `ListAliasesResponse` is `{ data: BTreeMap<Alias<T>, T> }`, so once the
243
- * `data` envelope is stripped the payload is a flat `{ alias: id }` map — not a
244
- * list of entries. Applies to context, application, and device aliases.
245
- */
246
- export type ListAliasesResponseData = Record<string, string>;
247
- export type CreateAliasResponseData = Record<string, never>;
248
- export type DeleteAliasResponseData = Record<string, never>;
249
- export interface LookupAliasResponseData {
250
- value?: string;
251
- }
252
- /**
253
- * The signed half of an invitation. Wire keys are snake_case: this type mirrors
254
- * a core primitive (`calimero_context_config::types`), which carries no
255
- * camelCase rename — unlike the admin DTOs that wrap it.
256
- */
257
- export interface GroupInvitationFromAdmin {
258
- readonly inviter_identity: number[];
259
- readonly group_id: number[];
260
- readonly expiration_timestamp: number;
261
- /** Per-invitation nonce; core keeps the legacy `secret_salt` wire name. */
262
- readonly secret_salt: number[];
263
- readonly invited_role: number;
264
- /**
265
- * Accounts permitted to admit a claim of this invitation, 64 hex characters
266
- * each — the same spelling every other account-addressing field uses.
267
- *
268
- * Empty means admission by broadcast: the joiner announces itself on the
269
- * namespace topic and any ready peer answers — which publishes the invitation
270
- * to every subscriber of that topic. Naming admitters keeps it off the topic,
271
- * and the joiner presents it to one of them directly.
272
- *
273
- * Inside the inviter's signature, so it cannot be redirected.
274
- */
275
- readonly admitters?: readonly string[];
276
- }
277
- /**
278
- * An invitation blob the node signed. **Opaque: pass it through unchanged.**
279
- *
280
- * `inviter_signature` covers `invitation`, and the trailing bootstrap fields
281
- * (`application_id`, `app_key`) are needed by the joiner even though they sit
282
- * outside the signature — so a value that has been rebuilt field-by-field is
283
- * not the value the node signed. Rebuilding is what a schema derived from these
284
- * declarations does: an object schema drops the keys it wasn't told about, and
285
- * core may add more (both trailing fields were added this way). Carry the value
286
- * verbatim from the call that produced it to {@link JoinGroupRequest}, and treat
287
- * the fields below as read-only detail for display.
288
- *
289
- * The `never`-typed brand makes that structural: an object literal or a schema
290
- * result cannot satisfy this type, while a value the SDK returned — or one
291
- * recovered with `JSON.parse` after transport — still does.
292
- */
293
- export interface SignedGroupOpenInvitation {
294
- readonly invitation: GroupInvitationFromAdmin;
295
- readonly inviter_signature: string;
296
- /**
297
- * libp2p addresses for the accounts in
298
- * {@link GroupInvitationFromAdmin.admitters}, each a full multiaddr including
299
- * its `/p2p/<peer-id>` suffix.
300
- *
301
- * The peer id travels with the address because a joiner cannot derive it:
302
- * resolving an account to a peer needs governance state, which is exactly what
303
- * a joiner has not synced yet.
304
- *
305
- * Outside the signature, like the other bootstrap fields. A wrong address
306
- * costs a failed dial — libp2p authenticates the peer id on connect, and the
307
- * admitting node still has to be in the signed list for its admission to
308
- * count.
309
- *
310
- * Best-effort: absent on invitations from nodes predating the field, and empty
311
- * when the minting node had no address for any admitter.
312
- */
313
- readonly admitter_addrs?: readonly string[];
314
- /**
315
- * The account the inviter acts as, as 64 hex characters — not the
316
- * `inviter_identity` key inside the signed body is written in. Governance
317
- * rows name accounts, and a joiner cannot derive this one: an account is a
318
- * hash of a root it has never seen.
319
- *
320
- * Unsigned bootstrap field, and outside the signature deliberately — a
321
- * client that round-trips an invitation through its own typed model would
322
- * drop an unknown field and invalidate the signature with it. Absent on
323
- * invitations from older nodes.
324
- */
325
- readonly inviter_account?: string;
326
- /** Unsigned bootstrap field; absent on invitations from older nodes. */
327
- readonly application_id?: number[];
328
- /** Unsigned bootstrap field; absent on invitations from older nodes. */
329
- /**
330
- * The wire name is `app_key`; core's Rust field is `bytecode_id` behind a
331
- * `rename` that covers both directions, and core pins this spelling in a test.
332
- * `Option<[u8; 32]>` crosses JSON as an array of byte values, not as hex —
333
- * unlike `AccountId`, which has its own hex representation.
334
- */
335
- readonly app_key?: number[];
336
- /** @internal Brand — never present at runtime, never write it. */
337
- readonly __nodeSigned: never;
338
- }
339
- export interface RecursiveInvitationEntry {
340
- groupId: string;
341
- invitation: SignedGroupOpenInvitation;
342
- groupName?: string;
343
- }
344
- export interface Namespace {
345
- namespaceId: string;
346
- appKey: string;
347
- targetApplicationId: string;
348
- /**
349
- * Absent from nodes that have dropped the concept, always `"LazyOnAccess"` on
350
- * every released one. Optional because this SDK talks to both; it carries no
351
- * information either way. Delete once no supported release still sends it.
352
- */
353
- upgradePolicy?: string;
354
- createdAt: number;
355
- name?: string;
356
- memberCount: number;
357
- contextCount: number;
358
- subgroupCount: number;
359
- /**
360
- * Bundle version of this namespace's `appKey` blob — the per-namespace truth,
361
- * where the application row only says "latest fetched". Absent when core
362
- * cannot resolve it (raw-wasm app, legacy key, blob not retained locally).
363
- */
364
- appVersion?: string;
365
- /** Package of the release the namespace targets; present before that release is installed here. */
366
- appPackage?: string;
367
- /**
368
- * What the namespace id was derived from, on nodes that hold it. Every
369
- * namespace's id is derived from its founder since core's schema v10, so
370
- * this is absent only on nodes that predate it.
371
- */
372
- founding?: NamespaceFounding;
373
- /**
374
- * Group ops this node logged but holds unapplied, because their group's
375
- * history is sealed under a key it lacks: their effects are missing here until
376
- * that key arrives. What explains a subgroup that looks stale on this node and
377
- * current on another. Absent when nothing is held, and on nodes that predate it.
378
- */
379
- heldOps?: NamespaceHeldOps;
380
- /**
381
- * The user removed this namespace from this node and the account is still a
382
- * member. Set only by {@link AdminApiClient.listNamespacesForApplication};
383
- * {@link AdminApiClient.restoreNamespace} brings it back.
384
- */
385
- forgotten?: boolean;
386
- }
387
- /** The group ops a namespace holds unapplied on the node that answered. */
388
- export interface NamespaceHeldOps {
389
- ops: NamespaceHeldOp[];
390
- /** Holds past the node's listing bound, counted but not listed. */
391
- untracked: number;
392
- }
393
- export interface NamespaceHeldOp {
394
- /** Hex id of the namespace op in the governance DAG. */
395
- deltaId: string;
396
- /** Hex id of the group whose sealed history it waits on. */
397
- groupId: string;
398
- }
399
- /**
400
- * The founder and salt a namespace id was derived from:
401
- * `domain_hash("calimero.namespace.id.v1", [founder, salt]) === namespaceId`.
402
- *
403
- * Anyone holding both can confirm which account founded the namespace without
404
- * holding any of its state. Neither is secret, and the salt cannot be replayed
405
- * for another account: the id commits to the founder.
406
- */
407
- export interface NamespaceFounding {
408
- /** Hex `AccountId` of the founder. */
409
- founderAccountId: string;
410
- /** Hex 32-byte salt. */
411
- salt: string;
412
- }
413
- export type ListNamespacesResponseData = Namespace[];
414
- /**
415
- * Who this node is: the account it writes as, the device it is, and the key it
416
- * signs with.
417
- *
418
- * Every field is node-level. One root key means one account, everywhere, and a
419
- * node signs with one key — so none of this varies by namespace, which is why
420
- * the endpoint behind it takes none.
421
- */
422
- /**
423
- * A member's request that a node run one method on their behalf.
424
- *
425
- * Delegated authorship exists for a holder that cannot run the application
426
- * itself — a device with only a signing key, which can neither compile the WASM
427
- * nor decrypt the state. What makes the resulting write *theirs* is the warrant:
428
- * a statement they signed, which travels with the change so every peer verifies
429
- * they consented rather than taking the node's word.
430
- */
431
- export interface PerformIntentRequest {
432
- /** The method to run. */
433
- method: string;
434
- /** Its arguments, as the JSON the guest will receive. */
435
- argsJson: unknown;
436
- /**
437
- * The author's consent: hex-encoded borsh of a `Warrant`.
438
- *
439
- * Opaque on purpose. Its canonical form is those bytes — the signature covers
440
- * them — so re-describing the fields as JSON would create a second spelling
441
- * that could disagree with what was signed.
442
- *
443
- * Mint it with {@link signWarrant}, or out of band with `merod account
444
- * warrant` / `meroctl context intent`.
445
- *
446
- * Signing here needs no dependency, which is why it is available at all: the
447
- * hash is WebCrypto SHA-256, the signature is WebCrypto Ed25519, and every
448
- * field of a warrant is fixed-width so the encoding is concatenation rather
449
- * than borsh. The byte contract is pinned on the node's side, at
450
- * `crates/account/src/tests/warrant_wire_fixture.rs`, because a drift there
451
- * would otherwise surface here as a 403 rather than as an encoding error.
452
- */
453
- warrant: string;
454
- /**
455
- * Hex-encoded borsh of the author's `AccountProof<DeviceCert>`, proving the
456
- * key that signed the warrant is a device of the account it names.
457
- *
458
- * Only the author's own half. The node attaches its own credential, which must
459
- * match the `executor` and `executor_key` the warrant names.
460
- */
461
- authorProof: string;
462
- }
463
- /** What a performed intent reports back. */
464
- /**
465
- * A read of a context, run as the caller's account. Needs no warrant: a read
466
- * publishes nothing, so there is no peer to convince.
467
- */
468
- export interface QueryContextRequest {
469
- /**
470
- * The method to call. It must be declared read-only in the application's ABI
471
- * (a `&self` method in a Rust app); anything else is refused with a `409`,
472
- * because a write needs a warrant ({@link PerformIntentRequest}).
473
- */
474
- method: string;
475
- /** Its arguments, as the JSON the guest will receive. */
476
- argsJson: unknown;
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
- }
527
- export interface QueryContextResponseData {
528
- /** The method's own return value. */
529
- returns: unknown | null;
530
- }
531
- export interface PerformIntentResponseData {
532
- /**
533
- * The context's scope root after the run — how a caller sees that it wrote.
534
- *
535
- * Worth asserting on rather than the status alone: an accepted intent that
536
- * advanced no state is a real failure mode, and it is cheaper to catch here
537
- * than on a later read of a value that was never written.
538
- */
539
- rootHash: string;
540
- /** The method's own return value, if it had one. */
541
- returns: unknown | null;
542
- }
543
- /**
544
- * What a node says about running intents in one context — read before minting a
545
- * warrant, not after being refused one.
546
- *
547
- * Every input to a warrant is something the author already holds except three:
548
- * whose account and key go in `executor` and `executor_key`, which release it
549
- * pins, and whether that node may act here at all. The node knows them, so they
550
- * are answered here, on the path the intent will be presented to.
551
- *
552
- * Reading it first is what lets a client fail before signing. A warrant spends a
553
- * nonce from a monotonic per-device sequence, and one naming the wrong executor
554
- * is unspendable — the number is gone and the write never happened.
555
- */
556
- export interface IntentRelayInfo {
557
- /** The account a warrant for this node must name as its `executor`, 64 hex. */
558
- executorAccount: string;
559
- /**
560
- * The signing key a warrant for this node must name as its `executor_key`, 64
561
- * hex: the one device that may spend it. A re-key voids unspent warrants.
562
- */
563
- executorKey: string;
564
- /**
565
- * Whether this node holds `CAN_AUTHOR_ON_BEHALF` on the group owning the
566
- * context.
567
- *
568
- * `false` is an answer, not an error, and it is the *default* state of every
569
- * context — the capability is implied by neither membership nor admin, and is
570
- * not propagated by the subgroup cascade. A client reads it to tell "ask an
571
- * admin of `groupId`" from "retry later".
572
- */
573
- canAuthorOnBehalf: boolean;
574
- /** The group whose admin must grant that capability, 64 hex. */
575
- groupId: string;
576
- /**
577
- * The blob id of the release that group names, 64 hex: what a warrant for this
578
- * node must pin as `release_bytecode_id`. The route answers 404 while the group
579
- * names no release.
580
- */
581
- releaseBytecodeId: string;
582
- /** That release's semver, for the warrant's `release_version`. */
583
- releaseVersion: string;
584
- }
585
- export interface NodeIdentity {
586
- /**
587
- * The account this node writes as, 64 hex characters. This — not
588
- * `publicKey` — is what member-addressing endpoints take, and what
589
- * `listGroupMembers` entries are keyed by, so it is how a caller locates
590
- * itself in a member list.
591
- */
592
- accountId: string;
593
- /**
594
- * The device this node is, 64 hex characters, or `null` before it has
595
- * enrolled anywhere.
596
- *
597
- * `null` is a real answer rather than a missing one: the account id above
598
- * exists as soon as the node has a root, and enrolment — which a join
599
- * performs — is what adds the device that speaks for it.
600
- */
601
- deviceId: string | null;
602
- /**
603
- * The key this node signs ops with, 64 hex.
604
- *
605
- * The device's signing key, not the account root: the root signs
606
- * certificates and never an op, so a signature on the wire verifies against
607
- * this one.
608
- */
609
- publicKey: string;
610
- /**
611
- * The epoch-0 root **public** key of this node's account, 64 hex characters.
612
- *
613
- * What a second device needs to pair into this account, and public by
614
- * construction — it is hashed into `accountId` and travels in every genesis.
615
- * The private root never leaves the node over HTTP.
616
- *
617
- * Optional because a node at or below `0.11.0-rc.22` does not send it: the
618
- * field landed after that release. Required in the type would make this SDK
619
- * claim something the node the caller chose may not report.
620
- */
621
- accountRootPublicKey?: string;
622
- /**
623
- * Whether this node holds the root key of the account it speaks for. `false`
624
- * means it runs on a delegate device key, so it cannot certify another device
625
- * into the account — which is what a pairing invite needs to know before
626
- * offering the option.
627
- *
628
- * Optional for the same reason as `accountRootPublicKey`: a node at or below
629
- * `0.11.0-rc.30` does not send it. `undefined` is therefore "this node is too
630
- * old to say", which is not the same answer as `false`, and a caller gating an
631
- * invite on it should not collapse the two.
632
- */
633
- holdsAccountRoot?: boolean;
634
- /**
635
- * Whether this node's device is certified into the account it speaks for.
636
- *
637
- * Pair-init mints a device but only pair-complete certifies it, and
638
- * `holdsAccountRoot` is `false` across both states, so this is what tells
639
- * them apart. Absent on a node predating the field.
640
- */
641
- deviceCertified?: boolean;
642
- /**
643
- * Hex X25519 public agreement key of this node's device, `null` before it
644
- * has a device row.
645
- *
646
- * The same key pairing calls `kemPublicKey`; core's name is kept here.
647
- */
648
- deviceAgreementKey?: string | null;
649
- /**
650
- * Hex id of the account namespace this node follows.
651
- *
652
- * A holder derives it before the namespace exists so an invite can carry
653
- * it; a device records it at pair-init. `null` on a node that neither holds
654
- * a root nor has paired with the id; absent on an old node.
655
- */
656
- accountNamespaceId?: string | null;
657
- /**
658
- * The account that withdrew this node's device, absent on a node no
659
- * revocation has reached.
660
- */
661
- revokedFrom?: RevokedFromEntry;
662
- }
663
- /** Which account withdrew this node's device, and which device it was. */
664
- export interface RevokedFromEntry {
665
- /** The account the device spoke for, 64 hex characters. */
666
- accountId: string;
667
- /** The device that was withdrawn, 64 hex characters. */
668
- deviceId: string;
669
- }
670
- export interface CreateNamespaceRequest {
671
- applicationId: string;
672
- name?: string;
673
- /** Hex 32-byte blob id; pins the namespace to a specific installed version. */
674
- appKey?: string;
675
- /**
676
- * Approve outbound requests for the app's publisher in the new namespace, in
677
- * the same call. Absent approves none, and the app's requests are refused
678
- * (`NotApproved`) until an admin approves them.
679
- */
680
- approveOutbound?: OutboundSelection;
681
- }
682
- export interface CreateNamespaceResponseData {
683
- namespaceId: string;
684
- /** What the id was derived from. Absent on nodes that predate derived ids. */
685
- founding?: NamespaceFounding;
686
- /** What the namespace approves for the app's publisher; present only when the request set `approveOutbound`. */
687
- outboundApproval?: OutboundApproval;
688
- }
689
- /**
690
- * Which outbound URL prefixes a namespace approves for an app's publisher:
691
- * `'manifest'` approves every prefix the app's manifest declares, a list
692
- * approves exactly those prefixes. The node rejects any other string.
693
- */
694
- export type OutboundSelection = 'manifest' | string[];
695
- /**
696
- * What a namespace approves for one publisher (the bundle signer): the URL
697
- * prefixes its apps may send outbound requests under, and the prefixes an
698
- * approver was shown.
699
- */
700
- export interface OutboundApproval {
701
- /** The publisher's signer id (`did:key`). */
702
- signer: string;
703
- prefixes: string[];
704
- reviewed: string[];
705
- }
706
- /**
707
- * `PUT /admin-api/namespaces/:namespaceId/outbound-approvals` — set what the
708
- * namespace approves for an installed app's publisher to exactly `approve`.
709
- * `[]` revokes everything.
710
- */
711
- export interface SetOutboundApprovalRequest {
712
- applicationId: string;
713
- approve: OutboundSelection;
714
- }
715
- export interface SetOutboundApprovalResponseData extends OutboundApproval {
716
- namespaceId: string;
717
- /** `false` when nothing changed, so no op was published. */
718
- published: boolean;
719
- }
720
- export interface DeleteNamespaceResponseData {
721
- isDeleted: boolean;
722
- }
723
- export interface CreateNamespaceInvitationRequest {
724
- expirationTimestamp?: number;
725
- recursive?: boolean;
726
- }
727
- export interface CreateNamespaceInvitationResponseData {
728
- invitation: SignedGroupOpenInvitation;
729
- groupName?: string;
730
- }
731
- export interface CreateRecursiveInvitationResponseData {
732
- invitations: RecursiveInvitationEntry[];
733
- }
734
- export interface JoinNamespaceRequest {
735
- invitation: SignedGroupOpenInvitation;
736
- groupName?: string;
737
- }
738
- export interface JoinNamespaceResponseData {
739
- /**
740
- * The namespace that was joined.
741
- *
742
- * core `0.11.0-rc.25` renamed this field on the wire from `groupId`
743
- * (core#3598). The endpoint had been sharing a response DTO with
744
- * `POST /admin-api/groups/join`, which leaked the internal "a namespace is a
745
- * root group" detail into the namespace API and meant a caller could not use
746
- * one spelling across the family.
747
- *
748
- * {@link AdminClient.joinNamespace} fills this in from whichever spelling the
749
- * node sent, so it is populated against nodes on either side of that release.
750
- */
751
- namespaceId: string;
752
- /**
753
- * @deprecated The pre-`0.11.0-rc.25` spelling of {@link namespaceId}. Present
754
- * only when the node predates that release — read `namespaceId` instead,
755
- * which is always set.
756
- */
757
- groupId?: string;
758
- /** The key the joiner signs with, 64 hex. */
759
- memberIdentity: string;
760
- /**
761
- * The account that key joined as, 64 hex characters. This — not
762
- * `memberIdentity` — is what every member-addressing endpoint takes, so it
763
- * is how the caller addresses the member it just became.
764
- */
765
- memberAccount: string;
766
- /** The name a restored namespace had when it was removed. Set only by a restore. */
767
- name?: string;
768
- }
769
- export interface CreateGroupInNamespaceRequest {
770
- groupName?: string;
771
- /**
772
- * Subgroup visibility at birth. Absent means `'open'` (core 0.11 and later;
773
- * older nodes default to `'restricted'`). Pass `'restricted'` for a private
774
- * subgroup, and choose here rather than flipping it afterwards: a subgroup
775
- * created Restricted and flipped Open strands namespace members outside it.
776
- */
777
- visibility?: 'open' | 'restricted';
778
- }
779
- export interface CreateGroupInNamespaceResponseData {
780
- groupId: string;
781
- }
782
- export interface SubgroupEntry {
783
- groupId: string;
784
- name?: string;
785
- }
786
- /**
787
- * Adopt an account that already lives on another device, and mint this node a
788
- * device of its own for it.
789
- *
790
- * The first half of pairing, run on the joining node. It publishes nothing and
791
- * needs no key: it produces the values the account holder's
792
- * {@link AdminApiClient.completeAccountPairing} certifies, plus a confirmation
793
- * code to read out to them.
794
- *
795
- * Account-level, and that is the whole point of it: both credentials pairing
796
- * mints were always account-wide - the certificate is root-signed and the
797
- * endorsement node-level, so neither ever named a namespace - while the older
798
- * per-namespace route still made the caller name one, and the device then
799
- * listened on that one topic while its holder's link fanned out across all of
800
- * them.
801
- */
802
- export interface AccountPairInitRequest {
803
- /**
804
- * The epoch-0 root **public** key of the account to join, 64 hex characters -
805
- * exactly what {@link NodeIdentity.accountRootPublicKey} reports on the node
806
- * that already holds the account.
807
- *
808
- * Named for the half it carries. An ed25519 private and public key are both 32
809
- * bytes and both hex, so nothing but the name tells them apart; the private
810
- * root never crosses this boundary at all.
811
- */
812
- accountRootPublicKey: string;
813
- /**
814
- * Ids of the namespaces to enroll into, 64 hex characters each.
815
- *
816
- * The caller has to supply these, because the joining node cannot discover
817
- * them - it is a member of nothing and holds no scope key, so it can neither
818
- * read the account's namespace set off a DAG nor derive it. The device that
819
- * already holds the account is the only party that knows it.
820
- *
821
- * This decides what the new device *listens* on, and it does not have to agree
822
- * with the applications the holder scopes `pair-complete` to: a binding
823
- * published where the device is not listening is picked up whenever it does
824
- * subscribe, and a subscription the holder never reaches costs nothing.
825
- *
826
- * Core refuses only a request that names neither this nor `accountNamespace`.
827
- * A caller that sends `accountNamespace` may leave this empty.
828
- */
829
- namespaces?: string[];
830
- /**
831
- * Hex id of the account namespace to follow - the value
832
- * {@link NodeIdentity.accountNamespaceId} reports on the holder.
833
- *
834
- * The device then learns the account's namespaces from the account namespace
835
- * itself, so the caller need not know them up front. A caller that does not
836
- * send this must name at least one namespace above.
837
- */
838
- accountNamespace?: string;
839
- }
840
- /**
841
- * What the joining device minted, for the account holder to certify.
842
- *
843
- * These are round-trip tokens: a caller copies them verbatim into
844
- * {@link AdminApiClient.completeAccountPairing}. The signing key is the NEW
845
- * device's, so it appears in no member listing yet and there is nothing here to
846
- * compare it against.
847
- *
848
- * One device is minted however many namespaces were named, so there is one of
849
- * each of these to hand over, not one per namespace.
850
- */
851
- export interface AccountPairInitResponseData {
852
- /** The account this device will speak for once linked, 64 hex characters. */
853
- accountId: string;
854
- /** The device that was minted, 64 hex characters. */
855
- deviceId: string;
856
- /** X25519 agreement key a scope key must be wrapped under to reach this device, hex. */
857
- kemPublicKey: string;
858
- /**
859
- * The Ed25519 key this device signs its ops with, hex.
860
- *
861
- * The account holder cannot derive this - it is minted here - and the
862
- * certificate names it, so it has to travel with the other two.
863
- */
864
- signPublicKey: string;
865
- /**
866
- * The time the device signed, then its Ed25519 signature over the account, the
867
- * device id, both keys above and that time, hex (8 + 64 bytes). The holder's
868
- * node refuses a statement older than a few minutes.
869
- *
870
- * Carried so the three values arrive as a statement by the device that minted
871
- * them rather than as assertions by whoever relayed them; `pair-complete`
872
- * refuses without it.
873
- */
874
- statement: string;
875
- /**
876
- * The value to read out to the account holder, who compares it against what
877
- * their `pair-complete` reports.
878
- *
879
- * The part a substituting attacker cannot fake: it can re-sign its own
880
- * statement, but it would have to make its own keys derive the code the other
881
- * side is already reading.
882
- */
883
- confirmationCode: string;
884
- }
885
- /**
886
- * Certify a device another node minted, link it, and deliver its scope keys.
887
- *
888
- * The second half of pairing, run on the node that holds the account root - the
889
- * only party that can sign the certificate that makes the device real. Every
890
- * field but `applications` is copied verbatim from that other node's
891
- * {@link AccountPairInitResponseData}.
892
- */
893
- export interface AccountPairCompleteRequest {
894
- /** The `deviceId` the other node minted, 64 hex characters. */
895
- deviceId: string;
896
- /** That device's X25519 agreement key, 64 hex characters. */
897
- kemPublicKey: string;
898
- /** That device's Ed25519 signing key, 64 hex characters. */
899
- signPublicKey: string;
900
- /**
901
- * The signature from that node's pair-init, 128 hex characters (64 bytes).
902
- *
903
- * Not optional: without it the three values above are only claims by whoever
904
- * sent them, and certifying those would make attacker-supplied keys a trusted
905
- * device of this account.
906
- */
907
- statement: string;
908
- /**
909
- * The code the account holder read off the pairing device, e.g.
910
- * `7BC0-DAAC-CCB4-84A4`. Grouping and case are ignored.
911
- *
912
- * Required so the comparison cannot be skipped: this side re-derives the code
913
- * for the key material that actually arrived and refuses a mismatch. Its value
914
- * rests on the code reaching the holder independently of this payload - sent
915
- * beside the keys, it proves nothing. One code covers the whole pairing,
916
- * because one device was minted for it.
917
- */
918
- confirmationCode: string;
919
- /**
920
- * Which applications this device may speak for, 64 hex each. Omitted or empty means
921
- * every one of them.
922
- *
923
- * Scoped by application rather than by namespace because a person can answer
924
- * "which apps may this device use" and cannot answer "which namespaces" - a
925
- * namespace is an implementation unit they never named. The node resolves
926
- * these to namespaces through the same lookup
927
- * {@link AdminApiClient.listNamespacesForApplication} reads.
928
- */
929
- applications?: string[];
930
- }
931
- /** What pairing established. */
932
- export interface AccountPairCompleteResponseData {
933
- /** The account the device now speaks for, 64 hex characters. */
934
- accountId: string;
935
- /** The device that was linked, 64 hex characters. */
936
- deviceId: string;
937
- /**
938
- * Whether the current scope key was wrapped and published for the device.
939
- *
940
- * `false` does not mean pairing failed - the link is what confers authority,
941
- * and the device's own sync pull re-requests the key. It does mean the device
942
- * cannot read until that lands.
943
- */
944
- keyDelivered: boolean;
945
- /**
946
- * The code for the key material this certified - the same value the request
947
- * carried, echoed so the operator can see what the certificate names.
948
- */
949
- confirmationCode: string;
950
- /**
951
- * The `AccountProof<DeviceCert>` this pairing minted, hex-encoded borsh.
952
- *
953
- * The certified device needs this to present itself as a device of the
954
- * account, and cannot read it off the DAG: doing so means being a member of a
955
- * group the account speaks in, which a thin client never is. Not a secret - a
956
- * certificate is public and proves nothing without the device key it names.
957
- */
958
- credential: string;
959
- }
960
- /**
961
- * A domain an outside verifier defined, which the account root may sign under.
962
- *
963
- * A name from a closed set, never the domain bytes. The node prepends the bytes
964
- * itself: "sign these bytes with the account root" would be a signing oracle
965
- * over the one key that can certify a device, which is account takeover. A node
966
- * refuses any name it does not know.
967
- *
968
- * Typed as a union plus `(string & {})` so a node newer than this SDK can be
969
- * reached without a cast, while the known names still autocomplete.
970
- */
971
- export type ExternalSigningDomain = 'mdma.account-link' | 'mdma.account-login' | 'mdma.account-recovery' | (string & {});
972
- /**
973
- * Ask this node's account root to sign a payload an outside verifier specified.
974
- *
975
- * The verifier owns the format; the node supplies only the domain. For the cloud
976
- * this is how a challenge it sealed and issued gets signed by a root that
977
- * deliberately never leaves the node holding it.
978
- */
979
- export interface AccountSignWithRootRequest {
980
- /** Which verifier's domain to sign under. */
981
- domain: ExternalSigningDomain;
982
- /**
983
- * The bytes to sign after the domain, hex-encoded.
984
- *
985
- * Hex rather than text because the field is bytes. For the cloud's challenge —
986
- * an ASCII string — that is the UTF-8 of it, hex-encoded; {@link hexEncodeUtf8}
987
- * does exactly that and exists so each caller does not re-derive it.
988
- */
989
- payload: string;
990
- }
991
- /**
992
- * Hex-encode a string's UTF-8 bytes, for {@link AccountSignWithRootRequest.payload}.
993
- *
994
- * Exists so each caller does not write the same loop. Every verifier this is
995
- * used with issues its challenge as text, and the node takes bytes — getting
996
- * that conversion subtly wrong (UTF-16 code units, a stray newline from a shell)
997
- * produces a signature over the wrong message, which fails at the verifier with
998
- * nothing local to point at.
999
- */
1000
- export declare function hexEncodeUtf8(text: string): string;
1001
- /** What the node signed, and the key to check it against. */
1002
- export interface AccountSignWithRootResponseData {
1003
- /** The account root's public key, 64 hex characters. */
1004
- rootPublicKey: string;
1005
- /**
1006
- * The signature over `domain ‖ payload`, **base64**.
1007
- *
1008
- * Base64 rather than hex because that is what the consuming verifiers decode;
1009
- * re-encoding it on the way out is a step that fails silently at the far end.
1010
- */
1011
- signature: string;
1012
- /** The account the signing key belongs to, 64 hex characters. */
1013
- accountId: string;
1014
- }
1015
- /**
1016
- * Repair or widen the reach of a device this account already certified.
1017
- *
1018
- * Pairing is a snapshot: it bound the device wherever this node took part at the
1019
- * time, so a namespace created or joined afterwards holds no binding for it and
1020
- * the paired device silently never sees that namespace. This re-runs the fan-out
1021
- * against the namespaces this node takes part in now. The device need not be
1022
- * online, and nothing but its id is required - the certificate is already held
1023
- * here, root-signed and naming no namespace, so a fresh endorsement and a key
1024
- * wrap are all a later namespace is missing.
1025
- */
1026
- export interface RelinkDeviceRequest {
1027
- /**
1028
- * Applications to add to the device's stored scope, 64 hex each.
1029
- *
1030
- * **Omitted or empty changes nothing** and repairs against the scope already
1031
- * stored, which is the request an operator makes to heal drift. Note that this
1032
- * is the one place an empty list does not mean "all": widening a narrow scope
1033
- * to every application is deliberately not expressible here, because
1034
- * overloading the empty list would make the accidental request the widest one.
1035
- */
1036
- applications?: string[];
1037
- }
1038
- /**
1039
- * The scope to hold: every application, or only the ones named.
1040
- *
1041
- * A tagged shape rather than a list whose emptiness means everything - `all`
1042
- * and `only: []` differ by a whole order of magnitude in what they grant, and
1043
- * an empty `only` is refused rather than treated as `all`.
1044
- */
1045
- export type DeviceScope = 'all' | {
1046
- only: string[];
1047
- };
1048
- /**
1049
- * Replace a device's scope outright, in one root-signed op.
1050
- *
1051
- * {@link relinkAccountDevice} only ever adds applications; this is how a
1052
- * scope is narrowed, or an `all` device is given a fixed list instead.
1053
- */
1054
- export interface RescopeDeviceRequest {
1055
- scope: DeviceScope;
1056
- }
1057
- /** One namespace the relink published the device's link into. */
1058
- export interface RelinkOutcomeEntry {
1059
- /** The namespace id, 64 hex characters. */
1060
- namespaceId: string;
1061
- /**
1062
- * Whether the scope key was wrapped and published for the device here.
1063
- *
1064
- * `false` means the link landed and the delivery did not; the link is what
1065
- * confers authority, and the device's own sync pull re-requests the key.
1066
- */
1067
- keyDelivered: boolean;
1068
- }
1069
- /** One namespace the relink published nothing into, and why. */
1070
- export interface RelinkSkipEntry {
1071
- /** The namespace id, 64 hex characters. */
1072
- namespaceId: string;
1073
- /**
1074
- * Why nothing was published there. Currently one of `outOfScope`,
1075
- * `alreadyBound`, `noScopeKey`, `revoked`, `ownDevice`, `failed`; left as a
1076
- * string because a node may report a reason newer than this SDK.
1077
- */
1078
- reason: string;
1079
- }
1080
- /** One namespace a scope replacement no longer reaches. */
1081
- export interface RescopeDescopeEntry {
1082
- /** The namespace id, 64 hex characters. */
1083
- namespaceId: string;
1084
- /**
1085
- * Whether the scope key was rotated. `false` means the device stopped writing
1086
- * there but still holds the key it had, until an admin rotates.
1087
- */
1088
- keyRotated: boolean;
1089
- }
1090
- /** The scope a device now holds, and what each namespace did about it. */
1091
- export interface RescopeDeviceResponseData {
1092
- /** The account the device speaks for, 64 hex characters. */
1093
- accountId: string;
1094
- /** The device that was rescoped, 64 hex characters. */
1095
- deviceId: string;
1096
- /** The scope after the request, 64 hex each. Empty means every application. */
1097
- applications: string[];
1098
- /** Namespaces the new scope no longer reaches. */
1099
- descoped: RescopeDescopeEntry[];
1100
- /** Namespaces the device was linked into by this call. */
1101
- linkedIn: RelinkOutcomeEntry[];
1102
- /** Namespaces nothing was published into, and why. */
1103
- skipped: RelinkSkipEntry[];
1104
- }
1105
- /** What the relink repaired, and what it left alone. */
1106
- export interface RelinkDeviceResponseData {
1107
- /** The account the device speaks for, 64 hex characters. */
1108
- accountId: string;
1109
- /** The device that was repaired, 64 hex characters. */
1110
- deviceId: string;
1111
- /**
1112
- * The device's scope after the request, 64 hex each. Empty means every
1113
- * application, which is what a pairing that named none asked for.
1114
- */
1115
- applications: string[];
1116
- /**
1117
- * Namespaces the link was published into by this call. Reported per namespace
1118
- * because publication is per-DAG, so which namespaces a device actually
1119
- * reached is a state the caller has to be able to see.
1120
- */
1121
- linkedIn: RelinkOutcomeEntry[];
1122
- /** Namespaces nothing was published into. */
1123
- skipped: RelinkSkipEntry[];
1124
- }
1125
- /**
1126
- * One device of this account, joined from the node-local certificate cache and
1127
- * the live bindings of every namespace this node takes part in.
1128
- */
1129
- export interface AccountDeviceEntry {
1130
- /** This device's id, 64 hex characters. */
1131
- deviceId: string;
1132
- /** The key this device signs its ops with, 64 hex. */
1133
- signingKey: string;
1134
- /** Set only on the device this node itself presents. */
1135
- isSelf: boolean;
1136
- /**
1137
- * Whether this device has been withdrawn from the account.
1138
- *
1139
- * A revoked device stays in the listing rather than vanishing from it, so a
1140
- * settings UI can render "revoked" as a state of a known device instead of
1141
- * silently losing the row. Never filter on this by default: a device that
1142
- * disappeared and a device that was withdrawn are different facts, and only
1143
- * the second one is a fact the account holder took an action to create.
1144
- *
1145
- * Revocation is **forward-only**. It withdraws the device's authority to
1146
- * write from here on; it does not retract, unsign or rewrite anything the
1147
- * device already authored, and ops it signed before the revocation stay valid
1148
- * and stay in the DAG. `revoked: true` therefore means "may not act any more",
1149
- * never "never acted" - do not build UI that implies the past was undone.
1150
- */
1151
- revoked: boolean;
1152
- /**
1153
- * Applications this device may speak for, 64 hex each. **Empty means every
1154
- * application**, the same convention the stored certificate uses - and the
1155
- * opposite of what an empty {@link RelinkDeviceRequest.applications} asks for.
1156
- * Empty also for a device this node holds no cached certificate for: one bound
1157
- * before the cache existed, or certified by another holder.
1158
- */
1159
- applications: string[];
1160
- /**
1161
- * Ids of the namespaces currently holding a live binding for this device, 64
1162
- * hex characters each. Empty for a certified device not yet bound anywhere.
1163
- */
1164
- namespaces: string[];
1165
- /**
1166
- * The replicated name the account gave this device, absent while it has
1167
- * none. Every device of the account reads the same one.
1168
- */
1169
- label?: string;
1170
- }
1171
- /**
1172
- * Name a device of this account, for a listing to render.
1173
- *
1174
- * Run on the node holding the account root to name any device; a paired node
1175
- * is accepted only for that device's own id.
1176
- */
1177
- export interface LabelDeviceRequest {
1178
- /** Trimmed, non-empty, bounded and free of control characters. */
1179
- label: string;
1180
- }
1181
- /**
1182
- * The name that was published, and the epoch that orders it against a rename
1183
- * another device of the account made at the same time.
1184
- */
1185
- export interface LabelDeviceResponseData {
1186
- /** The account the device speaks for, 64 hex characters. */
1187
- accountId: string;
1188
- /** The device that was named, 64 hex characters. */
1189
- deviceId: string;
1190
- label: string;
1191
- labelEpoch: number;
1192
- }
1193
- /**
1194
- * One application this account speaks in, derived from the namespaces this node
1195
- * takes part in that target it.
1196
- *
1197
- * An application installed with no namespace yet is absent here: it has no
1198
- * cross-device meaning until a namespace exists, so there is nothing to scope a
1199
- * device to.
1200
- */
1201
- export interface AccountApplicationEntry {
1202
- /** The application id, 64 hex. */
1203
- applicationId: string;
1204
- /** Ids of the namespaces targeting it, 64 hex characters each. */
1205
- namespaces: string[];
1206
- }
1207
- /**
1208
- * Withdraw a device from an account, terminally.
1209
- *
1210
- * Terminal in one direction only: revocation is **forward-only**. It stops the
1211
- * device acting from here on and does not retract past authorship - every op it
1212
- * already signed keeps verifying and stays in the DAG, because the certificate
1213
- * that authorised it was valid when the signature was made. There is no
1214
- * "un-author" in this system, so no revocation UI should promise one.
1215
- */
1216
- export interface RevokeAccountDeviceRequest {
1217
- /** The device to withdraw, 64 hex. */
1218
- deviceId: string;
1219
- /**
1220
- * A hex-encoded, borsh-serialized signed revocation minted elsewhere -
1221
- * the output of `merod account revoke-proof`.
1222
- *
1223
- * The lost-device path: the account root that owns the device is not on this
1224
- * node, so the proof is signed offline and this node only publishes it. Omit
1225
- * it and the node mints its own proof if it owns the account, and otherwise
1226
- * revokes as an admin.
1227
- *
1228
- * Not a credential and not a secret - it authorises this one revocation of
1229
- * this one device, and only alongside a stored binding naming the same
1230
- * account.
1231
- */
1232
- proof?: string;
1233
- }
1234
- /** What a revocation withdrew in one namespace. */
1235
- export interface RevocationOutcome {
1236
- /** The namespace, 64 hex. */
1237
- namespaceId: string;
1238
- /**
1239
- * Whether the scope key rotated in the same op, in THIS namespace.
1240
- *
1241
- * `false` means the device stopped writing there at once but still holds the
1242
- * key it had, so it can keep READING until an admin rotates. Only an admin
1243
- * may rotate and an account holder revoking their own device usually is not
1244
- * one, so this is commonly owed rather than exceptional.
1245
- */
1246
- keyRotated: boolean;
1247
- }
1248
- export interface RevokeAccountDeviceResponseData {
1249
- /** The account the device spoke for, 64 hex. */
1250
- accountId: string;
1251
- /** The device that was withdrawn, 64 hex. */
1252
- deviceId: string;
1253
- /**
1254
- * Whether the scope key rotated in the namespace named in the request.
1255
- *
1256
- * {@link revokedIn} is the full picture; prefer it. This reports only the one
1257
- * namespace the caller asked about and is retained because core keeps it for
1258
- * a released `calimero-client-py` wheel that requires the field.
1259
- */
1260
- keyRotated: boolean;
1261
- /**
1262
- * Every namespace the revocation was published into.
1263
- *
1264
- * A device belongs to an account rather than to a scope, so revoking it
1265
- * withdraws it from every namespace holding a binding for it - not only the
1266
- * one named in the request. Per namespace because publication is per-DAG: a
1267
- * namespace absent here did not receive the op, and a partially propagated
1268
- * revocation is a state the caller has to be able to see.
1269
- */
1270
- revokedIn: RevocationOutcome[];
1271
- }
1272
- /**
1273
- * Bind a device of an account the node does not hold, so what that device
1274
- * signs in the namespace resolves to its account.
1275
- *
1276
- * For an account with **no node**: its root certifies a device offline
1277
- * (`signDeviceCert`) and scopes it
1278
- * (`signDeviceScope`), and a relay that is a member of the namespace carries
1279
- * the link, endorsing the account with its own member key. Both proofs are
1280
- * root-signed, so the relay can carry them and cannot alter them.
1281
- */
1282
- export interface LinkAccountDeviceRequest {
1283
- /**
1284
- * The device's credential: hex, borsh `AccountProof<DeviceCert>` — what
1285
- * `signDeviceCert` returns and `merod account sign-cert` prints.
1286
- */
1287
- credential: string;
1288
- /**
1289
- * The device's scope: hex, borsh `AccountProof<DeviceScope>` — what
1290
- * `signDeviceScope` returns. It must reach the namespace's application, or
1291
- * name none.
1292
- */
1293
- scope: string;
1294
- }
1295
- export interface LinkAccountDeviceResponseData {
1296
- /** The account the device speaks for, 64 hex. */
1297
- accountId: string;
1298
- /** The device now bound, 64 hex. */
1299
- deviceId: string;
1300
- /**
1301
- * The namespace already bound this device key, so nothing was published.
1302
- * A repeat call is harmless and answers `true`.
1303
- */
1304
- alreadyBound: boolean;
1305
- }
1306
- /** One device of one member account, as the group's live bindings record it. */
1307
- export interface MemberDeviceEntry {
1308
- /** The device id, 64 hex - the form {@link RevokeAccountDeviceRequest.deviceId} takes. */
1309
- deviceId: string;
1310
- /**
1311
- * The key this device's signatures carry, 64 hex. This is the join column
1312
- * against the identities a context reports, which name bare signing keys and
1313
- * nothing else.
1314
- */
1315
- signingKey: string;
1316
- }
1317
- /** One member account of a group, with the devices currently bound for it. */
1318
- export interface MemberDevicesEntry {
1319
- /** The member's account id, 64 hex - the same id a group member listing names. */
1320
- account: string;
1321
- /**
1322
- * Devices holding a live binding for this account. Only live ones: a revoked
1323
- * device is gone from here, unlike {@link AccountDeviceEntry} which keeps it
1324
- * with `revoked: true`. So this answers "who may act now", never "who ever
1325
- * did" - a past author may well be absent.
1326
- */
1327
- devices: MemberDeviceEntry[];
1328
- }
1329
- /** Paging for a member-device listing. Both are optional; the node defaults them. */
1330
- export interface ListMemberDevicesOptions {
1331
- /** How many entries to skip. */
1332
- offset?: number;
1333
- /** How many entries to return. The node clamps this to its own maximum. */
1334
- limit?: number;
1335
- }
1336
- export interface CreateGroupRequest {
1337
- applicationId: string;
1338
- appKey?: string;
1339
- name?: string;
1340
- parentGroupId?: string;
1341
- /**
1342
- * A nested group's visibility at birth. Absent means `open`: every member of
1343
- * the parent is a member of the subgroup by inheritance. `restricted` admits
1344
- * only those added or invited to it. Ignored without `parentGroupId`.
1345
- * Needs core 0.11.0-rc.85 or later (core#4543); an older node refuses the
1346
- * field. `createGroupInNamespace` takes it on older nodes too.
1347
- */
1348
- visibility?: 'open' | 'restricted';
1349
- }
1350
- export interface CreateGroupResponseData {
1351
- groupId: string;
1352
- }
1353
- export interface MissingRelease {
1354
- package: string;
1355
- version: string;
1356
- applicationId: string;
1357
- }
1358
- export interface GroupUpgradeStatus {
1359
- fromVersion: string;
1360
- toVersion: string;
1361
- initiatedAt: number;
1362
- initiatedBy: string;
1363
- status: string;
1364
- /** Contexts THIS NODE enumerated for the upgrade. Node-local; fleet progress
1365
- * is the `getMigrationStatus` rollup. The counters and `completedAt` come
1366
- * from the upgrade propagator only: a plain group upgrade swaps each context
1367
- * lazily, on its next execution, and reports `completed` without any of them. */
1368
- localContextsTotal?: number;
1369
- localContextsSwapped?: number;
1370
- /** Contexts whose swap failed on this node; a non-zero value is what
1371
- * `retryGroupUpgrade` picks up. */
1372
- localContextsFailed?: number;
1373
- /** Unix seconds at which THIS NODE finished its own context swaps, when the
1374
- * propagator ran them (absent on a lazy upgrade, see above). Not fleet
1375
- * convergence - that is `MigrationStatus.fleetCompletedAt`. */
1376
- completedAt?: number;
1377
- }
1378
- export type MemberMigrationState = 'migrated' | 'in_progress' | 'unknown' | 'failed';
1379
- /** Why a member's migration did not complete. */
1380
- export type MigrationFailureReason = 'check_aborted' | 'apply_failed' | 'no_migration_path';
1381
- export interface MemberMigrationReport {
1382
- /** ABI state version the member has loaded, from `#[app::state(version = N)]` -
1383
- * the engine's migration gate, not the bundle semver and not a CRDT concept.
1384
- * The wrong reading here is how the core rollup defect (comparing bundle-semver
1385
- * majors instead of state versions) went unnoticed. */
1386
- schemaVersion: number;
1387
- residueAuto: number;
1388
- syncedUpToHlc: number;
1389
- reportedAt: number;
1390
- /** Member's self-reported pending-authored count (best-effort; skew #1). */
1391
- authoredRemaining: number;
1392
- /**
1393
- * Set when the member's migrate did not complete (its migration-check
1394
- * aborted, or the apply errored). Absent otherwise.
1395
- */
1396
- migrationFailed?: MigrationFailureReason;
1397
- }
1398
- export interface MemberMigrationStatusEntry {
1399
- /** The reporting device's signing KEY, bs58. One account with two devices
1400
- * appears as two rows: the cohort is replicas, not people. */
1401
- peer: string;
1402
- /** The ACCOUNT `peer` speaks for, 64 hex - join it to `listGroupMembers` to
1403
- * name a person. Absent from nodes predating the field. */
1404
- account?: string;
1405
- /** Freshest reported facts. Omitted (not `null`) when the member's state is
1406
- * `unknown`, so test falsiness rather than `=== null`. */
1407
- report?: MemberMigrationReport | null;
1408
- state: MemberMigrationState;
1409
- }
1410
- export interface MigrationStatusRollup {
1411
- migrated: number;
1412
- inProgress: number;
1413
- unknown: number;
1414
- /** Members whose migrate aborted (migration-check failed or apply errored). */
1415
- failed: number;
1416
- total: number;
1417
- allMigrated: boolean;
1418
- /** Count of members with authoredRemaining > 0 (owners still to re-sign). */
1419
- membersPendingSignature: number;
1420
- }
1421
- export interface MigrationStatus {
1422
- targetVersion: number;
1423
- expectedMembers: number;
1424
- /** Governance HLC the cohort was pinned at, as an opaque display string.
1425
- * Absent when there is no migration record. */
1426
- cohortPinnedAtHlc?: string;
1427
- /** Unix seconds at which this node watched the FLEET converge, absent while it
1428
- * has not. Distinct from `GroupUpgradeStatus.completedAt`, which is this node's
1429
- * own local swap completion. Durable, unlike `rollup.allMigrated`, which is
1430
- * recomputed from in-TTL heartbeats and lapses when a member goes quiet. */
1431
- fleetCompletedAt?: number;
1432
- rollup: MigrationStatusRollup;
1433
- members: MemberMigrationStatusEntry[];
1434
- }
1435
- export interface NamespaceRevokedDevices {
1436
- /** Device ids (64 hex) revoked in the namespace. */
1437
- revokedDevices: string[];
1438
- /** Hex `sha256(account || device)` of each device its own account withdrew in the namespace. */
1439
- withdrawnSlots: string[];
1440
- }
1441
- export interface CascadeStatusEntry {
1442
- groupId: string;
1443
- upgrade: GroupUpgradeStatus;
1444
- cascadeHlc?: string;
1445
- }
1446
- export interface GroupInfo {
1447
- groupId: string;
1448
- appKey: string;
1449
- targetApplicationId: string;
1450
- /**
1451
- * Absent from nodes that have dropped the concept, always `"LazyOnAccess"` on
1452
- * every released one. Optional because this SDK talks to both; it carries no
1453
- * information either way. Delete once no supported release still sends it.
1454
- */
1455
- upgradePolicy?: string;
1456
- memberCount: number;
1457
- contextCount: number;
1458
- activeUpgrade?: GroupUpgradeStatus;
1459
- defaultCapabilities: number;
1460
- /** How the group takes members: `'open'` inherits the parent's, `'restricted'` admits directly. */
1461
- subgroupVisibility: string;
1462
- /**
1463
- * Who outside the group can reach it: `'restricted'` when this group or any
1464
- * group above it (short of the namespace root) is Restricted, `'open'` only on
1465
- * an Open chain to the namespace. Draw privacy (a lock) from this, not from
1466
- * `subgroupVisibility`: an Open folder inside a private one is `'open'` there
1467
- * and `'restricted'` here. Absent from nodes that predate it.
1468
- */
1469
- effectiveVisibility?: 'open' | 'restricted';
1470
- /**
1471
- * The group's generic metadata record (replaces the old `alias` field).
1472
- * `null` if no metadata has ever been set for this group.
1473
- */
1474
- metadata?: MetadataRecord | null;
1475
- /** Hex hash of the group's authorization-relevant state, for convergence polling. */
1476
- groupStateHash?: string;
1477
- /**
1478
- * The namespace this group belongs to (itself, for a namespace root). An
1479
- * owner-op root proof binds it. Absent from nodes before core schema 18.
1480
- */
1481
- namespaceId?: string;
1482
- /**
1483
- * How many root-guarded owner ops this group has applied: the `counter` a
1484
- * root proof for its next one must name. Absent from nodes before core
1485
- * schema 18.
1486
- */
1487
- ownerOpCounter?: number;
1488
- /** Package of the release the group targets; present before that release is installed here. */
1489
- appPackage?: string;
1490
- /** Version of the release the group targets; absent until governance names one. */
1491
- appVersion?: string;
1492
- }
1493
- export type GroupInfoResponseData = GroupInfo;
1494
- /**
1495
- * A group member's role, as the node serializes it (PascalCase).
1496
- *
1497
- * The two TEE roles are minted by hardware-attestation admission only, never by
1498
- * an invitation or a role change:
1499
- * - `ReadOnlyTee` — a TEE **replica**: replicates and anchors sync, never
1500
- * relays a member's write (a relay intent to one is refused with a 403).
1501
- * - `RelayTee` — a TEE **relay**: a replica that may also author members'
1502
- * writes under their signed warrants, with no `CAN_AUTHOR_ON_BEHALF` grant.
1503
- * Admitted when the namespace's {@link TeeAdmissionMode} is `relay`.
1504
- */
1505
- export type GroupMemberRole = 'Admin' | 'Member' | 'ReadOnly' | 'ReadOnlyTee' | 'RelayTee';
1506
- export interface GroupMember {
1507
- /**
1508
- * The member's ACCOUNT: 64 hex characters.
1509
- *
1510
- * Not a signing key — a person may hold several keys
1511
- * and governance rows name the person. Both are 32 bytes, so nothing here or
1512
- * on the server will object if you pass the wrong one; it will simply name a
1513
- * principal that exists nowhere. Feed this value to
1514
- * {@link RemoveGroupMembersRequest} and {@link UpdateMemberRoleRequest}, not
1515
- * to {@link GroupMemberInput}.
1516
- */
1517
- identity: string;
1518
- role: GroupMemberRole;
1519
- name?: string;
1520
- }
1521
- export interface ListGroupMembersResponseData {
1522
- members: GroupMember[];
1523
- /**
1524
- * @deprecated The server response uses `members`, not `data`. This alias
1525
- * is retained so existing callers compile during the upgrade window; it
1526
- * is never populated by the client and will be removed in the next
1527
- * major. Switch reads to `response.members`.
1528
- */
1529
- data?: GroupMember[];
1530
- }
1531
- /** One device bound to a member account. */
1532
- export interface MemberDevice {
1533
- /** 64 hex; the form `revokeAccountDevice` takes. */
1534
- deviceId: string;
1535
- /**
1536
- * The key this device's signatures carry, 64 hex. Joins against the
1537
- * identities a context lists.
1538
- */
1539
- signingKey: string;
1540
- }
1541
- /** A member account and the devices bound to it in the namespace. */
1542
- export interface MemberDevicesEntry {
1543
- /** The member's ACCOUNT, 64 hex. */
1544
- account: string;
1545
- devices: MemberDevice[];
1546
- }
1547
- export interface ListMemberDevicesResponseData {
1548
- /**
1549
- * Every account in the group if the calling node is an admin; only its own
1550
- * entry if it is a plain member.
1551
- */
1552
- members: MemberDevicesEntry[];
1553
- }
1554
- export interface SealToAccountRequest {
1555
- /**
1556
- * Hex-encoded plaintext. Small by design: the route exists to hand an account
1557
- * something like a list of namespace ids, and the node caps the size.
1558
- */
1559
- plaintext: string;
1560
- }
1561
- /**
1562
- * A payload sealed to an account's root key. Only that account's root can open
1563
- * it; the node that sealed it cannot.
1564
- */
1565
- export interface SealedEnvelope {
1566
- /**
1567
- * The root-key epoch it was sealed under. A rotated root still opens envelopes
1568
- * from its own epoch, so a recipient holding several needs to know which.
1569
- */
1570
- accountRootEpoch: number;
1571
- /** Hex, 32 bytes: the one-shot sender key. */
1572
- ephemeralPublicKey: string;
1573
- /** Hex, 12 bytes: the AES-256-GCM nonce. */
1574
- nonce: string;
1575
- /** Hex: the ciphertext with its 16-byte tag appended. */
1576
- ciphertext: string;
1577
- }
1578
- export interface GroupContextEntry {
1579
- contextId: string;
1580
- name?: string;
1581
- }
1582
- export type ListGroupContextsResponseData = GroupContextEntry[];
1583
- export interface DeleteGroupResponseData {
1584
- isDeleted: boolean;
1585
- }
1586
- export interface GroupMemberInput {
1587
- /**
1588
- * The invitee's signing KEY, 64 hex — NOT an account. It is spelled exactly
1589
- * like one, so only the field name says which this is.
1590
- *
1591
- * Adding is the one member-facing call that names a key: the node binds the
1592
- * key to an account as it admits it, so before that there is no account to
1593
- * name. Every call that names an EXISTING member takes the account instead.
1594
- */
1595
- identity: string;
1596
- role: string;
1597
- }
1598
- export interface AddGroupMembersRequest {
1599
- members: GroupMemberInput[];
1600
- }
1601
- export type AddGroupMembersResponseData = Record<string, never>;
1602
- export interface RemoveGroupMembersRequest {
1603
- /**
1604
- * The members to remove, as ACCOUNTS (64 hex) — the same ids
1605
- * {@link GroupMember.identity} returns, and not the keys
1606
- * {@link GroupMemberInput.identity} took to add them.
1607
- */
1608
- members: string[];
1609
- }
1610
- export type RemoveGroupMembersResponseData = Record<string, never>;
1611
- export interface UpdateMemberRoleRequest {
1612
- role: string;
1613
- }
1614
- export type UpdateMemberRoleResponseData = Record<string, never>;
1615
- export interface MemberCapabilities {
1616
- capabilities: number;
1617
- }
1618
- export interface SetMemberCapabilitiesRequest {
1619
- capabilities: number;
1620
- }
1621
- export type SetMemberCapabilitiesResponseData = Record<string, never>;
1622
- export interface SetDefaultCapabilitiesRequest {
1623
- defaultCapabilities: number;
1624
- }
1625
- export type SetDefaultCapabilitiesResponseData = Record<string, never>;
1626
- export interface SetMemberAutoFollowRequest {
1627
- /** Auto-join contexts registered in this group. */
1628
- autoFollowContexts: boolean;
1629
- /** Self-admit into subgroups nested under this group. */
1630
- autoFollowSubgroups: boolean;
1631
- }
1632
- export type SetMemberAutoFollowResponseData = Record<string, never>;
1633
- export interface SetSubgroupVisibilityRequest {
1634
- subgroupVisibility: string;
1635
- }
1636
- export type SetSubgroupVisibilityResponseData = Record<string, never>;
1637
- /**
1638
- * The signed-release form of a TEE admission policy: admit a TEE running any
1639
- * mero-tee node release the mero-tee release workflow signed, if its quote
1640
- * matches one of `allowedProfiles` in that release's `published-mrtds.json`.
1641
- * Unlike the measurement lists, it does not need updating for each release.
1642
- */
1643
- export interface SignedReleaseTeePolicy {
1644
- /** Image profiles to admit, e.g. `locked-read-only`. */
1645
- allowedProfiles: string[];
1646
- /** The oldest release admitted (`2.3.72`); any signed release when absent. */
1647
- minReleaseVersion?: string;
1648
- }
1649
- /**
1650
- * Which role a namespace admits attested TEE nodes with: `replica`
1651
- * (`ReadOnlyTee`, the default) or `relay` (`RelayTee`, which may also author
1652
- * members' writes under their warrants). Part of the admin-signed policy, so
1653
- * every node admits with the same role; changing it converts the TEEs already
1654
- * admitted.
1655
- */
1656
- export type TeeAdmissionMode = 'replica' | 'relay';
1657
- /** A policy that lists the measurements it admits. */
1658
- export interface MeasurementTeeAdmissionPolicyRequest {
1659
- allowedMrtd: string[];
1660
- allowedRtmr0: string[];
1661
- allowedRtmr1: string[];
1662
- allowedRtmr2: string[];
1663
- allowedRtmr3: string[];
1664
- allowedTcbStatuses: string[];
1665
- acceptMock: boolean;
1666
- /** Absent means `replica`. */
1667
- mode?: TeeAdmissionMode;
1668
- /**
1669
- * Hex borsh of the signing admin's own root proof for this policy op
1670
- * ({@link signOwnerOpProof} with the matching policy encoder). Omit it on a
1671
- * node that holds that admin's account root, which signs one itself.
1672
- */
1673
- rootProof?: string;
1674
- }
1675
- /** A policy that admits by signed release. The node refuses measurement lists beside it. */
1676
- export interface SignedReleaseTeeAdmissionPolicyRequest {
1677
- signedRelease: SignedReleaseTeePolicy;
1678
- allowedTcbStatuses: string[];
1679
- acceptMock: boolean;
1680
- /** Absent means `replica`. */
1681
- mode?: TeeAdmissionMode;
1682
- /**
1683
- * Hex borsh of the signing admin's own root proof for this policy op
1684
- * ({@link signOwnerOpProof} with the matching policy encoder). Omit it on a
1685
- * node that holds that admin's account root, which signs one itself.
1686
- */
1687
- rootProof?: string;
1688
- }
1689
- export type SetTeeAdmissionPolicyRequest = MeasurementTeeAdmissionPolicyRequest | SignedReleaseTeeAdmissionPolicyRequest;
1690
- export type SetTeeAdmissionPolicyResponseData = Record<string, never>;
1691
- export interface GetTeeAdmissionPolicyResponseData {
1692
- /** `false` when no policy is set; the rest are then empty. */
1693
- enabled?: boolean;
1694
- allowedMrtd: string[];
1695
- allowedRtmr0: string[];
1696
- allowedRtmr1: string[];
1697
- allowedRtmr2: string[];
1698
- allowedRtmr3: string[];
1699
- allowedTcbStatuses: string[];
1700
- acceptMock: boolean;
1701
- /** Set when the policy admits by signed release; the lists are then empty. */
1702
- signedRelease?: SignedReleaseTeePolicy;
1703
- /**
1704
- * The role admitted TEEs receive. `replica` for a policy set before the mode
1705
- * existed; absent only from a node that predates it.
1706
- */
1707
- mode?: TeeAdmissionMode;
1708
- }
1709
- /**
1710
- * Which admitted TEEs may author as the group's TEE authority (the writer behind
1711
- * `TeeOnly` storage and `#[app::tee]` methods). A TEE whose attested MRTD is in
1712
- * `allowedMrtd` may author; an empty list turns TEE authorship off.
1713
- *
1714
- * Namespace-scoped: set it on the namespace root. The node refuses it on a subgroup.
1715
- */
1716
- export interface SetTeeAuthoringPolicyRequest {
1717
- allowedMrtd: string[];
1718
- /**
1719
- * Hex borsh of the signing admin's own root proof for this policy op
1720
- * ({@link signOwnerOpProof} with the matching policy encoder). Omit it on a
1721
- * node that holds that admin's account root, which signs one itself.
1722
- */
1723
- rootProof?: string;
1724
- }
1725
- /**
1726
- * The root proof an owner-level op carries (core schema 18).
1727
- *
1728
- * A device key alone cannot transfer a group, repoint a namespace's admin,
1729
- * delete a group through the owner-only path, or set a TEE policy: each needs a
1730
- * proof signed by the account's ROOT key. On a node that holds that root (as
1731
- * `merod init` provisions) omit `rootProof` and the node signs it. Otherwise sign
1732
- * one offline with {@link signOwnerOpProof}, over the group's current
1733
- * `ownerOpCounter` and `namespaceId` from {@link GroupInfo}. Each proof applies
1734
- * once. Without either, the node answers `403`.
1735
- */
1736
- export interface RootGuardedOpRequest {
1737
- /** Hex borsh of an `AccountProof<OwnerOpAuthorization>`. */
1738
- rootProof?: string;
1739
- }
1740
- /** Hand a group to `newOwner`, an account (64 hex) that is already one of its admins. */
1741
- export interface TransferOwnershipRequest extends RootGuardedOpRequest {
1742
- newOwner: string;
1743
- }
1744
- /** Repoint a namespace's admin pin at `newAdmin`, an account that is a member of its root. */
1745
- export interface ChangeNamespaceAdminRequest extends RootGuardedOpRequest {
1746
- newAdmin: string;
1747
- }
1748
- /**
1749
- * The owner-only deletion of a group that holds no contexts. The admin-level
1750
- * cascading delete is {@link AdminApiClient.deleteGroup}.
1751
- */
1752
- export type OwnerDeleteGroupRequest = RootGuardedOpRequest;
1753
- export type RootGuardedOpResponseData = Record<string, never>;
1754
- export type SetTeeAuthoringPolicyResponseData = Record<string, never>;
1755
- /**
1756
- * Generic metadata record attached to a group, group member, or
1757
- * context-registered-in-a-group (core `calimero_primitives::metadata::MetadataRecord`).
1758
- *
1759
- * `data` is application-defined and opaque to core — it is stored verbatim.
1760
- * Server-enforced size limits: `name` <= 64 bytes; at most 64 entries in
1761
- * `data`; each key <= 64 bytes; each value <= 4096 bytes. Clients do not need
1762
- * to enforce these — the server validates.
1763
- */
1764
- export interface MetadataRecord {
1765
- name: string | null;
1766
- data: Record<string, string>;
1767
- updatedAt: number;
1768
- /** Public key (hex) of the member that last updated the record. */
1769
- updatedBy: string;
1770
- }
1771
- /**
1772
- * Request body for setting a metadata record. **This wholly replaces the
1773
- * record**: `data` defaults to `{}` server-side and replaces the stored map,
1774
- * while omitting `name` keeps the current name. To change `name` while
1775
- * preserving existing `data`, GET the record first and pass its `data` back.
1776
- */
1777
- export interface SetMetadataRequest {
1778
- name?: string;
1779
- data?: Record<string, string>;
1780
- }
1781
- export type SetGroupMetadataRequest = SetMetadataRequest;
1782
- export type SetMemberMetadataRequest = SetMetadataRequest;
1783
- export type SetContextMetadataRequest = SetMetadataRequest;
1784
- export type SetMetadataResponseData = Record<string, never>;
1785
- /**
1786
- * Inner payload of a GET metadata response. `data` is `null` if no metadata
1787
- * has ever been set for the target group/member/context.
1788
- */
1789
- export interface GetMetadataResponseData {
1790
- data: MetadataRecord | null;
1791
- }
1792
- export interface SyncGroupResponseData {
1793
- groupId: string;
1794
- appKey: string;
1795
- targetApplicationId: string;
1796
- memberCount: number;
1797
- contextCount: number;
1798
- }
1799
- export interface UpgradeGroupRequest {
1800
- targetApplicationId: string;
1801
- /** Fan the upgrade out to every descendant subgroup running the same app
1802
- * (one atomic cascade op). Without it the upgrade applies to the target
1803
- * group only - members' subgroups never learn the migration. Server
1804
- * default: false. */
1805
- cascade?: boolean;
1806
- /** Proceed code-only when the target build embeds no ABI. Core refuses such an
1807
- * upgrade by default; setting this asserts the new code is layout-compatible
1808
- * with the running state so the upgrade goes ahead. It never bypasses a
1809
- * declared-migration or downgrade refusal. Wire name is camelCase passthrough;
1810
- * older nodes ignore the unknown field. Server default: false. */
1811
- forceCodeOnly?: boolean;
1812
- /** Publish without first trialling the migration on the admin's own contexts.
1813
- * Server default: false, so a migration that fails the trial is refused with a 409. */
1814
- skipTrial?: boolean;
1815
- /** Approve outbound requests for the target's publisher in the group's
1816
- * namespace before upgrading. Added to what the namespace already approves;
1817
- * a prefix the target declares that nobody approved waits (`AwaitingApproval`). */
1818
- approveOutbound?: OutboundSelection;
1819
- }
1820
- export interface UpgradeGroupResponseData {
1821
- groupId: string;
1822
- status: string;
1823
- localContextsTotal?: number;
1824
- localContextsSwapped?: number;
1825
- localContextsFailed?: number;
1826
- contextsTrialled?: number;
1827
- contextsNotHeld?: number;
1828
- /** What the namespace approves for the target's publisher; present only when the request set `approveOutbound`. */
1829
- outboundApproval?: OutboundApproval;
1830
- }
1831
- export type GroupUpgradeStatusResponseData = GroupUpgradeStatus | null;
1832
- export type RetryGroupUpgradeResponseData = UpgradeGroupResponseData;
1833
- export interface ActivateGroupUpgradeRequest {
1834
- /** Refuse with 409 unless this is the namespace's stored target application. */
1835
- expectedApplicationId?: string;
1836
- /** Refuse with 409 unless this is the target release's manifest version
1837
- * (application ids do not change between versions). */
1838
- expectedVersion?: string;
1839
- }
1840
- export interface ActivateGroupUpgradeFailedContext {
1841
- contextId: string;
1842
- error: string;
1843
- /** False when the switch itself failed (a migration or load); a retry repeats it. */
1844
- retryable: boolean;
1845
- }
1846
- export interface ActivateGroupUpgradeResponseData {
1847
- targetApplicationId: string;
1848
- /** Contexts this call moved to the target; 0 when all were current. */
1849
- switchedContexts: number;
1850
- /** Held deltas replayed into the namespace's contexts. */
1851
- replayedDeltas: number;
1852
- /** Calling again retries only these. */
1853
- failedContexts: ActivateGroupUpgradeFailedContext[];
1854
- }
1855
- export interface ReparentGroupRequest {
1856
- /** 64-char id of the destination parent group. */
1857
- newParentId: string;
1858
- }
1859
- export interface ReparentGroupResponseData {
1860
- reparented: boolean;
1861
- }
1862
- export type DetachContextFromGroupResponseData = Record<string, never>;
1863
- export interface IssueOwnershipProofRequest {
1864
- /** Who the proof is for. Non-empty, <= 256 characters. */
1865
- audience: string;
1866
- /** 64-hex context id the proof is scoped to. */
1867
- contextId: string;
1868
- /** What is being claimed. Non-empty, <= 512 characters. */
1869
- subject: string;
1870
- /** Caller-chosen hex nonce, 32-128 characters (even length). */
1871
- nonce: string;
1872
- /** Requested expiry, unix ms. Core clamps it to issue time + 5 minutes. */
1873
- expiresAtMs: number;
1874
- }
1875
- /** Namespace-scoped sibling: identical minus `contextId`. */
1876
- export type IssueNamespaceOwnershipProofRequest = Omit<IssueOwnershipProofRequest, 'contextId'>;
1877
- export interface IssueOwnershipProofResponseData {
1878
- /** Hex 32-byte ed25519 public key of the signer. */
1879
- signerPublicKey: string;
1880
- /**
1881
- * Base64 opaque UTF-8 JSON bytes of the claim. Verifiers re-parse these exact
1882
- * bytes and sign over `"calimero.ownership-claim.v1\0" || signedPayload`.
1883
- */
1884
- signedPayload: string;
1885
- /** Base64 64-byte ed25519 signature. */
1886
- signature: string;
1887
- /**
1888
- * Namespace proofs only: what the namespace id was derived from. Not signed;
1889
- * the id commits to it. With {@link credential}, it is what lets the cloud
1890
- * check that the signer is a node of the account that FOUNDED the namespace
1891
- * (mdma refuses a namespace proof without both). Absent on nodes that predate
1892
- * it, and on context proofs.
1893
- */
1894
- founding?: NamespaceFounding;
1895
- /**
1896
- * Namespace proofs only: hex borsh `AccountProof<DeviceCert>` — the node's join
1897
- * credential, whose account root certifies `signerPublicKey`. See
1898
- * {@link founding}.
1899
- */
1900
- credential?: string;
1901
- }
1902
- export interface CreateGroupInvitationRequest {
1903
- expirationTimestamp?: number;
1904
- recursive?: boolean;
1905
- /**
1906
- * Accounts permitted to admit a claim of this invitation, 64 hex each.
1907
- *
1908
- * Omitted or empty is filled in by the node from the group's admins and its
1909
- * TEE nodes; it refuses to mint if that set comes back empty, because an empty
1910
- * list on the wire authorises any node to admit. Naming admitters narrows that
1911
- * set.
1912
- *
1913
- * Core signs this list into the invitation, so it cannot be redirected after
1914
- * the fact.
1915
- */
1916
- admitters?: string[];
1917
- /**
1918
- * libp2p addresses for those admitters, each including its `/p2p/<peer-id>`
1919
- * suffix.
1920
- *
1921
- * Omitted or empty asks the node to fill them in from addresses it already has
1922
- * on file — which is usually what you want. Values supplied here are used as
1923
- * given rather than merged, on the grounds that a caller naming an address is
1924
- * correcting the node's view rather than extending it.
1925
- *
1926
- * Not signed, so a wrong address costs a failed dial and nothing more.
1927
- */
1928
- admitterAddrs?: string[];
1929
- }
1930
- export interface CreateGroupInvitationResponseData {
1931
- invitation: SignedGroupOpenInvitation;
1932
- groupName?: string;
1933
- }
1934
- export interface CreateRecursiveGroupInvitationResponseData {
1935
- invitations: RecursiveInvitationEntry[];
1936
- }
1937
- export interface JoinGroupRequest {
1938
- invitation: SignedGroupOpenInvitation;
1939
- groupName?: string;
1940
- }
1941
- export interface JoinGroupResponseData {
1942
- groupId: string;
1943
- /** The key the joiner signs with, 64 hex. */
1944
- memberIdentity: string;
1945
- /**
1946
- * The account that key joined as, 64 hex characters. This — not
1947
- * `memberIdentity` — is what every member-addressing endpoint takes, so it
1948
- * is how the caller addresses the member it just became.
1949
- */
1950
- memberAccount: string;
1951
- }
1952
- export interface TeeInfoResponseData {
1953
- cloudProvider: string;
1954
- osImage: string;
1955
- mrtd: string;
1956
- }
1957
- export interface TeeAttestRequest {
1958
- nonce: string;
1959
- applicationId?: string;
1960
- /**
1961
- * Bind the node's X25519 transport key into the quote; the response names it
1962
- * as `transportPublicKey`. See `fetchAttestedTransportKey`.
1963
- */
1964
- bindTransportKey?: boolean;
1965
- /**
1966
- * Also return the Intel-signed collateral the quote is verified against, as
1967
- * `collateral`, so the quote can be verified with nothing but the node. See
1968
- * `createQuoteVerifier`. A node that predates it refuses the field.
1969
- */
1970
- includeCollateral?: boolean;
1971
- }
1972
- export interface QuoteHeader {
1973
- version: number;
1974
- attestationKeyType: number;
1975
- teeType: number;
1976
- qeVendorId: string;
1977
- userData: string;
1978
- }
1979
- export interface QuoteBody {
1980
- tdxVersion: string;
1981
- teeTcbSvn: string;
1982
- mrseam: string;
1983
- mrsignerseam: string;
1984
- seamattributes: string;
1985
- tdattributes: string;
1986
- xfam: string;
1987
- mrtd: string;
1988
- mrconfigid: string;
1989
- mrowner: string;
1990
- mrownerconfig: string;
1991
- rtmr0: string;
1992
- rtmr1: string;
1993
- rtmr2: string;
1994
- rtmr3: string;
1995
- reportdata: string;
1996
- teeTcbSvn2?: string;
1997
- mrservicetd?: string;
1998
- }
1999
- export interface Quote {
2000
- header: QuoteHeader;
2001
- body: QuoteBody;
2002
- signature: string;
2003
- attestationKey: string;
2004
- certificationData: unknown;
2005
- }
2006
- export interface TeeAttestResponseData {
2007
- quoteB64: string;
2008
- quote: Quote;
2009
- /** Hex X25519 transport key, present only when the request set `bindTransportKey`. */
2010
- transportPublicKey?: string;
2011
- /**
2012
- * The Intel-signed collateral the quote verifies against, present only when
2013
- * the request set `includeCollateral` and the quote is not a mock.
2014
- */
2015
- collateral?: DcapCollateral;
2016
- }
2017
- export interface AdminApiClientConfig {
2018
- baseUrl: string;
2019
- getAuthToken?: () => Promise<string | undefined>;
2020
- timeoutMs?: number;
2021
- /** Fetch every request goes through. Defaults to global `fetch`. */
2022
- fetch?: typeof fetch;
2023
- }
2024
- /** A join signed by its subject, handed to an admitter to publish. */
2025
- export interface AdmitJoinRequest {
2026
- /** The invitation being claimed. Must name the admitter in `admitters`. */
2027
- readonly invitation: SignedGroupOpenInvitation;
2028
- /**
2029
- * The signed `SignedNamespaceOp`, borsh-encoded and hex.
2030
- *
2031
- * Signed by the joiner's device key, which is what stops an admitter
2032
- * substituting a different member: peers check the op's signer against the
2033
- * credential the op carries.
2034
- */
2035
- readonly signedOp: string;
2036
- }
2037
- /** What the admitter did with it. */
2038
- export interface AdmitJoinResponseData {
2039
- /**
2040
- * Whether the op reached the namespace topic.
2041
- *
2042
- * Not "joined" — membership lands when peers apply the op, which the admitter
2043
- * neither performs nor waits for.
2044
- */
2045
- readonly published: boolean;
2046
- }