@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,472 +0,0 @@
1
- /**
2
- * Write to a context through a relay, holding nothing but a signing key.
3
- *
4
- * # What this replaces
5
- *
6
- * `sdk.rpc.execute` asks a node to run a method *as itself*: it needs a node,
7
- * that node needs to be a member, and the caller needs a credential on it. For
8
- * a browser tab, a phone, or an agent, none of those three is available — the
9
- * runtime cannot compile WASM against materialized state, never received the
10
- * scope key that seals the deltas, and has no account on anybody's node.
11
- *
12
- * This client is the other path. The caller signs a warrant locally, the relay
13
- * runs the method as the *author's* principal, and the resulting delta is
14
- * attributed to the author's account and device — their replica slot, their
15
- * membership, their name in the app. The relay's key signs the envelope and
16
- * nothing else.
17
- *
18
- * # The three preconditions, and why they are checked in this order
19
- *
20
- * `describe()` answers the first two in one call, before anything is signed:
21
- * the relay's executor account and signing key and the release the context's
22
- * group names (which the warrant must name), and whether it holds
23
- * `CAN_AUTHOR_ON_BEHALF` on the owning group. The third,
24
- * that the author's account is a member, only the group knows, and it surfaces
25
- * as a refusal.
26
- *
27
- * Checking before signing is not politeness. A warrant consumes a nonce from a
28
- * monotonic per-device sequence, and one minted against the wrong executor is
29
- * unspendable: the number is gone and the write never happened.
30
- */
31
- import { type Signer } from '../signer/signer.js';
32
- import { type GovernanceOp } from '../warrant/governance-op.js';
33
- import type { NonceSource } from './nonce-source.js';
34
- /** Where and as whom to write, plus the key that consents. */
35
- export interface RelayClientConfig {
36
- /**
37
- * The relay's base URL — the node's origin, not a path.
38
- *
39
- * Discover it from {@link CloudClient.getNamespaceRelays} for a hosted
40
- * namespace, or take it from the operator for a self-hosted one.
41
- */
42
- relayUrl: string;
43
- /**
44
- * The account the relay writes as, hex — a warrant's `executor`.
45
- *
46
- * Only checked against what the relay answers: a warrant also names the
47
- * relay's signing key and the release, which only discovery reports, so every write asks.
48
- */
49
- executorAccount?: string;
50
- /** The author's account, hex — whose consent the warrant carries. */
51
- authorAccount: string;
52
- /**
53
- * The author's `AccountProof<DeviceCert>`, hex-encoded borsh.
54
- *
55
- * Proves the key that signed the warrant is a device of the account it names.
56
- * The author sends only its own half; the relay attaches its own.
57
- */
58
- authorProof: string;
59
- /**
60
- * The author device's ed25519 signing secret, hex (32 bytes).
61
- *
62
- * Never transmitted. It signs in this process and only the signature leaves,
63
- * which is the whole reason a keyholder can author without a node.
64
- *
65
- * Mutually exclusive with {@link RelayClientConfig.signer}: exactly one is
66
- * required. A browser should prefer the signer: a secret held as a string is
67
- * readable by anything on the origin, and a non-extractable key is not.
68
- */
69
- deviceSecret?: string;
70
- /**
71
- * The author device's signer: use instead of
72
- * {@link RelayClientConfig.deviceSecret} when the key cannot be exported
73
- * (a non-extractable WebCrypto key, a passkey, a hardware or remote signer).
74
- */
75
- signer?: Signer;
76
- /**
77
- * Where nonces come from. See {@link NonceSource} — a reset replays.
78
- *
79
- * Persist it (`createLocalStorageNonceSource` in a browser): the node keeps
80
- * the spent ledger but serves no lookup of it, so the client's own counter is
81
- * the only record of where the sequence stands.
82
- */
83
- nonces: NonceSource;
84
- /**
85
- * Seconds a minted warrant stays valid. Defaults to 300.
86
- *
87
- * Checked by the relay against its own clock, and by peers against the
88
- * delta's own signed stamp, never their clocks: this bounds how long *this*
89
- * request may sit in flight before the relay runs it.
90
- */
91
- ttlSeconds?: number;
92
- /** Injected for tests and non-browser runtimes. Defaults to global `fetch`. */
93
- fetch?: typeof fetch;
94
- timeoutMs?: number;
95
- /**
96
- * How many times a `429` is waited out before it reaches the caller.
97
- * Defaults to 3; `0` surfaces rate limits immediately.
98
- *
99
- * Safe to retry because the relay's ingress limiter runs before the node sees
100
- * the request, so a throttled warrant's nonce is not spent.
101
- */
102
- rateLimitRetries?: number;
103
- }
104
- /** The relay a warrant names: its account, and the one key of it that may spend the warrant. */
105
- export interface RelayExecutor {
106
- /** The account a warrant must name as `executor`, hex. */
107
- executorAccount: string;
108
- /** The signing key a warrant must name as `executor_key`, hex. */
109
- executorKey: string;
110
- }
111
- /** What a relay says about its ability to run intents in one context. */
112
- export interface RelayDescription extends RelayExecutor {
113
- /** Whether the relay holds `CAN_AUTHOR_ON_BEHALF` on the owning group. */
114
- canAuthorOnBehalf: boolean;
115
- /** The group whose admin grants that capability, hex. */
116
- groupId: string;
117
- /**
118
- * The blob id of the release the group names, hex: what a warrant must pin
119
- * as `release_bytecode_id`. Discovery answers 404 while the group names none.
120
- */
121
- releaseBytecodeId: string;
122
- /** That release's semver, signed as the warrant's `release_version`. */
123
- releaseVersion: string;
124
- }
125
- /** What a relay says about its ability to create contexts in one group. */
126
- export interface CreationDescription extends RelayExecutor {
127
- /** The group, hex. */
128
- groupId: string;
129
- /**
130
- * Whether the relay has standing to act for members of this group (a
131
- * `RelayTee` role or `CAN_AUTHOR_ON_BEHALF`). It needs no create rights of
132
- * its own — those are checked on the author.
133
- */
134
- canCreateOnBehalf: boolean;
135
- /**
136
- * Whether the author holds `CAN_CREATE_CONTEXT` (or admin) here. Present only
137
- * when `describeCreation` was given an `author`.
138
- */
139
- authorMayCreate?: boolean;
140
- }
141
- /** What {@link RelayClient.createContext} creates. */
142
- export interface CreateContextInput {
143
- /** The group to create the context in, hex. */
144
- groupId: string;
145
- /** The application to create it with, hex (32 bytes). */
146
- applicationId: string;
147
- /** The JSON the app's `init()` receives — run as the author's account. */
148
- initArgs?: unknown;
149
- /** Which service of a multi-service bundle; absent for the default. */
150
- serviceName?: string;
151
- /** A display name for the context. */
152
- name?: string;
153
- /**
154
- * The seed the context id is derived from, hex (32 bytes). Random when
155
- * absent, which is what almost every caller wants.
156
- */
157
- seed?: string;
158
- }
159
- /** Where a delegated creation landed. */
160
- export interface CreatedContext {
161
- /** The new context's id, hex. */
162
- contextId: string;
163
- /** The group it was created in, hex. */
164
- groupId: string;
165
- /** The relay's identity in the new context, hex. */
166
- memberPublicKey: string;
167
- }
168
- /** What a relay says about publishing governance ops for members of one group. */
169
- export interface GovernanceDescription extends RelayExecutor {
170
- /** The group asked about, hex. */
171
- groupId: string;
172
- /**
173
- * Whether the relay may act for members here (a `RelayTee` role or
174
- * `CAN_AUTHOR_ON_BEHALF`). It needs no right to the op itself: that is
175
- * checked on the author, as the op is applied as the author.
176
- */
177
- canActOnBehalf: boolean;
178
- }
179
- /** What {@link RelayClient.govern} publishes. */
180
- export interface GovernInput {
181
- /**
182
- * Where the op is published, hex: the group itself for a group op, the
183
- * **namespace** for a root op (creating, moving or deleting a subgroup).
184
- */
185
- groupId: string;
186
- /** The op, from one of the encoders (`memberAddedOp`, `groupCreatedOp`, ...). */
187
- op: GovernanceOp;
188
- }
189
- /** Where a delegated governance op landed. */
190
- export interface GovernResult {
191
- /** The group the op acted on, hex: the new subgroup, for a creation. */
192
- groupId: string;
193
- }
194
- /** What {@link RelayClient.foundNamespace} founds with. */
195
- export interface FoundNamespaceInput {
196
- /**
197
- * The salt the namespace id is derived from, hex (32 bytes). Random when
198
- * absent, which is what almost every caller wants: one account founds many
199
- * namespaces by varying it.
200
- */
201
- salt?: string;
202
- /**
203
- * The relay's account and node key (pinned, or from `resolveRelayNodeKey`). Never
204
- * a discovery answer: that key is unauthenticated, and no namespace exists yet.
205
- */
206
- executor: RelayExecutor;
207
- /**
208
- * The namespace root's default capability mask (`MemberCapabilities` bits),
209
- * set right after founding. A namespace is founded with core's minimal
210
- * default (`CAN_JOIN_OPEN_SUBGROUPS` only), so an app that wants members to
211
- * create contexts or invite, for example, names its own mask here.
212
- *
213
- * Set through the relay with a delegated `DefaultCapabilitiesSet`, applied as
214
- * the founder, who is the namespace's admin. It cannot include
215
- * `CAN_AUTHOR_ON_BEHALF` (bit 9): which relays may write for members is never
216
- * decided through a relay, and such a mask is refused before anything is
217
- * signed.
218
- */
219
- defaultCapabilities?: number;
220
- /**
221
- * The application the namespace runs, set right after founding. Without one
222
- * a founded namespace targets no application, and no context can be created
223
- * in it. Set through the relay with a delegated `TargetApplicationSet`, which
224
- * core accepts only as a group's first application.
225
- */
226
- application?: {
227
- applicationId: string;
228
- package: string;
229
- version: string;
230
- };
231
- }
232
- /** A namespace founded through a relay. */
233
- export interface FoundedNamespace {
234
- /** The new namespace's id, hex: `foundedNamespaceId(author, salt)`. */
235
- namespaceId: string;
236
- /**
237
- * The salt it was derived with, hex. Keep it if anyone will need to be shown
238
- * who founded the namespace: `(founder, salt)` reproduces the id.
239
- */
240
- salt: string;
241
- /**
242
- * Whether the relay admitted itself as the namespace's first TEE, which also
243
- * sets its default relay-mode admission policy. `false` from a relay that is
244
- * not a TEE, or whose attestation failed (see `teeError`). The namespace is
245
- * founded either way.
246
- */
247
- teeEnabled: boolean;
248
- /** Why `teeEnabled` is `false`, when the relay tried and failed. */
249
- teeError?: string;
250
- /**
251
- * Present only when `defaultCapabilities` was asked for: whether the mask was
252
- * set. `false` leaves the namespace founded with core's default; retry with
253
- * `govern({ groupId: namespaceId, op: defaultCapabilitiesSetOp(mask) })`.
254
- */
255
- defaultCapabilitiesSet?: boolean;
256
- /** Why `defaultCapabilitiesSet` is `false`. */
257
- defaultCapabilitiesError?: string;
258
- /**
259
- * Present only when `application` was asked for: whether the namespace now
260
- * runs it. `false` leaves it with no application; retry with
261
- * `govern({ groupId: namespaceId, op: targetApplicationSetOp(application) })`.
262
- */
263
- applicationSet?: boolean;
264
- /** Why `applicationSet` is `false`. */
265
- applicationError?: string;
266
- }
267
- /** Where an accepted intent landed. */
268
- export interface IntentResult<T = unknown> {
269
- /** The context's scope root after the run — did this change anything? */
270
- rootHash: string;
271
- /** The method's own return value. */
272
- returns: T | null;
273
- }
274
- /**
275
- * Thrown when a relay refuses an intent, carrying which precondition failed.
276
- *
277
- * The distinction is the whole reason this type exists. A `403` from this
278
- * endpoint means one of several unrelated things — no grant on the relay, the
279
- * relay is a TEE replica (`ReadOnlyTee`) or a `ReadOnly` member (neither ever
280
- * relays), the author is
281
- * not a member or is read-only in the context, or the nonce was already spent
282
- * — and they send a caller somewhere completely different: ask an admin, pick
283
- * a relay the namespace admits in `relay` mode, ask for an invitation, or just
284
- * retry. Collapsing them into "forbidden" makes a retryable replay look
285
- * like a permissions bug.
286
- */
287
- export declare class IntentRefusedError extends Error {
288
- /** The relay's own explanation, verbatim. */
289
- readonly reason: string;
290
- /** `true` when re-presenting the same intent under a *fresh* warrant may work. */
291
- readonly retryable: boolean;
292
- readonly status: number;
293
- name: string;
294
- constructor(
295
- /** The relay's own explanation, verbatim. */
296
- reason: string,
297
- /** `true` when re-presenting the same intent under a *fresh* warrant may work. */
298
- retryable: boolean, status: number);
299
- }
300
- export declare class RelayClient {
301
- private readonly baseUrl;
302
- private readonly config;
303
- private readonly fetchImpl;
304
- private readonly timeoutMs;
305
- /** How many times a 429 is waited out before it is raised. */
306
- private readonly rateLimitRetries;
307
- constructor(config: RelayClientConfig);
308
- /**
309
- * The relay's origin, trailing slash stripped.
310
- *
311
- * Exposed because a relay **is a node**: the same origin that answers the
312
- * intents routes also answers `/auth/challenge`, `/auth/token`, `/sse` and
313
- * `/ws`. Anything building an observing session over this relay needs the
314
- * URL, and asking the caller to pass it a second time is how the two drift.
315
- */
316
- get relayUrl(): string;
317
- /** The author's account, hex — whose consent every warrant here carries. */
318
- get authorAccount(): string;
319
- /**
320
- * The author's `AccountProof<DeviceCert>`, hex.
321
- *
322
- * The same credential `login()` wants, which is why it is readable: a caller
323
- * that already handed it to this client should not have to hand an identical
324
- * copy to the login as well, where the two could disagree.
325
- */
326
- get authorProof(): string;
327
- /**
328
- * The author device's signer.
329
- *
330
- * A {@link Signer} and never the secret: this returns something that can
331
- * *sign*, so no caller of a `RelayClient` gains the ability to read a key
332
- * that was passed in as `deviceSecret`. That asymmetry is the point — the
333
- * login needs a signature, not key material.
334
- */
335
- authorSigner(): Promise<Signer>;
336
- /**
337
- * Ask the relay what it can do in `contextId`.
338
- *
339
- * Cheap and unauthenticated on a relay that serves delegated execution
340
- * publicly, which is what makes it usable as a precondition check rather than
341
- * as diagnostics after a failure.
342
- */
343
- describe(contextId: string): Promise<RelayDescription>;
344
- /**
345
- * Mint a warrant for `method(args)` and present it to the relay.
346
- *
347
- * One intent, once: the warrant authorizes exactly this method and these
348
- * arguments in exactly this context, and its nonce is spent by the network on
349
- * apply. Nothing accumulates and nothing is reusable.
350
- */
351
- execute<T = unknown>(contextId: string, method: string, argsJson?: unknown): Promise<IntentResult<T>>;
352
- /**
353
- * Publish one presence statement through the relay (`presence-intents`).
354
- *
355
- * Not retried on 429: presence resends every 2.5 s anyway, and a retry would
356
- * only queue behind the next resend. A refusal throws with its `status`.
357
- */
358
- presenceIntent(contextId: string, body: {
359
- state: string | null;
360
- seq: number;
361
- sentAtMs: number;
362
- signature: string;
363
- authorProof: string;
364
- }): Promise<void>;
365
- /**
366
- * Ask the relay what it can do about creating contexts in `groupId`.
367
- *
368
- * Pass `author` (an account, hex) to also learn whether that account may
369
- * create here — `authorMayCreate` is present only then.
370
- */
371
- describeCreation(groupId: string, opts?: {
372
- author?: string;
373
- }): Promise<CreationDescription>;
374
- /**
375
- * Create a context in a group through the relay, as the author.
376
- *
377
- * Always asks {@link describeCreation} first — with the author, so both
378
- * standing checks happen before anything is signed. A relay without standing
379
- * in the group, or an author without `CAN_CREATE_CONTEXT`, is refused here as
380
- * an {@link IntentRefusedError} *before* a nonce is taken: the nonce source
381
- * is monotonic, and a warrant nobody will spend burns one for nothing.
382
- *
383
- * The creation warrant's nonce is spent in the new context's per-device
384
- * ledger — the same one later `execute` calls in that context draw from — so
385
- * it comes from the configured {@link NonceSource} like any other warrant.
386
- *
387
- * Sealing: nothing here is plaintext-specific. The request goes through the
388
- * injected `fetch`, so a `createAttestedSealedFetch` seals it exactly as it
389
- * seals `execute`. Whether the relay *accepts* it sealed is the node's call:
390
- * a proxy-auth relay only admits sealed requests for routes `merod` serves
391
- * without a credential, so `/admin-api/groups/:id/context-intents` must be on
392
- * that list on the core side or the request comes back
393
- * `403 sealed_route_unguarded`.
394
- */
395
- createContext(input: CreateContextInput): Promise<CreatedContext>;
396
- /**
397
- * Ask the relay whether it may publish governance ops for members of
398
- * `groupId`, and which account and key a warrant must name.
399
- */
400
- describeGovernance(groupId: string): Promise<GovernanceDescription>;
401
- /**
402
- * Publish one governance op through the relay, as the author.
403
- *
404
- * The warrant commits to the op's exact bytes and is scoped to `groupId`, so
405
- * the relay can neither change what the op does nor spend it elsewhere. Every
406
- * peer applies the op as the author, so the author's own rights decide
407
- * (`MANAGE_MEMBERS` to add a member, `CAN_CREATE_SUBGROUP` to create a
408
- * subgroup, and so on); a lack of them comes back as an
409
- * {@link IntentRefusedError} from the relay.
410
- *
411
- * Always asks {@link describeGovernance} first and refuses *before* taking a
412
- * nonce when the relay has no standing, for the reason `createContext` does.
413
- * The nonce comes from the configured {@link NonceSource}; it is spent in a
414
- * per-group ledger, and a monotonic source is correct for it as for every
415
- * other warrant.
416
- */
417
- govern(input: GovernInput): Promise<GovernResult>;
418
- /**
419
- * Found a namespace through the relay, with the author as its founder, owner
420
- * and admin. For an account with no node, this is how it gets a namespace at
421
- * all.
422
- *
423
- * The author signs the exact genesis (`NamespaceCreatedV2`, carrying the
424
- * author's own credential and the salt) under a root-plane governance
425
- * warrant scoped to the new namespace's id, which is derived from the
426
- * author's account and the salt, so the relay can neither choose another id
427
- * nor found it for anyone else. The relay takes an identity in the new
428
- * namespace, mints its key, publishes the genesis, and is seated as the
429
- * founding relay (a `Member` holding `CAN_AUTHOR_ON_BEHALF`), so later
430
- * `govern`, `createContext` and `execute` calls in the namespace work
431
- * through it straight away. A TEE relay then admits itself as the
432
- * namespace's first TEE; `teeEnabled` reports whether it did.
433
- *
434
- * The executor cannot be learned from the relay first: the namespace does not
435
- * exist, so `describeGovernance` has nothing to answer about. It comes from
436
- * `input.executor` only, and without it this throws before taking a nonce.
437
- * The nonce is spent in the new namespace's ledger.
438
- *
439
- * With `defaultCapabilities`, the founder then sets the namespace's default
440
- * capability mask through the same relay (a second warrant, a second nonce)
441
- * and `defaultCapabilitiesSet` reports whether it landed. A failure there
442
- * does not throw, since the namespace is already founded.
443
- *
444
- * Refusals (`400`/`403`) come back as {@link IntentRefusedError}; a salt
445
- * that names an existing namespace is a `409`, an `HTTPError`.
446
- */
447
- foundNamespace(input: FoundNamespaceInput): Promise<FoundedNamespace>;
448
- private postGovernance;
449
- /**
450
- * The relay's answer, checked against a configured account.
451
- * Decoded here so a relay naming no key is refused before a nonce is taken.
452
- */
453
- private checkedExecutor;
454
- /**
455
- * One request, waiting out a rate limit rather than failing the caller.
456
- *
457
- * The relay's ingress limits the delegated-execution routes to 20 requests a
458
- * second per source IP, burst 40 — tighter than everything else it serves,
459
- * because those two routes are the ones it answers to anonymous callers.
460
- *
461
- * Retrying a 429 is safe here in a way retrying most refusals is not: the
462
- * limiter sits *first* in the middleware chain, so a throttled request never
463
- * reached the node and its warrant nonce was never spent. The same bytes can
464
- * go again. Contrast the spent-nonce 403 below, which needs a fresh warrant.
465
- *
466
- * `Retry-After` is honoured when the ingress sends one; otherwise the wait
467
- * doubles from a little over the limiter's own window, which is the shortest
468
- * delay that can actually clear.
469
- */
470
- private json;
471
- private jsonOnce;
472
- }