@calimero-network/mero-js 19.24.0 → 19.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin-api/admin-client.d.ts +29 -1
- package/dist/admin-api/admin-client.js +43 -0
- package/dist/admin-api/admin-types.d.ts +78 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +3 -3
- package/dist/index.cjs +86 -3
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +86 -3
- package/dist/index.mjs.map +2 -2
- package/dist/sealed/sealed.d.ts +5 -1
- package/dist/sealed/sealed.js +50 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -929,6 +929,14 @@ var AdminApiClient = class {
|
|
|
929
929
|
async healthCheck() {
|
|
930
930
|
return unwrap(await this.httpClient.get("/admin-api/health"));
|
|
931
931
|
}
|
|
932
|
+
/**
|
|
933
|
+
* Whether the node has finished starting and its store answers. Public, like
|
|
934
|
+
* {@link healthCheck}; unlike it, a node that is up but not ready answers
|
|
935
|
+
* `503`, which this surfaces as an `HTTPError` whose body names the stage.
|
|
936
|
+
*/
|
|
937
|
+
async readinessCheck() {
|
|
938
|
+
return unwrap(await this.httpClient.get("/admin-api/ready"));
|
|
939
|
+
}
|
|
932
940
|
async isAuthed() {
|
|
933
941
|
return this.httpClient.get("/admin-api/is-authed");
|
|
934
942
|
}
|
|
@@ -1323,6 +1331,23 @@ var AdminApiClient = class {
|
|
|
1323
1331
|
)
|
|
1324
1332
|
);
|
|
1325
1333
|
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Read a context as the session's ACCOUNT, without minting a warrant.
|
|
1336
|
+
*
|
|
1337
|
+
* Needs an account-authenticated session — one from {@link login}, not the
|
|
1338
|
+
* admin password login — and refuses otherwise with a `401`. The account must
|
|
1339
|
+
* be a member of the group owning the context (`403` if not), and the method
|
|
1340
|
+
* must be declared read-only in the app's ABI (`409` if not; a write needs
|
|
1341
|
+
* {@link performIntent}).
|
|
1342
|
+
*/
|
|
1343
|
+
async queryContext(contextId, request) {
|
|
1344
|
+
return unwrap(
|
|
1345
|
+
await this.httpClient.post(
|
|
1346
|
+
`/admin-api/contexts/${contextId}/query`,
|
|
1347
|
+
request
|
|
1348
|
+
)
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1326
1351
|
/**
|
|
1327
1352
|
* Ask what this node can do for a member in `contextId`, before they sign
|
|
1328
1353
|
* anything.
|
|
@@ -1645,6 +1670,32 @@ var AdminApiClient = class {
|
|
|
1645
1670
|
}
|
|
1646
1671
|
return response;
|
|
1647
1672
|
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Member accounts in the group and the devices bound to each. An admin node
|
|
1675
|
+
* sees every account; a plain member only its own. `403` if this node is not a
|
|
1676
|
+
* member of the group.
|
|
1677
|
+
*/
|
|
1678
|
+
async listMemberDevices(groupId, options = {}) {
|
|
1679
|
+
const params = new URLSearchParams();
|
|
1680
|
+
if (options.offset !== void 0) params.set("offset", String(options.offset));
|
|
1681
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
1682
|
+
const query = params.toString();
|
|
1683
|
+
const path = `/admin-api/groups/${groupId}/member-devices${query ? `?${query}` : ""}`;
|
|
1684
|
+
return this.httpClient.get(path);
|
|
1685
|
+
}
|
|
1686
|
+
/**
|
|
1687
|
+
* Seal a small payload to a member account's root key. This node must be a
|
|
1688
|
+
* member of the group, and `account` must be an account the group knows, so
|
|
1689
|
+
* the route reaches no further than the caller already does.
|
|
1690
|
+
*/
|
|
1691
|
+
async sealToAccount(groupId, account, request) {
|
|
1692
|
+
return unwrap(
|
|
1693
|
+
await this.httpClient.post(
|
|
1694
|
+
`/admin-api/groups/${groupId}/accounts/${account}/seal`,
|
|
1695
|
+
request
|
|
1696
|
+
)
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1648
1699
|
async listGroupContexts(groupId) {
|
|
1649
1700
|
return unwrap(await this.httpClient.get(`/admin-api/groups/${groupId}/contexts`));
|
|
1650
1701
|
}
|
|
@@ -6760,6 +6811,8 @@ var HEADER_LEN = 1 + SESSION_ID_LEN + 8;
|
|
|
6760
6811
|
var FRAME_HEAD = 0;
|
|
6761
6812
|
var FRAME_DATA = 1;
|
|
6762
6813
|
var FRAME_END = 2;
|
|
6814
|
+
var MAX_FRAME_LEN = 1 + 64 * 1024 + 16;
|
|
6815
|
+
var MAX_HANDSHAKE_REPLY = 1024;
|
|
6763
6816
|
var RENEW_BEFORE_MS = 6e4;
|
|
6764
6817
|
var TRANSPORT_BINDING_DOMAIN = "calimero.tee-attest.transport-key.v1";
|
|
6765
6818
|
var NULL_BODY_STATUSES = [101, 204, 205, 304];
|
|
@@ -6771,10 +6824,11 @@ var StaleTransportKeyError = class extends Error {
|
|
|
6771
6824
|
}
|
|
6772
6825
|
};
|
|
6773
6826
|
var SealedTransportError = class extends Error {
|
|
6774
|
-
constructor(status, code, message) {
|
|
6827
|
+
constructor(status, code, message, retryAfterMs) {
|
|
6775
6828
|
super(message);
|
|
6776
6829
|
this.status = status;
|
|
6777
6830
|
this.code = code;
|
|
6831
|
+
this.retryAfterMs = retryAfterMs;
|
|
6778
6832
|
this.name = "SealedTransportError";
|
|
6779
6833
|
}
|
|
6780
6834
|
};
|
|
@@ -6878,6 +6932,15 @@ async function checkedKey(key) {
|
|
|
6878
6932
|
return bytes;
|
|
6879
6933
|
}
|
|
6880
6934
|
async function handshake(baseFetch, nodeUrl, transportKey) {
|
|
6935
|
+
try {
|
|
6936
|
+
return await handshakeOnce(baseFetch, nodeUrl, transportKey);
|
|
6937
|
+
} catch (error) {
|
|
6938
|
+
if (!(error instanceof SealedTransportError) || error.code !== "busy") throw error;
|
|
6939
|
+
await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 1e3));
|
|
6940
|
+
return handshakeOnce(baseFetch, nodeUrl, transportKey);
|
|
6941
|
+
}
|
|
6942
|
+
}
|
|
6943
|
+
async function handshakeOnce(baseFetch, nodeUrl, transportKey) {
|
|
6881
6944
|
const noise = await initiate(transportKey, PROLOGUE);
|
|
6882
6945
|
const response = await baseFetch(`${nodeUrl}${HANDSHAKE_PATH}`, {
|
|
6883
6946
|
method: "POST",
|
|
@@ -6887,7 +6950,7 @@ async function handshake(baseFetch, nodeUrl, transportKey) {
|
|
|
6887
6950
|
if (response.headers.get("content-type") !== SEALED_CONTENT_TYPE) {
|
|
6888
6951
|
throw await envelopeRefusal(response);
|
|
6889
6952
|
}
|
|
6890
|
-
const reply =
|
|
6953
|
+
const reply = await readAtMost(response, MAX_HANDSHAKE_REPLY);
|
|
6891
6954
|
return sessionFrom(noise, reply);
|
|
6892
6955
|
}
|
|
6893
6956
|
async function sessionFrom(noise, reply) {
|
|
@@ -7013,6 +7076,10 @@ function frameReader(reader) {
|
|
|
7013
7076
|
async next() {
|
|
7014
7077
|
if (!await fill(4)) return null;
|
|
7015
7078
|
const length = new DataView(buffer.buffer, buffer.byteOffset).getUint32(0, false);
|
|
7079
|
+
if (length > MAX_FRAME_LEN) {
|
|
7080
|
+
await reader.cancel();
|
|
7081
|
+
throw new Error("The sealed response is malformed: a frame is larger than the node sends");
|
|
7082
|
+
}
|
|
7016
7083
|
if (!await fill(4 + length)) return null;
|
|
7017
7084
|
const frame = buffer.slice(4, 4 + length);
|
|
7018
7085
|
buffer = buffer.slice(4 + length);
|
|
@@ -7021,6 +7088,20 @@ function frameReader(reader) {
|
|
|
7021
7088
|
cancel: () => reader.cancel()
|
|
7022
7089
|
};
|
|
7023
7090
|
}
|
|
7091
|
+
async function readAtMost(response, limit) {
|
|
7092
|
+
if (!response.body) return new Uint8Array();
|
|
7093
|
+
const reader = response.body.getReader();
|
|
7094
|
+
let bytes = new Uint8Array();
|
|
7095
|
+
for (; ; ) {
|
|
7096
|
+
const { done, value } = await reader.read();
|
|
7097
|
+
if (done) return bytes;
|
|
7098
|
+
bytes = concat(bytes, value);
|
|
7099
|
+
if (bytes.length > limit) {
|
|
7100
|
+
await reader.cancel();
|
|
7101
|
+
throw new Error("The handshake reply is malformed: it is too long");
|
|
7102
|
+
}
|
|
7103
|
+
}
|
|
7104
|
+
}
|
|
7024
7105
|
async function envelopeRefusal(response) {
|
|
7025
7106
|
let code;
|
|
7026
7107
|
let message = `Sealed request refused: HTTP ${response.status}`;
|
|
@@ -7031,7 +7112,9 @@ async function envelopeRefusal(response) {
|
|
|
7031
7112
|
} catch {
|
|
7032
7113
|
}
|
|
7033
7114
|
if (code === "stale_transport_key") return new StaleTransportKeyError();
|
|
7034
|
-
|
|
7115
|
+
const retryAfter = Number(response.headers.get("retry-after"));
|
|
7116
|
+
const retryAfterMs = Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter, 5) * 1e3 : void 0;
|
|
7117
|
+
return new SealedTransportError(response.status, code, message, retryAfterMs);
|
|
7035
7118
|
}
|
|
7036
7119
|
|
|
7037
7120
|
// src/namespace-op/namespace-op.ts
|