@elisym/sdk 0.25.3 → 0.25.4
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/index.cjs +29 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +29 -5
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +47 -28
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +6 -0
- package/dist/node.d.ts +6 -0
- package/dist/node.js +47 -28
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -801,13 +801,22 @@ declare class BlossomService {
|
|
|
801
801
|
/** Delete a blob by sha256 (BUD-02). Blossom only - there is no fallback for deletes. */
|
|
802
802
|
delete(identity: ElisymIdentity, sha256: string): Promise<void>;
|
|
803
803
|
/**
|
|
804
|
-
* Download a
|
|
805
|
-
* the declared Content-Length) and verifies the sha256 when
|
|
804
|
+
* Download a content-addressed blob from THIS Blossom server (BUD-01 GET, no auth). Bounds memory
|
|
805
|
+
* on the ACTUAL streamed bytes (never the declared Content-Length) and verifies the sha256 when
|
|
806
|
+
* `expectedSha256` is given. Browser-safe.
|
|
807
|
+
*
|
|
808
|
+
* SSRF guard: `url` typically arrives inside a remote counterparty's encrypted job envelope, so it
|
|
809
|
+
* is untrusted. elisym blobs are content-addressed on the single configured server (`seedBytes`
|
|
810
|
+
* refuses non-content-addressed fallbacks), so a legitimate URL is always `<serverUrl>/<sha256>`.
|
|
811
|
+
* The origin is pinned to `serverUrl` and redirects are refused, so a crafted url (or a 30x from
|
|
812
|
+
* the host) can't coerce a fetch to loopback, cloud-metadata, or internal addresses. Federation
|
|
813
|
+
* across Blossom servers would replace this single-origin pin with an explicit allowlist.
|
|
806
814
|
*/
|
|
807
815
|
download(url: string, opts?: {
|
|
808
816
|
maxBytes?: number;
|
|
809
817
|
timeoutMs?: number;
|
|
810
818
|
expectedSha256?: string;
|
|
819
|
+
signal?: AbortSignal;
|
|
811
820
|
}): Promise<Uint8Array>;
|
|
812
821
|
private uploadToBlossom;
|
|
813
822
|
private authHeader;
|
|
@@ -1171,6 +1180,8 @@ interface BlossomBlobTransport {
|
|
|
1171
1180
|
transport: BlossomTransport;
|
|
1172
1181
|
senderPubkey: string;
|
|
1173
1182
|
maxBytes?: number;
|
|
1183
|
+
/** Abort the in-flight download (e.g. job stop() / input-fetch budget). */
|
|
1184
|
+
signal?: AbortSignal;
|
|
1174
1185
|
}): Promise<Uint8Array>;
|
|
1175
1186
|
}
|
|
1176
1187
|
declare function createBlossomTransport(opts: {
|
package/dist/index.d.ts
CHANGED
|
@@ -801,13 +801,22 @@ declare class BlossomService {
|
|
|
801
801
|
/** Delete a blob by sha256 (BUD-02). Blossom only - there is no fallback for deletes. */
|
|
802
802
|
delete(identity: ElisymIdentity, sha256: string): Promise<void>;
|
|
803
803
|
/**
|
|
804
|
-
* Download a
|
|
805
|
-
* the declared Content-Length) and verifies the sha256 when
|
|
804
|
+
* Download a content-addressed blob from THIS Blossom server (BUD-01 GET, no auth). Bounds memory
|
|
805
|
+
* on the ACTUAL streamed bytes (never the declared Content-Length) and verifies the sha256 when
|
|
806
|
+
* `expectedSha256` is given. Browser-safe.
|
|
807
|
+
*
|
|
808
|
+
* SSRF guard: `url` typically arrives inside a remote counterparty's encrypted job envelope, so it
|
|
809
|
+
* is untrusted. elisym blobs are content-addressed on the single configured server (`seedBytes`
|
|
810
|
+
* refuses non-content-addressed fallbacks), so a legitimate URL is always `<serverUrl>/<sha256>`.
|
|
811
|
+
* The origin is pinned to `serverUrl` and redirects are refused, so a crafted url (or a 30x from
|
|
812
|
+
* the host) can't coerce a fetch to loopback, cloud-metadata, or internal addresses. Federation
|
|
813
|
+
* across Blossom servers would replace this single-origin pin with an explicit allowlist.
|
|
806
814
|
*/
|
|
807
815
|
download(url: string, opts?: {
|
|
808
816
|
maxBytes?: number;
|
|
809
817
|
timeoutMs?: number;
|
|
810
818
|
expectedSha256?: string;
|
|
819
|
+
signal?: AbortSignal;
|
|
811
820
|
}): Promise<Uint8Array>;
|
|
812
821
|
private uploadToBlossom;
|
|
813
822
|
private authHeader;
|
|
@@ -1171,6 +1180,8 @@ interface BlossomBlobTransport {
|
|
|
1171
1180
|
transport: BlossomTransport;
|
|
1172
1181
|
senderPubkey: string;
|
|
1173
1182
|
maxBytes?: number;
|
|
1183
|
+
/** Abort the in-flight download (e.g. job stop() / input-fetch budget). */
|
|
1184
|
+
signal?: AbortSignal;
|
|
1174
1185
|
}): Promise<Uint8Array>;
|
|
1175
1186
|
}
|
|
1176
1187
|
declare function createBlossomTransport(opts: {
|
package/dist/index.js
CHANGED
|
@@ -1262,18 +1262,38 @@ var BlossomService = class {
|
|
|
1262
1262
|
}
|
|
1263
1263
|
}
|
|
1264
1264
|
/**
|
|
1265
|
-
* Download a
|
|
1266
|
-
* the declared Content-Length) and verifies the sha256 when
|
|
1265
|
+
* Download a content-addressed blob from THIS Blossom server (BUD-01 GET, no auth). Bounds memory
|
|
1266
|
+
* on the ACTUAL streamed bytes (never the declared Content-Length) and verifies the sha256 when
|
|
1267
|
+
* `expectedSha256` is given. Browser-safe.
|
|
1268
|
+
*
|
|
1269
|
+
* SSRF guard: `url` typically arrives inside a remote counterparty's encrypted job envelope, so it
|
|
1270
|
+
* is untrusted. elisym blobs are content-addressed on the single configured server (`seedBytes`
|
|
1271
|
+
* refuses non-content-addressed fallbacks), so a legitimate URL is always `<serverUrl>/<sha256>`.
|
|
1272
|
+
* The origin is pinned to `serverUrl` and redirects are refused, so a crafted url (or a 30x from
|
|
1273
|
+
* the host) can't coerce a fetch to loopback, cloud-metadata, or internal addresses. Federation
|
|
1274
|
+
* across Blossom servers would replace this single-origin pin with an explicit allowlist.
|
|
1267
1275
|
*/
|
|
1268
1276
|
async download(url, opts = {}) {
|
|
1277
|
+
if (new URL(url).origin !== new URL(this.serverUrl).origin) {
|
|
1278
|
+
throw new Error(`Refusing to download from a non-Blossom origin: ${url}`);
|
|
1279
|
+
}
|
|
1269
1280
|
const maxBytes = opts.maxBytes ?? LIMITS.MAX_FILE_SIZE;
|
|
1270
1281
|
const controller = new AbortController();
|
|
1271
1282
|
const timer = setTimeout(
|
|
1272
1283
|
() => controller.abort(),
|
|
1273
1284
|
opts.timeoutMs ?? DEFAULTS.BLOSSOM_FETCH_TIMEOUT_MS
|
|
1274
1285
|
);
|
|
1286
|
+
const externalSignal = opts.signal;
|
|
1287
|
+
const onExternalAbort = () => controller.abort();
|
|
1288
|
+
if (externalSignal !== void 0) {
|
|
1289
|
+
if (externalSignal.aborted) {
|
|
1290
|
+
controller.abort();
|
|
1291
|
+
} else {
|
|
1292
|
+
externalSignal.addEventListener("abort", onExternalAbort, { once: true });
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1275
1295
|
try {
|
|
1276
|
-
const res = await fetch(url, { signal: controller.signal });
|
|
1296
|
+
const res = await fetch(url, { signal: controller.signal, redirect: "error" });
|
|
1277
1297
|
if (!res.ok) {
|
|
1278
1298
|
throw new Error(`Download failed: ${res.status} ${res.statusText}`);
|
|
1279
1299
|
}
|
|
@@ -1315,6 +1335,9 @@ var BlossomService = class {
|
|
|
1315
1335
|
return bytes;
|
|
1316
1336
|
} finally {
|
|
1317
1337
|
clearTimeout(timer);
|
|
1338
|
+
if (externalSignal !== void 0) {
|
|
1339
|
+
externalSignal.removeEventListener("abort", onExternalAbort);
|
|
1340
|
+
}
|
|
1318
1341
|
}
|
|
1319
1342
|
}
|
|
1320
1343
|
async uploadToBlossom(identity, bytes, hashHex, mime) {
|
|
@@ -3712,11 +3735,12 @@ function createBlossomTransport(opts) {
|
|
|
3712
3735
|
enc: { alg: "AES-256-GCM", iv, key: wrappedKey }
|
|
3713
3736
|
};
|
|
3714
3737
|
},
|
|
3715
|
-
async fetchToBytes({ transport, senderPubkey, maxBytes }) {
|
|
3738
|
+
async fetchToBytes({ transport, senderPubkey, maxBytes, signal }) {
|
|
3716
3739
|
const plaintextCap = maxBytes ?? LIMITS.MAX_BLOSSOM_ENCRYPTED_BYTES;
|
|
3717
3740
|
const ciphertext = await blossom.download(transport.url, {
|
|
3718
3741
|
maxBytes: plaintextCap + AES_GCM_TAG_BYTES,
|
|
3719
|
-
expectedSha256: transport.sha256
|
|
3742
|
+
expectedSha256: transport.sha256,
|
|
3743
|
+
signal
|
|
3720
3744
|
});
|
|
3721
3745
|
return decryptBytesFromSender(
|
|
3722
3746
|
ciphertext,
|