@amalgm/live 0.2.13 → 0.2.15
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/PURPOSE.md +6 -0
- package/dist/transfer/download.d.ts +3 -3
- package/dist/transfer/download.d.ts.map +1 -1
- package/dist/transfer/download.js +2 -2
- package/dist/transfer/download.js.map +1 -1
- package/dist/transfer/parallel.d.ts.map +1 -1
- package/dist/transfer/parallel.js +11 -2
- package/dist/transfer/parallel.js.map +1 -1
- package/dist/transfer/upload.d.ts +10 -2
- package/dist/transfer/upload.d.ts.map +1 -1
- package/dist/transfer/upload.js +28 -2
- package/dist/transfer/upload.js.map +1 -1
- package/package.json +1 -1
package/PURPOSE.md
CHANGED
|
@@ -144,6 +144,12 @@ its cutover.
|
|
|
144
144
|
stronger current-content witness exists. Repository packing remains
|
|
145
145
|
transfer preparation and may run beside structural registration, but
|
|
146
146
|
neither act may weaken the other's result.
|
|
147
|
+
30. **Proof travels forward; bytes do not travel backward.** Capture derives
|
|
148
|
+
and stores a block manifest while it already owns an artifact's bytes.
|
|
149
|
+
Cold upload reads those sealed bytes once to send them, and cold download
|
|
150
|
+
writes received bytes once before their registered adapter consumes them.
|
|
151
|
+
Reopening a complete artifact to recreate or repeat an earlier integrity
|
|
152
|
+
proof is redundant work, not additional correctness.
|
|
147
153
|
|
|
148
154
|
## Five surfaces, one behavior
|
|
149
155
|
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
* the complete artifact. Sealing must verify the whole byte count and content
|
|
7
7
|
* hash before returning a local handle.
|
|
8
8
|
*/
|
|
9
|
-
import { type
|
|
9
|
+
import { type ContentManifest } from '../contracts/content.js';
|
|
10
10
|
import type { Sha256Hex } from '../entities/types.js';
|
|
11
11
|
import { type TransferArtifact } from './artifacts.js';
|
|
12
12
|
export interface DownloadPorts<LocalArtifact> {
|
|
13
13
|
readonly sha256Hex: Sha256Hex;
|
|
14
14
|
getManifest(artifact: TransferArtifact): Promise<unknown>;
|
|
15
15
|
/** True only when this exact content-addressed chunk is locally verified. */
|
|
16
|
-
hasChunk(
|
|
16
|
+
hasChunk(artifact: TransferArtifact, manifest: ContentManifest, index: number): Promise<boolean>;
|
|
17
17
|
getChunk(artifact: TransferArtifact, manifest: ContentManifest, index: number): Promise<Uint8Array>;
|
|
18
|
-
putChunk(
|
|
18
|
+
putChunk(artifact: TransferArtifact, manifest: ContentManifest, index: number, bytes: Uint8Array): Promise<void>;
|
|
19
19
|
/** Verify and expose the complete immutable artifact assembled from cache. */
|
|
20
20
|
sealArtifact(artifact: TransferArtifact, manifest: ContentManifest): Promise<SealedArtifact<LocalArtifact>>;
|
|
21
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/transfer/download.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAwB,KAAK,
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/transfer/download.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,MAAM,WAAW,aAAa,CAAC,aAAa;IAC1C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,6EAA6E;IAC7E,QAAQ,CACN,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,QAAQ,CACN,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,QAAQ,CACN,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,8EAA8E;IAC9E,YAAY,CACV,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,cAAc,CAAC,aAAa;IAC3C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe,CAAC,aAAa;IAC5C,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,yEAAyE;AACzE,wBAAsB,QAAQ,CAAC,aAAa,EAC1C,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,EACnC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CAqCzC"}
|
|
@@ -18,7 +18,7 @@ export async function download(artifact, ports, options = {}) {
|
|
|
18
18
|
const manifest = checked.value;
|
|
19
19
|
const missing = [];
|
|
20
20
|
for (const [index, chunk] of manifest.chunks.entries()) {
|
|
21
|
-
if (!await ports.hasChunk(
|
|
21
|
+
if (!await ports.hasChunk(artifact, manifest, index))
|
|
22
22
|
missing.push(index);
|
|
23
23
|
}
|
|
24
24
|
await parallelForEach(missing, options.concurrency ?? 4, async (index) => {
|
|
@@ -31,7 +31,7 @@ export async function download(artifact, ports, options = {}) {
|
|
|
31
31
|
|| ports.sha256Hex(bytes) !== expected.sha256) {
|
|
32
32
|
throw new Error(`downloaded content chunk ${index} failed verification`);
|
|
33
33
|
}
|
|
34
|
-
await ports.putChunk(
|
|
34
|
+
await ports.putChunk(artifact, manifest, index, bytes);
|
|
35
35
|
});
|
|
36
36
|
const sealed = await ports.sealArtifact(artifact, manifest);
|
|
37
37
|
if (sealed.bytes !== manifest.bytes || sealed.contentHash !== manifest.contentHash) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/transfer/download.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/transfer/download.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAwB,MAAM,yBAAyB,CAAC;AAErF,OAAO,EAAE,sBAAsB,EAAyB,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AA+ChD,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAA0B,EAC1B,KAAmC,EACnC,UAA2B,EAAE;IAE7B,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,oBAAoB,CAClC,MAAM,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EACjC,QAAQ,CAAC,WAAW,CACrB,CAAC;IACF,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAE/B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACvE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC9F,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC;eAC7B,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,KAAK;eACnC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,sBAAsB,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5D,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,IAAI,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,WAAW,sBAAsB,CAAC,CAAC;IACrF,CAAC;IACD,OAAO;QACL,QAAQ;QACR,QAAQ;QACR,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,gBAAgB,EAAE,OAAO,CAAC,MAAM;QAChC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;KACtD,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../src/transfer/parallel.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAsB,eAAe,CAAC,CAAC,EACrC,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../src/transfer/parallel.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAsB,eAAe,CAAC,CAAC,EACrC,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,CAuBf"}
|
|
@@ -4,15 +4,24 @@ export async function parallelForEach(items, concurrency, effect) {
|
|
|
4
4
|
throw new Error('transfer concurrency must be a positive integer');
|
|
5
5
|
}
|
|
6
6
|
let cursor = 0;
|
|
7
|
+
let failure;
|
|
7
8
|
const worker = async () => {
|
|
8
|
-
while (cursor < items.length) {
|
|
9
|
+
while (failure === undefined && cursor < items.length) {
|
|
9
10
|
const index = cursor;
|
|
10
11
|
cursor += 1;
|
|
11
12
|
const item = items[index];
|
|
12
|
-
if (item
|
|
13
|
+
if (item === undefined)
|
|
14
|
+
continue;
|
|
15
|
+
try {
|
|
13
16
|
await effect(item);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
failure ??= error;
|
|
20
|
+
}
|
|
14
21
|
}
|
|
15
22
|
};
|
|
16
23
|
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, worker));
|
|
24
|
+
if (failure !== undefined)
|
|
25
|
+
throw failure;
|
|
17
26
|
}
|
|
18
27
|
//# sourceMappingURL=parallel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/transfer/parallel.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAmB,EACnB,WAAmB,EACnB,MAAkC;IAElC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;QACvC,OAAO,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/transfer/parallel.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAmB,EACnB,WAAmB,EACnB,MAAkC;IAElC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,OAAgB,CAAC;IACrB,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;QACvC,OAAO,OAAO,KAAK,SAAS,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,MAAM,CAAC;YACrB,MAAM,IAAI,CAAC,CAAC;YACZ,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,KAAK,KAAK,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CACpE,CAAC;IACF,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,OAAO,CAAC;AAC3C,CAAC"}
|
|
@@ -13,8 +13,11 @@ export interface UploadSource {
|
|
|
13
13
|
readonly bytes: number;
|
|
14
14
|
/** Previously derived local metadata. Invalid metadata is refused. */
|
|
15
15
|
readonly manifest?: unknown;
|
|
16
|
-
/**
|
|
17
|
-
|
|
16
|
+
/** True only when `manifest` was derived while sealing this immutable,
|
|
17
|
+
* content-addressed source. Sent chunks are still checked individually. */
|
|
18
|
+
readonly manifestVerified?: boolean;
|
|
19
|
+
/** Verify an unsealed source without requiring Live to buffer it. */
|
|
20
|
+
verify?(contentHash: string): Promise<boolean>;
|
|
18
21
|
/** Return exactly `bytes` bytes beginning at `offset`. */
|
|
19
22
|
read(offset: number, bytes: number): Promise<Uint8Array>;
|
|
20
23
|
}
|
|
@@ -35,6 +38,11 @@ export interface UploadReceipt {
|
|
|
35
38
|
readonly uploadedChunks: number;
|
|
36
39
|
readonly reusedChunks: number;
|
|
37
40
|
}
|
|
41
|
+
/** Derive the reusable upload evidence while capture already owns the bytes.
|
|
42
|
+
* A host persists this beside its immutable artifact so upload never has to
|
|
43
|
+
* rediscover block boundaries or reread the complete source just to prove the
|
|
44
|
+
* work registration already completed. */
|
|
45
|
+
export declare function deriveUploadManifest(artifact: TransferArtifact, bytes: Uint8Array, sha256Hex: Sha256Hex): ContentManifest;
|
|
38
46
|
/** Upload one immutable artifact, sending only authority-declared gaps. */
|
|
39
47
|
export declare function upload(artifact: TransferArtifact, source: UploadSource, ports: UploadPorts, options?: UploadOptions): Promise<UploadReceipt>;
|
|
40
48
|
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/transfer/upload.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/transfer/upload.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;+EAC2E;IAC3E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC,qEAAqE;IACrE,MAAM,CAAC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,0DAA0D;IAC1D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,oEAAoE;IACpE,aAAa,CACX,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAC9B,QAAQ,CACN,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,8EAA8E;IAC9E,WAAW,CAAC,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAyCD;;;0CAG0C;AAC1C,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,SAAS,GACnB,eAAe,CAejB;AAUD,2EAA2E;AAC3E,wBAAsB,MAAM,CAC1B,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,aAAa,CAAC,CA4DxB"}
|
package/dist/transfer/upload.js
CHANGED
|
@@ -39,6 +39,27 @@ const artifactPartSizes = (artifact, totalBytes) => {
|
|
|
39
39
|
return fixedSizes(totalBytes, MAX_CONTENT_BLOCK_BYTES);
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
|
+
/** Derive the reusable upload evidence while capture already owns the bytes.
|
|
43
|
+
* A host persists this beside its immutable artifact so upload never has to
|
|
44
|
+
* rediscover block boundaries or reread the complete source just to prove the
|
|
45
|
+
* work registration already completed. */
|
|
46
|
+
export function deriveUploadManifest(artifact, bytes, sha256Hex) {
|
|
47
|
+
assertTransferArtifact(artifact);
|
|
48
|
+
if (sha256Hex(bytes) !== artifact.contentHash) {
|
|
49
|
+
throw new Error(`captured artifact does not match ${artifact.contentHash}`);
|
|
50
|
+
}
|
|
51
|
+
const chunks = [];
|
|
52
|
+
let offset = 0;
|
|
53
|
+
for (const size of artifactPartSizes(artifact, bytes.byteLength)) {
|
|
54
|
+
const part = bytes.subarray(offset, offset + size);
|
|
55
|
+
chunks.push({ sha256: sha256Hex(part), bytes: size });
|
|
56
|
+
offset += size;
|
|
57
|
+
}
|
|
58
|
+
const checked = manifestFromChunks(artifact.contentHash, chunks);
|
|
59
|
+
if (!checked.ok)
|
|
60
|
+
throw new Error(checked.error);
|
|
61
|
+
return checked.value;
|
|
62
|
+
}
|
|
42
63
|
const readExact = async (source, chunk) => {
|
|
43
64
|
const bytes = await source.read(chunk.offset, chunk.bytes);
|
|
44
65
|
if (!(bytes instanceof Uint8Array) || bytes.byteLength !== chunk.bytes) {
|
|
@@ -52,6 +73,9 @@ export async function upload(artifact, source, ports, options = {}) {
|
|
|
52
73
|
if (!Number.isSafeInteger(source.bytes) || source.bytes < 0) {
|
|
53
74
|
throw new Error('upload source byte count is invalid');
|
|
54
75
|
}
|
|
76
|
+
if (source.manifestVerified === true && source.manifest === undefined) {
|
|
77
|
+
throw new Error('verified upload manifest is missing');
|
|
78
|
+
}
|
|
55
79
|
const expectedSizes = artifactPartSizes(artifact, source.bytes);
|
|
56
80
|
let plan;
|
|
57
81
|
let manifest;
|
|
@@ -82,8 +106,10 @@ export async function upload(artifact, source, ports, options = {}) {
|
|
|
82
106
|
|| missing.some((index) => !Number.isSafeInteger(index) || index < 0 || index >= plan.length)) {
|
|
83
107
|
throw new Error('upload authority returned invalid missing chunk indexes');
|
|
84
108
|
}
|
|
85
|
-
if (missing.length > 0 &&
|
|
86
|
-
|
|
109
|
+
if (missing.length > 0 && source.manifestVerified !== true) {
|
|
110
|
+
if (!source.verify || !await source.verify(artifact.contentHash)) {
|
|
111
|
+
throw new Error(`upload source does not match ${artifact.contentHash}`);
|
|
112
|
+
}
|
|
87
113
|
}
|
|
88
114
|
await parallelForEach(missing, options.concurrency ?? 4, async (index) => {
|
|
89
115
|
const chunk = plan[index];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/transfer/upload.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,UAAU,EACV,kBAAkB,GAEnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,sBAAsB,EAAyB,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/transfer/upload.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,UAAU,EACV,kBAAkB,GAEnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,sBAAsB,EAAyB,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAkDhD,MAAM,UAAU,GAAG,CAAC,KAAwB,EAA2B,EAAE;IACvE,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC/B,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC7C,MAAM,IAAI,IAAI,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,UAAkB,EAAE,SAAiB,EAAY,EAAE;IACrE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,SAAS,GAAG,UAAU,EAAE,SAAS,GAAG,CAAC,EAAE,SAAS,IAAI,SAAS,EAAE,CAAC;QACvE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;gFAGgF;AAChF,MAAM,iBAAiB,GAAG,CAAC,QAA0B,EAAE,UAAkB,EAAqB,EAAE;IAC9F,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,MAAM;YACT,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC;QAChC,KAAK,MAAM;YACT,IAAI,UAAU,GAAG,uBAAuB;gBAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC1G,OAAO,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC9C,KAAK,KAAK;YACR,OAAO,UAAU,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC,CAAC;AAEF;;;0CAG0C;AAC1C,MAAM,UAAU,oBAAoB,CAClC,QAA0B,EAC1B,KAAiB,EACjB,SAAoB;IAEpB,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,IAAI,CAAC;IACjB,CAAC;IACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChD,OAAO,OAAO,CAAC,KAAK,CAAC;AACvB,CAAC;AAED,MAAM,SAAS,GAAG,KAAK,EAAE,MAAoB,EAAE,KAAmB,EAAuB,EAAE;IACzF,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,yDAAyD,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,QAA0B,EAC1B,MAAoB,EACpB,KAAkB,EAClB,UAAyB,EAAE;IAE3B,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,MAAM,CAAC,gBAAgB,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAChE,IAAI,IAA6B,CAAC;IAClC,IAAI,QAAyB,CAAC;IAC9B,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK;eAChD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,aAAa,CAAC,KAAK,CAAC,CAAC;eAChF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QACD,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;QACxB,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAC3B,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnE,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM;WACvC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAChG,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAC7F,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,6CAA6C,KAAK,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5C,OAAO;QACL,QAAQ;QACR,QAAQ;QACR,cAAc,EAAE,OAAO,CAAC,MAAM;QAC9B,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;KACtD,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amalgm/live",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
4
|
"description": "Portable realtime SDK for Amalgm — wire contracts, mutation discipline, and delivery state machines behind host-injected adapters.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|