@opengeni/storage 0.2.96 → 0.2.106-canary.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/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { type FileAsset } from "@opengeni/contracts";
3
3
  export * from "./bounded-object-read.js";
4
4
  export * from "./bounded-object-write.js";
5
5
  export * from "./object-storage-bounded.js";
6
+ export * from "./retry-while-missing.js";
6
7
  export declare const MAX_SINGLE_PUT_SIZE_BYTES = 5000000000;
7
8
  export declare const UPLOAD_URL_TTL_SECONDS: number;
8
9
  export declare const DOWNLOAD_URL_TTL_SECONDS: number;
package/dist/index.js CHANGED
@@ -210,6 +210,34 @@ function messageForCode(code) {
210
210
 
211
211
  // src/bounded-object-write.ts
212
212
  import { createHash } from "crypto";
213
+
214
+ // src/retry-while-missing.ts
215
+ var OBJECT_VISIBILITY_RETRY_DELAYS_MS = [50, 100, 200, 400, 400, 400, 400];
216
+ async function retryWhileMissing(load, options = {}) {
217
+ const delays = options.delaysMs ?? OBJECT_VISIBILITY_RETRY_DELAYS_MS;
218
+ const sleep = options.sleep ?? defaultSleep;
219
+ for (let attempt = 0; ; attempt += 1) {
220
+ throwIfAborted2(options.signal);
221
+ const value = await load();
222
+ if (value !== null) return value;
223
+ if (attempt >= delays.length) return null;
224
+ await sleep(delays[attempt]);
225
+ throwIfAborted2(options.signal);
226
+ }
227
+ }
228
+ function defaultSleep(ms) {
229
+ return new Promise((resolve) => {
230
+ setTimeout(resolve, ms);
231
+ });
232
+ }
233
+ function throwIfAborted2(signal) {
234
+ if (signal?.aborted) {
235
+ const error = signal.reason;
236
+ throw error instanceof Error ? error : new Error("Object visibility wait was cancelled");
237
+ }
238
+ }
239
+
240
+ // src/bounded-object-write.ts
213
241
  var BoundedObjectWriteError = class extends Error {
214
242
  code;
215
243
  constructor(code) {
@@ -222,7 +250,7 @@ function createBoundedImmutableObjectWritePort(input) {
222
250
  return Object.freeze({
223
251
  async write(request) {
224
252
  validateWriteRequest(request);
225
- throwIfAborted2(request.signal);
253
+ throwIfAborted3(request.signal);
226
254
  let session;
227
255
  let committed = false;
228
256
  try {
@@ -235,7 +263,7 @@ function createBoundedImmutableObjectWritePort(input) {
235
263
  const digest = createHash("sha256");
236
264
  let byteSize = 0;
237
265
  for await (const sourceChunk of request.chunks) {
238
- throwIfAborted2(request.signal);
266
+ throwIfAborted3(request.signal);
239
267
  if (!(sourceChunk instanceof Uint8Array) || sourceChunk.byteLength === 0) {
240
268
  throw new BoundedObjectWriteError("truncated");
241
269
  }
@@ -250,7 +278,7 @@ function createBoundedImmutableObjectWritePort(input) {
250
278
  digest.update(chunk);
251
279
  await scrubWriteBackend(async () => session.write(chunk, request.signal));
252
280
  }
253
- throwIfAborted2(request.signal);
281
+ throwIfAborted3(request.signal);
254
282
  if (request.expectedByteSize !== void 0 && byteSize !== request.expectedByteSize) {
255
283
  throw new BoundedObjectWriteError("truncated");
256
284
  }
@@ -268,13 +296,26 @@ function createBoundedImmutableObjectWritePort(input) {
268
296
  );
269
297
  validateOpaqueReference(promoted.opaqueReference);
270
298
  committed = true;
271
- throwIfAborted2(request.signal);
272
- const reader = await input.readback.open({
273
- opaqueReference: promoted.opaqueReference,
274
- maxBytes: request.maxBytes,
275
- expectedByteSize: byteSize,
276
- ...request.signal ? { signal: request.signal } : {}
277
- });
299
+ throwIfAborted3(request.signal);
300
+ const reader = await retryWhileMissing(
301
+ async () => {
302
+ try {
303
+ return await input.readback.open({
304
+ opaqueReference: promoted.opaqueReference,
305
+ maxBytes: request.maxBytes,
306
+ expectedByteSize: byteSize,
307
+ ...request.signal ? { signal: request.signal } : {}
308
+ });
309
+ } catch (error) {
310
+ if (error instanceof BoundedObjectReadError && error.code === "object_missing") {
311
+ return null;
312
+ }
313
+ throw error;
314
+ }
315
+ },
316
+ request.signal ? { signal: request.signal } : {}
317
+ );
318
+ if (!reader) throw new BoundedObjectWriteError("readback_mismatch");
278
319
  try {
279
320
  if (reader.contentType !== void 0 && reader.contentType !== request.contentType) {
280
321
  throw new BoundedObjectWriteError("readback_mismatch");
@@ -295,7 +336,7 @@ function createBoundedImmutableObjectWritePort(input) {
295
336
  throw new BoundedObjectWriteError("readback_mismatch");
296
337
  }
297
338
  await reader.assertUnchanged(request.signal);
298
- throwIfAborted2(request.signal);
339
+ throwIfAborted3(request.signal);
299
340
  } finally {
300
341
  await reader.close();
301
342
  }
@@ -350,7 +391,7 @@ function mapWriteFailure(error, signal) {
350
391
  if (signal?.aborted) return new BoundedObjectWriteError("aborted");
351
392
  return new BoundedObjectWriteError("backend_failure");
352
393
  }
353
- function throwIfAborted2(signal) {
394
+ function throwIfAborted3(signal) {
354
395
  if (signal?.aborted) throw new BoundedObjectWriteError("aborted");
355
396
  }
356
397
  function writeErrorMessage(code) {
@@ -397,9 +438,9 @@ function versionedBackend(storage, hashForReferenceValue) {
397
438
  return Object.freeze({
398
439
  async describe(input) {
399
440
  const expectedHash = hashForReferenceValue(input.opaqueReference);
400
- throwIfAborted3(input.signal);
441
+ throwIfAborted4(input.signal);
401
442
  const head = await headObject(input.opaqueReference);
402
- throwIfAborted3(input.signal);
443
+ throwIfAborted4(input.signal);
403
444
  if (!head) return null;
404
445
  if (!Number.isSafeInteger(head.ContentLength) || head.ContentLength < 0 || typeof head.VersionToken !== "string" || head.VersionToken.length < 1 || head.VersionToken.length > 2048 || head.Metadata?.sha256 !== expectedHash) {
405
446
  throw new Error("Immutable object metadata is invalid");
@@ -413,14 +454,14 @@ function versionedBackend(storage, hashForReferenceValue) {
413
454
  },
414
455
  async readRange(input) {
415
456
  hashForReferenceValue(input.opaqueReference);
416
- throwIfAborted3(input.signal);
457
+ throwIfAborted4(input.signal);
417
458
  const result = await getObjectRange({
418
459
  key: input.opaqueReference,
419
460
  start: input.start,
420
461
  endInclusive: input.endInclusive,
421
462
  expectedVersionToken: input.expectedVersionToken
422
463
  });
423
- throwIfAborted3(input.signal);
464
+ throwIfAborted4(input.signal);
424
465
  if (!result) return null;
425
466
  return Object.freeze({
426
467
  bytes: result.bytes.slice(),
@@ -433,13 +474,13 @@ function immutableWriteBackend(storage, keyPrefix) {
433
474
  return Object.freeze({
434
475
  async begin(input) {
435
476
  validateContentType(input.contentType);
436
- throwIfAborted3(input.signal);
477
+ throwIfAborted4(input.signal);
437
478
  const stagingDirectory = await mkdtemp(join(tmpdir(), "opengeni-artifact-write-"));
438
479
  const stagingPath = join(stagingDirectory, "payload");
439
480
  let handle = null;
440
481
  try {
441
482
  await chmod(stagingDirectory, 448);
442
- throwIfAborted3(input.signal);
483
+ throwIfAborted4(input.signal);
443
484
  handle = await open(stagingPath, "wx", 384);
444
485
  } catch (error) {
445
486
  await rm(stagingDirectory, { recursive: true, force: true });
@@ -462,7 +503,7 @@ function immutableWriteBackend(storage, keyPrefix) {
462
503
  return {
463
504
  async write(chunk, signal) {
464
505
  if (closed) throw new Error("Immutable write session is closed");
465
- throwIfAborted3(signal);
506
+ throwIfAborted4(signal);
466
507
  if (!(chunk instanceof Uint8Array) || chunk.byteLength === 0) {
467
508
  throw new Error("Immutable write chunk is invalid");
468
509
  }
@@ -474,7 +515,7 @@ function immutableWriteBackend(storage, keyPrefix) {
474
515
  if (closed) throw new Error("Immutable write session is closed");
475
516
  closed = true;
476
517
  try {
477
- throwIfAborted3(commit.signal);
518
+ throwIfAborted4(commit.signal);
478
519
  if (commit.contentType !== input.contentType || commit.byteSize !== byteSize) {
479
520
  throw new Error("Immutable write commit metadata changed");
480
521
  }
@@ -490,7 +531,7 @@ function immutableWriteBackend(storage, keyPrefix) {
490
531
  if (existing) {
491
532
  assertStoredObject(existing, byteSize, contentHash, input.contentType);
492
533
  } else {
493
- await storage.putObjectStreamIfAbsent({
534
+ const created = await storage.putObjectStreamIfAbsent({
494
535
  key: opaqueReference,
495
536
  contentType: input.contentType,
496
537
  chunks: fileChunks(stagingPath, byteSize, commit.signal),
@@ -498,11 +539,16 @@ function immutableWriteBackend(storage, keyPrefix) {
498
539
  sha256: contentHash,
499
540
  ...commit.signal ? { signal: commit.signal } : {}
500
541
  });
501
- const stored = await storage.headObject(opaqueReference);
502
- if (!stored) throw new Error("Immutable object was not visible after write");
503
- assertStoredObject(stored, byteSize, contentHash, input.contentType);
542
+ if (!created) {
543
+ const stored = await retryWhileMissing(
544
+ async () => await storage.headObject(opaqueReference),
545
+ commit.signal ? { signal: commit.signal } : {}
546
+ );
547
+ if (!stored) throw new Error("Immutable content-addressed object is missing");
548
+ assertStoredObject(stored, byteSize, contentHash, input.contentType);
549
+ }
504
550
  }
505
- throwIfAborted3(commit.signal);
551
+ throwIfAborted4(commit.signal);
506
552
  return Object.freeze({ opaqueReference });
507
553
  } finally {
508
554
  await cleanup();
@@ -547,7 +593,7 @@ async function* fileChunks(path, expectedByteSize, signal) {
547
593
  const buffer = new Uint8Array(1024 * 1024);
548
594
  let offset = 0;
549
595
  while (offset < expectedByteSize) {
550
- throwIfAborted3(signal);
596
+ throwIfAborted4(signal);
551
597
  const length = Math.min(buffer.byteLength, expectedByteSize - offset);
552
598
  let filled = 0;
553
599
  while (filled < length) {
@@ -579,7 +625,7 @@ async function writeAll(handle, bytes, position) {
579
625
  offset += bytesWritten;
580
626
  }
581
627
  }
582
- function throwIfAborted3(signal) {
628
+ function throwIfAborted4(signal) {
583
629
  if (signal?.aborted) throw new Error("Object storage operation was cancelled");
584
630
  }
585
631
 
@@ -1381,11 +1427,13 @@ export {
1381
1427
  DOWNLOAD_URL_TTL_SECONDS,
1382
1428
  MAX_BOUNDED_OBJECT_CHUNK_BYTES,
1383
1429
  MAX_SINGLE_PUT_SIZE_BYTES,
1430
+ OBJECT_VISIBILITY_RETRY_DELAYS_MS,
1384
1431
  UPLOAD_URL_TTL_SECONDS,
1385
1432
  bytesToDataUrl,
1386
1433
  createBoundedImmutableObjectWritePort,
1387
1434
  createBoundedObjectReadPort,
1388
1435
  createObjectStorage,
1389
- createObjectStorageBoundedPorts
1436
+ createObjectStorageBoundedPorts,
1437
+ retryWhileMissing
1390
1438
  };
1391
1439
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/bounded-object-read.ts","../src/bounded-object-write.ts","../src/object-storage-bounded.ts"],"sourcesContent":["import type { Settings } from \"@opengeni/config\";\nimport { RETAINED_OUTPUT_MAX_PAGE_BYTES, type FileAsset } from \"@opengeni/contracts\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport {\n BlobSASPermissions,\n BlobServiceClient,\n generateBlobSASQueryParameters,\n StorageSharedKeyCredential,\n type BlobDownloadResponseParsed,\n type BlobGetPropertiesResponse,\n} from \"@azure/storage-blob\";\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n PutObjectCommand,\n S3Client,\n type S3ClientConfig,\n} from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport {\n Storage as GcsClient,\n type GetSignedUrlConfig,\n type StorageOptions,\n} from \"@google-cloud/storage\";\n\nexport * from \"./bounded-object-read\";\nexport * from \"./bounded-object-write\";\nexport * from \"./object-storage-bounded\";\n\nexport const MAX_SINGLE_PUT_SIZE_BYTES = 5_000_000_000;\nexport const UPLOAD_URL_TTL_SECONDS = 15 * 60;\nexport const DOWNLOAD_URL_TTL_SECONDS = 5 * 60;\nconst INTERNAL_STREAM_BUFFER_BYTES = 1024 * 1024;\nconst INTERNAL_STREAM_CONCURRENCY = 2;\n\nexport type ObjectHead = {\n ContentLength?: number;\n ContentType?: string;\n Metadata?: Record<string, string>;\n /** Opaque provider generation/etag used only for conditional internal reads. */\n VersionToken?: string;\n};\n\nexport type ObjectStorage = {\n bucket: string;\n backend: \"s3-compatible\" | \"aws-s3\" | \"azure-blob\" | \"gcs\";\n maxSinglePutSizeBytes: number;\n createPutUrl: (args: {\n key: string;\n contentType: string;\n sha256?: string | null;\n expiresInSeconds?: number;\n /** Select the network endpoint embedded in the signed URL. */\n audience?: \"public\" | \"sandbox\";\n }) => Promise<{ url: string; requiredHeaders: Record<string, string>; expiresAt: Date }>;\n createGetUrl: (args: {\n key: string;\n expiresInSeconds?: number;\n /** Select the network endpoint embedded in the signed URL. */\n audience?: \"public\" | \"sandbox\";\n }) => Promise<{ url: string; expiresAt: Date }>;\n headFile: (file: FileAsset) => Promise<ObjectHead>;\n /** Check provider existence without downloading object bytes. */\n fileExists: (file: FileAsset) => Promise<boolean>;\n getFileBytes: (file: FileAsset) => Promise<Uint8Array>;\n /**\n * Fetch exactly one inclusive byte range without materializing the complete\n * object. Returns null when the provider reports that the object is missing.\n */\n getFileRange: (\n file: FileAsset,\n range: { start: number; end: number },\n ) => Promise<Uint8Array | null>;\n /** Fetch an object by raw storage key (not a tracked FileAsset). Returns null on 404/missing. */\n getObjectBytes: (key: string) => Promise<{ bytes: Uint8Array; contentType?: string } | null>;\n /** Provider-versioned raw-key primitives used by bounded immutable adapters. */\n headObject?: (key: string) => Promise<ObjectHead | null>;\n getObjectRange?: (args: {\n key: string;\n start: number;\n endInclusive: number;\n expectedVersionToken: string;\n }) => Promise<{ bytes: Uint8Array; versionToken: string } | null>;\n /**\n * SERVER-SIDE authenticated direct PUT (no presign + browser fetch). For an\n * in-process upload from a trusted holder of the storage credentials (e.g. the\n * worker writing a recording), this sends the bytes straight to the storage\n * backend over the configured endpoint with the in-process SDK client — bypassing\n * the presigned-URL round-trip, which on split public/internal topologies (a\n * public `objectStorageEndpoint` with no in-cluster route) would otherwise 401.\n * Browser uploads keep using `createPutUrl`; this is the trusted-server twin.\n * Repeating a PUT for the same deterministic key and verified sha256 is\n * permitted: storage backends converge to the same bytes, while the database\n * completion fence remains the source of truth.\n */\n putObject: (args: {\n key: string;\n contentType: string;\n body: Uint8Array;\n sha256?: string | null;\n }) => Promise<void>;\n /** Atomic create-only raw PUT. Returns false when the key already exists. */\n putObjectIfAbsent?: (args: {\n key: string;\n contentType: string;\n body: Uint8Array;\n sha256: string;\n }) => Promise<boolean>;\n /**\n * Atomic create-only raw upload from a bounded asynchronous byte stream.\n * Providers may buffer a small fixed number of chunks, never the whole body.\n */\n putObjectStreamIfAbsent?: (args: {\n key: string;\n contentType: string;\n chunks: AsyncIterable<Uint8Array>;\n byteSize: number;\n sha256: string;\n signal?: AbortSignal;\n }) => Promise<boolean>;\n /**\n * SERVER-SIDE authenticated delete of a single object by raw storage key.\n * Idempotent: a missing key is a no-op (S3/GCS/Azure delete-by-key does not\n * 404 on absent objects, or the 404 is swallowed). Used by the Workbench v2\n * capture GC (keep the latest 10) to reap after-image blobs that no\n * surviving revision references. Best-effort at the call site — a failed\n * delete leaves an orphan blob, never corrupts a live capture.\n */\n deleteObject: (key: string) => Promise<void>;\n};\n\nexport function createObjectStorage(settings: Settings): ObjectStorage | null {\n if (settings.objectStorageBackend === \"azure-blob\") {\n return createAzureBlobObjectStorage(settings);\n }\n if (settings.objectStorageBackend === \"gcs\") {\n return createGcsObjectStorage(settings);\n }\n return createS3CompatibleObjectStorage(settings);\n}\n\nfunction createS3CompatibleObjectStorage(settings: Settings): ObjectStorage | null {\n if (\n settings.objectStorageBackend === \"s3-compatible\" &&\n (!settings.objectStorageEndpoint ||\n !settings.objectStorageAccessKeyId ||\n !settings.objectStorageSecretAccessKey)\n ) {\n return null;\n }\n const sharedClientConfig: S3ClientConfig = {\n region: settings.objectStorageRegion,\n forcePathStyle: settings.objectStorageForcePathStyle,\n requestChecksumCalculation: \"WHEN_REQUIRED\",\n ...(settings.objectStorageAccessKeyId && settings.objectStorageSecretAccessKey\n ? {\n credentials: {\n accessKeyId: settings.objectStorageAccessKeyId,\n secretAccessKey: settings.objectStorageSecretAccessKey,\n },\n }\n : {}),\n };\n const presignClient = new S3Client({\n ...sharedClientConfig,\n ...(settings.objectStorageEndpoint ? { endpoint: settings.objectStorageEndpoint } : {}),\n });\n const sandboxPresignClient = settings.objectStorageSandboxEndpoint\n ? new S3Client({\n ...sharedClientConfig,\n endpoint: settings.objectStorageSandboxEndpoint,\n })\n : presignClient;\n const requestClient = settings.objectStorageInternalEndpoint\n ? new S3Client({\n ...sharedClientConfig,\n endpoint: settings.objectStorageInternalEndpoint,\n })\n : presignClient;\n return {\n bucket: settings.objectStorageBucket,\n backend: settings.objectStorageBackend === \"aws-s3\" ? \"aws-s3\" : \"s3-compatible\",\n maxSinglePutSizeBytes: MAX_SINGLE_PUT_SIZE_BYTES,\n async createPutUrl(args) {\n const expiresIn = args.expiresInSeconds ?? UPLOAD_URL_TTL_SECONDS;\n const requiredHeaders: Record<string, string> = {\n \"content-type\": args.contentType,\n };\n const command = new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n Metadata: args.sha256 ? { sha256: args.sha256 } : undefined,\n });\n return {\n url: await getSignedUrl(\n args.audience === \"sandbox\" ? sandboxPresignClient : presignClient,\n command,\n {\n expiresIn,\n },\n ),\n requiredHeaders,\n expiresAt: new Date(Date.now() + expiresIn * 1000),\n };\n },\n async createGetUrl(args) {\n const expiresIn = args.expiresInSeconds ?? DOWNLOAD_URL_TTL_SECONDS;\n return {\n url: await getSignedUrl(\n args.audience === \"sandbox\" ? sandboxPresignClient : presignClient,\n new GetObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n }),\n { expiresIn },\n ),\n expiresAt: new Date(Date.now() + expiresIn * 1000),\n };\n },\n async putObject(args) {\n // Authenticated in-process PUT against the configured (in-cluster) endpoint.\n // A presigned URL buys nothing here — the worker already holds the creds — and\n // on a split public/internal endpoint topology the presigned URL points at the\n // PUBLIC host (no MinIO route → 401). This sends bytes straight to the backend.\n await requestClient.send(\n new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n Body: args.body,\n Metadata: args.sha256 ? { sha256: args.sha256 } : undefined,\n }),\n );\n },\n async putObjectIfAbsent(args) {\n try {\n await requestClient.send(\n new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n Body: args.body,\n Metadata: { sha256: args.sha256 },\n IfNoneMatch: \"*\",\n }),\n );\n return true;\n } catch (error) {\n if (isS3VersionMismatch(error)) return false;\n throw error;\n }\n },\n async putObjectStreamIfAbsent(args) {\n try {\n await requestClient.send(\n new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n ContentLength: args.byteSize,\n Body: Readable.from(args.chunks),\n Metadata: { sha256: args.sha256 },\n IfNoneMatch: \"*\",\n }),\n args.signal ? { abortSignal: args.signal } : undefined,\n );\n return true;\n } catch (error) {\n if (isS3VersionMismatch(error)) return false;\n throw error;\n }\n },\n async headFile(file) {\n const head = await requestClient.send(\n new HeadObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n }),\n );\n return objectHead({\n contentLength: head.ContentLength,\n contentType: head.ContentType,\n metadata: head.Metadata,\n });\n },\n async fileExists(file) {\n try {\n await requestClient.send(\n new HeadObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n }),\n );\n return true;\n } catch (error) {\n if (isS3NotFound(error)) return false;\n throw error;\n }\n },\n async getFileBytes(file) {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n }),\n );\n return await s3BodyToBytes(result.Body, file.objectKey);\n },\n async getFileRange(file, range) {\n const length = assertFileByteRange(file, range);\n try {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n Range: `bytes=${range.start}-${range.end}`,\n }),\n );\n return await s3BodyToBoundedBytes(result.Body, file.objectKey, length);\n } catch (error) {\n if (isS3NotFound(error)) return null;\n throw error;\n }\n },\n async headObject(key) {\n try {\n const head = await requestClient.send(\n new HeadObjectCommand({ Bucket: settings.objectStorageBucket, Key: key }),\n );\n return objectHead({\n contentLength: head.ContentLength,\n contentType: head.ContentType,\n metadata: head.Metadata,\n versionToken: head.ETag,\n });\n } catch (error) {\n if (isS3NotFound(error)) return null;\n throw error;\n }\n },\n async getObjectRange(args) {\n const length = assertRawObjectByteRange(args.key, args.start, args.endInclusive);\n try {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n Range: `bytes=${args.start}-${args.endInclusive}`,\n IfMatch: args.expectedVersionToken,\n }),\n );\n if (!result.ETag || result.ETag !== args.expectedVersionToken) return null;\n return {\n bytes: await s3BodyToBoundedBytes(result.Body, args.key, length),\n versionToken: result.ETag,\n };\n } catch (error) {\n if (isS3NotFound(error) || isS3VersionMismatch(error)) return null;\n throw error;\n }\n },\n async getObjectBytes(key) {\n try {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: key,\n }),\n );\n const bytes = await s3BodyToBytes(result.Body, key);\n return { bytes, ...(result.ContentType ? { contentType: result.ContentType } : {}) };\n } catch (error) {\n if (isS3NotFound(error)) {\n return null;\n }\n throw error;\n }\n },\n async deleteObject(key) {\n // S3 DeleteObject is idempotent — deleting an absent key returns 204.\n await requestClient.send(\n new DeleteObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: key,\n }),\n );\n },\n };\n}\n\nasync function s3BodyToBytes(body: unknown, objectKey: string): Promise<Uint8Array> {\n if (!body) {\n throw new Error(`Object body is empty: ${objectKey}`);\n }\n const withTransform = body as { transformToByteArray?: () => Promise<Uint8Array> };\n if (typeof withTransform.transformToByteArray === \"function\") {\n return await withTransform.transformToByteArray();\n }\n const chunks: Uint8Array[] = [];\n for await (const chunk of body as AsyncIterable<Uint8Array | Buffer | string>) {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n }\n return Buffer.concat(chunks);\n}\n\nasync function s3BodyToBoundedBytes(\n body: unknown,\n objectKey: string,\n expectedBytes: number,\n): Promise<Uint8Array> {\n if (!body) {\n throw new Error(`Object body is empty: ${objectKey}`);\n }\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n for await (const chunk of body as AsyncIterable<Uint8Array | Buffer | string>) {\n const normalized = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n bytes += normalized.byteLength;\n if (bytes > expectedBytes) {\n throw new Error(`Object range exceeded requested length: ${objectKey}`);\n }\n chunks.push(normalized);\n }\n if (bytes !== expectedBytes) {\n throw new Error(\n `Object range length mismatch for ${objectKey}: expected ${expectedBytes}, received ${bytes}`,\n );\n }\n return Buffer.concat(chunks, bytes);\n}\n\nfunction isS3NotFound(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const name = \"name\" in error ? (error as { name?: unknown }).name : undefined;\n if (name === \"NoSuchKey\" || name === \"NotFound\") {\n return true;\n }\n const metadata =\n \"$metadata\" in error\n ? (error as { $metadata?: { httpStatusCode?: number } }).$metadata\n : undefined;\n return metadata?.httpStatusCode === 404;\n}\n\nfunction isS3VersionMismatch(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const metadata =\n \"$metadata\" in error\n ? (error as { $metadata?: { httpStatusCode?: number } }).$metadata\n : undefined;\n return metadata?.httpStatusCode === 412;\n}\n\nfunction createGcsObjectStorage(settings: Settings): ObjectStorage {\n const client = new GcsClient(gcsClientOptions(settings));\n const bucket = client.bucket(settings.objectStorageBucket);\n return {\n bucket: settings.objectStorageBucket,\n backend: \"gcs\",\n maxSinglePutSizeBytes: MAX_SINGLE_PUT_SIZE_BYTES,\n async createPutUrl(args) {\n const expiresIn = args.expiresInSeconds ?? UPLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const config: GetSignedUrlConfig = {\n version: \"v4\",\n action: \"write\",\n expires: expiresAt,\n contentType: args.contentType,\n };\n if (args.sha256) {\n config.extensionHeaders = { \"x-goog-meta-sha256\": args.sha256 };\n }\n const [url] = await bucket.file(args.key).getSignedUrl(config);\n return {\n url,\n requiredHeaders: {\n \"content-type\": args.contentType,\n ...(args.sha256 ? { \"x-goog-meta-sha256\": args.sha256 } : {}),\n },\n expiresAt,\n };\n },\n async createGetUrl(args) {\n const expiresIn = args.expiresInSeconds ?? DOWNLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const [url] = await bucket.file(args.key).getSignedUrl({\n version: \"v4\",\n action: \"read\",\n expires: expiresAt,\n });\n return { url, expiresAt };\n },\n async putObject(args) {\n // Authenticated in-process PUT via the GCS SDK (the server holds the creds).\n await bucket.file(args.key).save(Buffer.from(args.body), {\n contentType: args.contentType,\n ...(args.sha256 ? { metadata: { metadata: { sha256: args.sha256 } } } : {}),\n });\n },\n async putObjectIfAbsent(args) {\n try {\n await bucket.file(args.key).save(Buffer.from(args.body), {\n contentType: args.contentType,\n metadata: { metadata: { sha256: args.sha256 } },\n preconditionOpts: { ifGenerationMatch: 0 },\n });\n return true;\n } catch (error) {\n if (isGcsVersionMismatch(error)) return false;\n throw error;\n }\n },\n async putObjectStreamIfAbsent(args) {\n const destination = bucket.file(args.key).createWriteStream({\n resumable: false,\n contentType: args.contentType,\n highWaterMark: INTERNAL_STREAM_BUFFER_BYTES,\n metadata: { metadata: { sha256: args.sha256 } },\n preconditionOpts: { ifGenerationMatch: 0 },\n });\n try {\n if (args.signal) {\n await pipeline(Readable.from(args.chunks), destination, { signal: args.signal });\n } else {\n await pipeline(Readable.from(args.chunks), destination);\n }\n return true;\n } catch (error) {\n if (isGcsVersionMismatch(error)) return false;\n throw error;\n }\n },\n async headFile(file) {\n const [metadata] = await bucket.file(file.objectKey).getMetadata();\n return objectHead({\n contentLength: parseContentLength(metadata.size),\n contentType: metadata.contentType,\n metadata: stringMetadata(metadata.metadata),\n });\n },\n async fileExists(file) {\n try {\n await bucket.file(file.objectKey).getMetadata();\n return true;\n } catch (error) {\n if (isGcsNotFound(error)) return false;\n throw error;\n }\n },\n async getFileBytes(file) {\n const [bytes] = await bucket.file(file.objectKey).download();\n return bytes;\n },\n async getFileRange(file, range) {\n const length = assertFileByteRange(file, range);\n try {\n const [bytes] = await bucket\n .file(file.objectKey)\n .download({ start: range.start, end: range.end });\n return exactRangeBytes(bytes, file.objectKey, length);\n } catch (error) {\n if (isGcsNotFound(error)) return null;\n throw error;\n }\n },\n async headObject(key) {\n try {\n const [metadata] = await bucket.file(key).getMetadata();\n return objectHead({\n contentLength: parseContentLength(metadata.size),\n contentType: metadata.contentType,\n metadata: stringMetadata(metadata.metadata),\n versionToken: metadata.generation === undefined ? undefined : String(metadata.generation),\n });\n } catch (error) {\n if (isGcsNotFound(error)) return null;\n throw error;\n }\n },\n async getObjectRange(args) {\n const length = assertRawObjectByteRange(args.key, args.start, args.endInclusive);\n try {\n const [bytes] = await bucket\n .file(args.key, { generation: args.expectedVersionToken })\n .download({ start: args.start, end: args.endInclusive });\n return {\n bytes: exactRangeBytes(bytes, args.key, length),\n versionToken: args.expectedVersionToken,\n };\n } catch (error) {\n if (isGcsNotFound(error) || isGcsVersionMismatch(error)) return null;\n throw error;\n }\n },\n async getObjectBytes(key) {\n try {\n const [bytes] = await bucket.file(key).download();\n return { bytes };\n } catch (error) {\n if (isGcsNotFound(error)) {\n return null;\n }\n throw error;\n }\n },\n async deleteObject(key) {\n // ignoreNotFound keeps the delete idempotent (a missing blob is a no-op).\n await bucket.file(key).delete({ ignoreNotFound: true });\n },\n };\n}\n\nfunction isGcsNotFound(error: unknown): boolean {\n return Boolean(error) && typeof error === \"object\" && (error as { code?: unknown }).code === 404;\n}\n\nfunction isGcsVersionMismatch(error: unknown): boolean {\n return Boolean(error) && typeof error === \"object\" && (error as { code?: unknown }).code === 412;\n}\n\nfunction createAzureBlobObjectStorage(settings: Settings): ObjectStorage | null {\n const sharedKey = azureSharedKeyCredential(settings);\n const requestServiceClient = settings.objectStorageAzureConnectionString\n ? BlobServiceClient.fromConnectionString(settings.objectStorageAzureConnectionString)\n : new BlobServiceClient(azureBlobServiceUrl(settings), sharedKey);\n const presignServiceClient = settings.objectStorageAzureEndpoint\n ? new BlobServiceClient(azureBlobServiceUrl(settings), sharedKey)\n : requestServiceClient;\n const requestContainerClient = requestServiceClient.getContainerClient(\n settings.objectStorageBucket,\n );\n const presignContainerClient = presignServiceClient.getContainerClient(\n settings.objectStorageBucket,\n );\n\n return {\n bucket: settings.objectStorageBucket,\n backend: \"azure-blob\",\n maxSinglePutSizeBytes: MAX_SINGLE_PUT_SIZE_BYTES,\n async createPutUrl(args) {\n const expiresIn = args.expiresInSeconds ?? UPLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const blobClient = presignContainerClient.getBlockBlobClient(args.key);\n const sas = generateBlobSASQueryParameters(\n {\n containerName: settings.objectStorageBucket,\n blobName: args.key,\n permissions: BlobSASPermissions.parse(\"cw\"),\n expiresOn: expiresAt,\n contentType: args.contentType,\n },\n sharedKey,\n ).toString();\n return {\n url: `${blobClient.url}?${sas}`,\n requiredHeaders: {\n \"content-type\": args.contentType,\n \"x-ms-blob-type\": \"BlockBlob\",\n ...(args.sha256 ? { \"x-ms-meta-sha256\": args.sha256 } : {}),\n },\n expiresAt,\n };\n },\n async createGetUrl(args) {\n const expiresIn = args.expiresInSeconds ?? DOWNLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const blobClient = presignContainerClient.getBlobClient(args.key);\n const sas = generateBlobSASQueryParameters(\n {\n containerName: settings.objectStorageBucket,\n blobName: args.key,\n permissions: BlobSASPermissions.parse(\"r\"),\n expiresOn: expiresAt,\n },\n sharedKey,\n ).toString();\n return {\n url: `${blobClient.url}?${sas}`,\n expiresAt,\n };\n },\n async putObject(args) {\n // Authenticated in-process upload via the shared-key Azure client (no SAS).\n const blobClient = requestContainerClient.getBlockBlobClient(args.key);\n const body = Buffer.from(args.body);\n await blobClient.upload(body, body.byteLength, {\n blobHTTPHeaders: { blobContentType: args.contentType },\n ...(args.sha256 ? { metadata: { sha256: args.sha256 } } : {}),\n });\n },\n async putObjectIfAbsent(args) {\n const blobClient = requestContainerClient.getBlockBlobClient(args.key);\n const body = Buffer.from(args.body);\n try {\n await blobClient.upload(body, body.byteLength, {\n blobHTTPHeaders: { blobContentType: args.contentType },\n metadata: { sha256: args.sha256 },\n conditions: { ifNoneMatch: \"*\" },\n });\n return true;\n } catch (error) {\n if (isAzureVersionMismatch(error)) return false;\n throw error;\n }\n },\n async putObjectStreamIfAbsent(args) {\n const blobClient = requestContainerClient.getBlockBlobClient(args.key);\n try {\n await blobClient.uploadStream(\n Readable.from(args.chunks),\n INTERNAL_STREAM_BUFFER_BYTES,\n INTERNAL_STREAM_CONCURRENCY,\n {\n blobHTTPHeaders: { blobContentType: args.contentType },\n metadata: { sha256: args.sha256 },\n conditions: { ifNoneMatch: \"*\" },\n ...(args.signal ? { abortSignal: args.signal } : {}),\n },\n );\n return true;\n } catch (error) {\n if (isAzureVersionMismatch(error)) return false;\n throw error;\n }\n },\n async headFile(file) {\n return azureHeadToObjectHead(\n await requestContainerClient.getBlobClient(file.objectKey).getProperties(),\n );\n },\n async fileExists(file) {\n try {\n await requestContainerClient.getBlobClient(file.objectKey).getProperties();\n return true;\n } catch (error) {\n if (isAzureNotFound(error)) return false;\n throw error;\n }\n },\n async getFileBytes(file) {\n return await azureDownloadToBytes(\n await requestContainerClient.getBlobClient(file.objectKey).download(),\n );\n },\n async getFileRange(file, range) {\n const length = assertFileByteRange(file, range);\n try {\n return await azureDownloadToBoundedBytes(\n await requestContainerClient.getBlobClient(file.objectKey).download(range.start, length),\n file.objectKey,\n length,\n );\n } catch (error) {\n if (isAzureNotFound(error)) return null;\n throw error;\n }\n },\n async headObject(key) {\n try {\n const properties = await requestContainerClient.getBlobClient(key).getProperties();\n return objectHead({\n contentLength: properties.contentLength,\n contentType: properties.contentType,\n metadata: properties.metadata,\n versionToken: properties.etag,\n });\n } catch (error) {\n if (isAzureNotFound(error)) return null;\n throw error;\n }\n },\n async getObjectRange(args) {\n const length = assertRawObjectByteRange(args.key, args.start, args.endInclusive);\n try {\n const download = await requestContainerClient\n .getBlobClient(args.key)\n .download(args.start, length, { conditions: { ifMatch: args.expectedVersionToken } });\n if (!download.etag || download.etag !== args.expectedVersionToken) return null;\n return {\n bytes: await azureDownloadToBoundedBytes(download, args.key, length),\n versionToken: download.etag,\n };\n } catch (error) {\n if (isAzureNotFound(error) || isAzureVersionMismatch(error)) return null;\n throw error;\n }\n },\n async getObjectBytes(key) {\n try {\n const download = await requestContainerClient.getBlobClient(key).download();\n const bytes = await azureDownloadToBytes(download);\n return { bytes, ...(download.contentType ? { contentType: download.contentType } : {}) };\n } catch (error) {\n if (isAzureNotFound(error)) {\n return null;\n }\n throw error;\n }\n },\n async deleteObject(key) {\n // deleteIfExists keeps the delete idempotent (a missing blob is a no-op).\n await requestContainerClient.getBlockBlobClient(key).deleteIfExists();\n },\n };\n}\n\nfunction isAzureNotFound(error: unknown): boolean {\n return (\n Boolean(error) &&\n typeof error === \"object\" &&\n (error as { statusCode?: unknown }).statusCode === 404\n );\n}\n\nfunction isAzureVersionMismatch(error: unknown): boolean {\n return (\n Boolean(error) &&\n typeof error === \"object\" &&\n (error as { statusCode?: unknown }).statusCode === 412\n );\n}\n\nfunction azureSharedKeyCredential(settings: Settings): StorageSharedKeyCredential {\n if (settings.objectStorageAzureConnectionString) {\n const parsed = parseConnectionString(settings.objectStorageAzureConnectionString);\n if (parsed.AccountName && parsed.AccountKey) {\n return new StorageSharedKeyCredential(parsed.AccountName, parsed.AccountKey);\n }\n throw new Error(\n \"Azure Blob connection string must include AccountName and AccountKey to create presigned URLs\",\n );\n }\n if (!settings.objectStorageAzureAccountName || !settings.objectStorageAzureAccountKey) {\n throw new Error(\"Azure Blob storage requires account name and account key\");\n }\n return new StorageSharedKeyCredential(\n settings.objectStorageAzureAccountName,\n settings.objectStorageAzureAccountKey,\n );\n}\n\nfunction azureBlobServiceUrl(settings: Settings): string {\n if (settings.objectStorageAzureEndpoint) {\n return settings.objectStorageAzureEndpoint.replace(/\\/+$/, \"\");\n }\n if (!settings.objectStorageAzureAccountName) {\n throw new Error(\"Azure Blob storage requires account name\");\n }\n return `https://${settings.objectStorageAzureAccountName}.blob.core.windows.net`;\n}\n\nfunction parseConnectionString(value: string): Record<string, string> {\n return Object.fromEntries(\n value\n .split(\";\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => {\n const index = part.indexOf(\"=\");\n return index === -1 ? [part, \"\"] : [part.slice(0, index), part.slice(index + 1)];\n }),\n );\n}\n\nfunction gcsClientOptions(settings: Settings): StorageOptions {\n const options: StorageOptions = {\n ...(settings.objectStorageGcsProjectId\n ? { projectId: settings.objectStorageGcsProjectId }\n : {}),\n ...(settings.objectStorageGcsKeyFilename\n ? { keyFilename: settings.objectStorageGcsKeyFilename }\n : {}),\n ...(settings.objectStorageGcsApiEndpoint\n ? { apiEndpoint: settings.objectStorageGcsApiEndpoint }\n : {}),\n };\n if (settings.objectStorageGcsCredentialsJson) {\n options.credentials = parseGcsCredentials(settings.objectStorageGcsCredentialsJson);\n }\n return options;\n}\n\nfunction parseGcsCredentials(raw: string): Record<string, string> {\n const parsed = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"GCS credentials JSON must be an object\");\n }\n return parsed as Record<string, string>;\n}\n\nfunction parseContentLength(value: string | number | undefined): number | undefined {\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value !== \"string\" || value.length === 0) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction stringMetadata(\n value: Record<string, string | number | boolean | null> | undefined,\n): Record<string, string> | undefined {\n if (!value) {\n return undefined;\n }\n return Object.fromEntries(\n Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n ),\n );\n}\n\nfunction azureHeadToObjectHead(head: BlobGetPropertiesResponse): ObjectHead {\n return objectHead({\n contentLength: head.contentLength,\n contentType: head.contentType,\n metadata: head.metadata,\n });\n}\n\nasync function azureDownloadToBytes(download: BlobDownloadResponseParsed): Promise<Uint8Array> {\n if (!download.readableStreamBody) {\n throw new Error(\"Azure Blob download response did not include a readable body\");\n }\n const chunks: Uint8Array[] = [];\n for await (const chunk of download.readableStreamBody as AsyncIterable<\n Uint8Array | Buffer | string\n >) {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n }\n return Buffer.concat(chunks);\n}\n\nasync function azureDownloadToBoundedBytes(\n download: BlobDownloadResponseParsed,\n objectKey: string,\n expectedBytes: number,\n): Promise<Uint8Array> {\n if (!download.readableStreamBody) {\n throw new Error(\"Azure Blob download response did not include a readable body\");\n }\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n for await (const chunk of download.readableStreamBody as AsyncIterable<\n Uint8Array | Buffer | string\n >) {\n const normalized = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n bytes += normalized.byteLength;\n if (bytes > expectedBytes) {\n throw new Error(`Object range exceeded requested length: ${objectKey}`);\n }\n chunks.push(normalized);\n }\n if (bytes !== expectedBytes) {\n throw new Error(\n `Object range length mismatch for ${objectKey}: expected ${expectedBytes}, received ${bytes}`,\n );\n }\n return Buffer.concat(chunks, bytes);\n}\n\nfunction assertFileByteRange(\n file: Pick<FileAsset, \"sizeBytes\" | \"objectKey\">,\n range: { start: number; end: number },\n): number {\n if (\n !Number.isSafeInteger(range.start) ||\n !Number.isSafeInteger(range.end) ||\n range.start < 0 ||\n range.end < range.start ||\n range.end >= file.sizeBytes\n ) {\n throw new RangeError(`Invalid object byte range for ${file.objectKey}`);\n }\n const length = range.end - range.start + 1;\n if (length > RETAINED_OUTPUT_MAX_PAGE_BYTES) {\n throw new RangeError(\n `Object byte range exceeds ${RETAINED_OUTPUT_MAX_PAGE_BYTES} bytes for ${file.objectKey}`,\n );\n }\n return length;\n}\n\nfunction assertRawObjectByteRange(key: string, start: number, endInclusive: number): number {\n if (\n typeof key !== \"string\" ||\n key.length < 1 ||\n key.length > 2048 ||\n !Number.isSafeInteger(start) ||\n !Number.isSafeInteger(endInclusive) ||\n start < 0 ||\n endInclusive < start\n ) {\n throw new RangeError(\"Invalid raw object byte range\");\n }\n const length = endInclusive - start + 1;\n if (length > RETAINED_OUTPUT_MAX_PAGE_BYTES) {\n throw new RangeError(\"Raw object byte range exceeds the bounded page limit\");\n }\n return length;\n}\n\nfunction exactRangeBytes(bytes: Uint8Array, objectKey: string, expectedBytes: number): Uint8Array {\n if (bytes.byteLength !== expectedBytes) {\n throw new Error(\n `Object range length mismatch for ${objectKey}: expected ${expectedBytes}, received ${bytes.byteLength}`,\n );\n }\n return bytes;\n}\n\nfunction objectHead(input: {\n contentLength?: number | undefined;\n contentType?: string | undefined;\n metadata?: Record<string, string> | undefined;\n versionToken?: string | undefined;\n}): ObjectHead {\n return {\n ...(input.contentLength !== undefined ? { ContentLength: input.contentLength } : {}),\n ...(input.contentType !== undefined ? { ContentType: input.contentType } : {}),\n ...(input.metadata !== undefined ? { Metadata: input.metadata } : {}),\n ...(input.versionToken !== undefined ? { VersionToken: input.versionToken } : {}),\n };\n}\n\nexport function bytesToDataUrl(bytes: Uint8Array, contentType: string): string {\n return `data:${contentType};base64,${Buffer.from(bytes).toString(\"base64\")}`;\n}\n","/**\n * Version-pinned, bounded object reads for large trusted-server workloads.\n *\n * This surface deliberately deals in opaque references. Provider keys, bucket\n * names, signed URLs, and provider diagnostics stay behind the backend\n * callback and are never included in returned values or public errors.\n */\n\nexport const DEFAULT_BOUNDED_OBJECT_CHUNK_BYTES = 1024 * 1024;\nexport const MAX_BOUNDED_OBJECT_CHUNK_BYTES = 8 * 1024 * 1024;\n\nexport type BoundedObjectReadErrorCode =\n | \"aborted\"\n | \"backend_failure\"\n | \"invalid_request\"\n | \"object_changed\"\n | \"object_missing\"\n | \"size_limit\"\n | \"truncated\";\n\nexport class BoundedObjectReadError extends Error {\n readonly code: BoundedObjectReadErrorCode;\n\n constructor(code: BoundedObjectReadErrorCode) {\n super(messageForCode(code));\n this.name = \"BoundedObjectReadError\";\n this.code = code;\n }\n}\n\nexport type VersionedObjectDescription = Readonly<{\n byteSize: number;\n /** Opaque provider generation/etag token. It never crosses this package. */\n versionToken: string;\n /**\n * Explicit adapter assertion that the opaque reference resolves forever to\n * this provider generation (for example a version id or immutable\n * content-addressed object). Mutable raw keys must never set this flag.\n */\n immutableReference: true;\n contentType?: string;\n}>;\n\nexport type VersionedObjectRange = Readonly<{\n bytes: Uint8Array;\n versionToken: string;\n}>;\n\n/**\n * Provider adapter used by the range reader. Implementations should use a\n * provider-native generation/version/If-Match condition whenever available.\n * Returning a different version is treated as replacement, never as data.\n */\nexport interface VersionedRangeObjectBackend {\n describe(input: {\n opaqueReference: string;\n signal?: AbortSignal;\n }): Promise<VersionedObjectDescription | null>;\n readRange(input: {\n opaqueReference: string;\n start: number;\n endInclusive: number;\n expectedVersionToken: string;\n signal?: AbortSignal;\n }): Promise<VersionedObjectRange | null>;\n close?(input: { opaqueReference: string }): void | Promise<void>;\n}\n\nexport interface BoundedObjectRead {\n readonly byteSize: number;\n readonly contentType: string | undefined;\n /** A read handle is intentionally single-use. */\n chunks(input?: { chunkBytes?: number; signal?: AbortSignal }): AsyncIterable<Uint8Array>;\n /** Revalidate the immutable provider generation after all consumers finish. */\n assertUnchanged(signal?: AbortSignal): Promise<void>;\n close(): Promise<void>;\n}\n\nexport interface BoundedObjectReadPort {\n open(input: {\n opaqueReference: string;\n maxBytes: number;\n expectedByteSize?: number;\n signal?: AbortSignal;\n }): Promise<BoundedObjectRead>;\n}\n\n/**\n * Adds uniform limits, exact-range checks, replacement fencing, cancellation,\n * and diagnostic scrubbing around a provider-specific range backend.\n */\nexport function createBoundedObjectReadPort(\n backend: VersionedRangeObjectBackend,\n): BoundedObjectReadPort {\n return Object.freeze({\n async open(input: {\n opaqueReference: string;\n maxBytes: number;\n expectedByteSize?: number;\n signal?: AbortSignal;\n }): Promise<BoundedObjectRead> {\n validateReference(input.opaqueReference);\n assertPositiveSafeInteger(input.maxBytes);\n if (input.expectedByteSize !== undefined) {\n assertNonnegativeSafeInteger(input.expectedByteSize);\n }\n throwIfAborted(input.signal);\n const description = await scrubBackendFailure(async () =>\n backend.describe({\n opaqueReference: input.opaqueReference,\n ...(input.signal ? { signal: input.signal } : {}),\n }),\n );\n // Provider adapters are allowed to receive AbortSignal, but correctness\n // cannot depend on every SDK honouring it while an I/O promise is active.\n throwIfAborted(input.signal);\n if (!description) throw new BoundedObjectReadError(\"object_missing\");\n validateDescription(description);\n if (description.byteSize > input.maxBytes) {\n throw new BoundedObjectReadError(\"size_limit\");\n }\n if (input.expectedByteSize !== undefined && description.byteSize !== input.expectedByteSize) {\n throw new BoundedObjectReadError(\"truncated\");\n }\n return new VersionPinnedBoundedObjectRead(backend, input.opaqueReference, description);\n },\n });\n}\n\nclass VersionPinnedBoundedObjectRead implements BoundedObjectRead {\n readonly byteSize: number;\n readonly contentType: string | undefined;\n readonly #backend: VersionedRangeObjectBackend;\n readonly #opaqueReference: string;\n readonly #versionToken: string;\n #claimed = false;\n #closed = false;\n\n constructor(\n backend: VersionedRangeObjectBackend,\n opaqueReference: string,\n description: VersionedObjectDescription,\n ) {\n this.#backend = backend;\n this.#opaqueReference = opaqueReference;\n this.#versionToken = description.versionToken;\n this.byteSize = description.byteSize;\n this.contentType = description.contentType;\n }\n\n chunks(\n input: {\n chunkBytes?: number;\n signal?: AbortSignal;\n } = {},\n ): AsyncIterable<Uint8Array> {\n if (this.#closed || this.#claimed) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n const chunkBytes = input.chunkBytes ?? DEFAULT_BOUNDED_OBJECT_CHUNK_BYTES;\n assertPositiveSafeInteger(chunkBytes);\n if (chunkBytes > MAX_BOUNDED_OBJECT_CHUNK_BYTES) {\n throw new BoundedObjectReadError(\"size_limit\");\n }\n this.#claimed = true;\n return this.#streamChunks(chunkBytes, input.signal);\n }\n\n async *#streamChunks(\n chunkBytes: number,\n signal: AbortSignal | undefined,\n ): AsyncIterableIterator<Uint8Array> {\n let offset = 0;\n let completed = false;\n try {\n while (offset < this.byteSize) {\n throwIfAborted(signal);\n if (this.#closed) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n const endInclusive = Math.min(this.byteSize - 1, offset + chunkBytes - 1);\n const range = await scrubBackendFailure(async () =>\n this.#backend.readRange({\n opaqueReference: this.#opaqueReference,\n start: offset,\n endInclusive,\n expectedVersionToken: this.#versionToken,\n ...(signal ? { signal } : {}),\n }),\n );\n throwIfAborted(signal);\n if (!range) {\n throw new BoundedObjectReadError(\"object_changed\");\n }\n if (range.versionToken !== this.#versionToken) {\n throw new BoundedObjectReadError(\"object_changed\");\n }\n const expectedLength = endInclusive - offset + 1;\n if (range.bytes.byteLength !== expectedLength) {\n throw new BoundedObjectReadError(\"truncated\");\n }\n offset += range.bytes.byteLength;\n // Detach consumers from mutable provider buffers.\n yield range.bytes.slice();\n }\n throwIfAborted(signal);\n completed = true;\n } finally {\n // Keep a successfully consumed handle live for the mandatory final\n // generation check. Early return, failure, and cancellation clean up\n // immediately; normal callers close after assertUnchanged().\n if (!completed) await this.close();\n }\n }\n\n async assertUnchanged(signal?: AbortSignal): Promise<void> {\n if (this.#closed) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n throwIfAborted(signal);\n const current = await scrubBackendFailure(async () =>\n this.#backend.describe({\n opaqueReference: this.#opaqueReference,\n ...(signal ? { signal } : {}),\n }),\n );\n throwIfAborted(signal);\n if (\n !current ||\n current.versionToken !== this.#versionToken ||\n current.byteSize !== this.byteSize\n ) {\n throw new BoundedObjectReadError(\"object_changed\");\n }\n }\n\n async close(): Promise<void> {\n if (this.#closed) return;\n this.#closed = true;\n if (!this.#backend.close) return;\n try {\n await this.#backend.close({ opaqueReference: this.#opaqueReference });\n } catch {\n // Cleanup is best-effort and must not replace the verification result.\n }\n }\n}\n\nasync function scrubBackendFailure<T>(operation: () => Promise<T>): Promise<T> {\n try {\n return await operation();\n } catch (error) {\n if (error instanceof BoundedObjectReadError) throw error;\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n}\n\nfunction validateReference(value: string): void {\n if (\n typeof value !== \"string\" ||\n value.length < 1 ||\n value.length > 2048 ||\n value.trim() !== value ||\n /[\\u0000-\\u001f\\u007f]/.test(value)\n ) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n}\n\nfunction validateDescription(value: VersionedObjectDescription): void {\n assertNonnegativeSafeInteger(value.byteSize);\n if (value.immutableReference !== true) {\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n if (\n typeof value.versionToken !== \"string\" ||\n value.versionToken.length < 1 ||\n value.versionToken.length > 2048\n ) {\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n if (\n value.contentType !== undefined &&\n (value.contentType.length < 1 || value.contentType.length > 256)\n ) {\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n}\n\nfunction assertPositiveSafeInteger(value: number): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n}\n\nfunction assertNonnegativeSafeInteger(value: number): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new BoundedObjectReadError(\"aborted\");\n}\n\nfunction messageForCode(code: BoundedObjectReadErrorCode): string {\n switch (code) {\n case \"aborted\":\n return \"Bounded object read was cancelled\";\n case \"backend_failure\":\n return \"Bounded object read failed\";\n case \"invalid_request\":\n return \"Bounded object read request is invalid\";\n case \"object_changed\":\n return \"Bounded object changed during verification\";\n case \"object_missing\":\n return \"Bounded object is unavailable\";\n case \"size_limit\":\n return \"Bounded object exceeds the configured limit\";\n case \"truncated\":\n return \"Bounded object length does not match its immutable metadata\";\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { MAX_BOUNDED_OBJECT_CHUNK_BYTES, type BoundedObjectReadPort } from \"./bounded-object-read\";\n\nexport type BoundedObjectWriteErrorCode =\n | \"aborted\"\n | \"backend_failure\"\n | \"content_hash_mismatch\"\n | \"invalid_request\"\n | \"readback_mismatch\"\n | \"size_limit\"\n | \"truncated\";\n\nexport class BoundedObjectWriteError extends Error {\n readonly code: BoundedObjectWriteErrorCode;\n\n constructor(code: BoundedObjectWriteErrorCode) {\n super(writeErrorMessage(code));\n this.name = \"BoundedObjectWriteError\";\n this.code = code;\n }\n}\n\nexport interface ImmutableContentAddressedWriteSession {\n write(chunk: Uint8Array, signal?: AbortSignal): Promise<void>;\n /**\n * Atomically promotes staged bytes to an immutable content-addressed object.\n * The returned reference must resolve forever to this exact generation.\n */\n commit(input: {\n byteSize: number;\n contentHash: string;\n contentType: string;\n signal?: AbortSignal;\n }): Promise<{ opaqueReference: string }>;\n abort(): void | Promise<void>;\n}\n\nexport interface ImmutableContentAddressedWriteBackend {\n begin(input: {\n contentType: string;\n signal?: AbortSignal;\n }): Promise<ImmutableContentAddressedWriteSession>;\n}\n\nexport type BoundedImmutableObjectWriteResult = Readonly<{\n opaqueReference: string;\n byteSize: number;\n contentHash: string;\n contentType: string;\n}>;\n\nexport interface BoundedImmutableObjectWritePort {\n write(input: {\n chunks: AsyncIterable<Uint8Array>;\n contentType: string;\n maxBytes: number;\n expectedByteSize?: number;\n expectedContentHash?: string;\n signal?: AbortSignal;\n }): Promise<BoundedImmutableObjectWriteResult>;\n}\n\n/**\n * Streams to provider staging, atomically promotes by digest, then streams the\n * immutable object back and hashes it independently before returning its\n * opaque reference. Neither direction accumulates the complete object.\n */\nexport function createBoundedImmutableObjectWritePort(input: {\n backend: ImmutableContentAddressedWriteBackend;\n readback: BoundedObjectReadPort;\n}): BoundedImmutableObjectWritePort {\n return Object.freeze({\n async write(request: {\n chunks: AsyncIterable<Uint8Array>;\n contentType: string;\n maxBytes: number;\n expectedByteSize?: number;\n expectedContentHash?: string;\n signal?: AbortSignal;\n }): Promise<BoundedImmutableObjectWriteResult> {\n validateWriteRequest(request);\n throwIfAborted(request.signal);\n let session: ImmutableContentAddressedWriteSession | undefined;\n let committed = false;\n try {\n session = await scrubWriteBackend(async () =>\n input.backend.begin({\n contentType: request.contentType,\n ...(request.signal ? { signal: request.signal } : {}),\n }),\n );\n const digest = createHash(\"sha256\");\n let byteSize = 0;\n for await (const sourceChunk of request.chunks) {\n throwIfAborted(request.signal);\n if (!(sourceChunk instanceof Uint8Array) || sourceChunk.byteLength === 0) {\n throw new BoundedObjectWriteError(\"truncated\");\n }\n if (sourceChunk.byteLength > MAX_BOUNDED_OBJECT_CHUNK_BYTES) {\n throw new BoundedObjectWriteError(\"size_limit\");\n }\n byteSize += sourceChunk.byteLength;\n if (byteSize > request.maxBytes) {\n throw new BoundedObjectWriteError(\"size_limit\");\n }\n const chunk = sourceChunk.slice();\n digest.update(chunk);\n await scrubWriteBackend(async () => session!.write(chunk, request.signal));\n }\n // A backend may ignore AbortSignal and resolve the final write after the\n // caller has cancelled. Recheck before publishing staged bytes; without\n // this fence a one-chunk upload could still be committed after abort.\n throwIfAborted(request.signal);\n if (request.expectedByteSize !== undefined && byteSize !== request.expectedByteSize) {\n throw new BoundedObjectWriteError(\"truncated\");\n }\n const contentHash = `sha256:${digest.digest(\"hex\")}`;\n if (\n request.expectedContentHash !== undefined &&\n contentHash !== request.expectedContentHash\n ) {\n throw new BoundedObjectWriteError(\"content_hash_mismatch\");\n }\n const promoted = await scrubWriteBackend(async () =>\n session!.commit({\n byteSize,\n contentHash,\n contentType: request.contentType,\n ...(request.signal ? { signal: request.signal } : {}),\n }),\n );\n validateOpaqueReference(promoted.opaqueReference);\n committed = true;\n // A provider may finish promotion after cancellation despite receiving\n // the signal. The immutable object can be swept, but it must never be\n // returned to a caller as a successful publication candidate.\n throwIfAborted(request.signal);\n\n const reader = await input.readback.open({\n opaqueReference: promoted.opaqueReference,\n maxBytes: request.maxBytes,\n expectedByteSize: byteSize,\n ...(request.signal ? { signal: request.signal } : {}),\n });\n try {\n if (reader.contentType !== undefined && reader.contentType !== request.contentType) {\n throw new BoundedObjectWriteError(\"readback_mismatch\");\n }\n const readbackHash = createHash(\"sha256\");\n let readbackBytes = 0;\n for await (const chunk of reader.chunks({\n ...(request.signal ? { signal: request.signal } : {}),\n })) {\n readbackBytes += chunk.byteLength;\n if (readbackBytes > byteSize) {\n throw new BoundedObjectWriteError(\"readback_mismatch\");\n }\n readbackHash.update(chunk);\n }\n const readbackContentHash = `sha256:${readbackHash.digest(\"hex\")}`;\n if (readbackBytes !== byteSize || readbackContentHash !== contentHash) {\n throw new BoundedObjectWriteError(\"readback_mismatch\");\n }\n await reader.assertUnchanged(request.signal);\n throwIfAborted(request.signal);\n } finally {\n await reader.close();\n }\n return Object.freeze({\n opaqueReference: promoted.opaqueReference,\n byteSize,\n contentHash,\n contentType: request.contentType,\n });\n } catch (error) {\n throw mapWriteFailure(error, request.signal);\n } finally {\n if (session && !committed) {\n try {\n await session.abort();\n } catch {\n // Best-effort staging cleanup; a sweeper remains the final guard.\n }\n }\n }\n },\n });\n}\n\nfunction validateWriteRequest(input: {\n contentType: string;\n maxBytes: number;\n expectedByteSize?: number;\n expectedContentHash?: string;\n}): void {\n if (!Number.isSafeInteger(input.maxBytes) || input.maxBytes <= 0) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n if (\n input.expectedByteSize !== undefined &&\n (!Number.isSafeInteger(input.expectedByteSize) || input.expectedByteSize < 0)\n ) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n if (\n typeof input.contentType !== \"string\" ||\n input.contentType.length < 1 ||\n input.contentType.length > 256 ||\n /[\\u0000-\\u001f\\u007f]/.test(input.contentType)\n ) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n if (\n input.expectedContentHash !== undefined &&\n !/^sha256:[0-9a-f]{64}$/.test(input.expectedContentHash)\n ) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n}\n\nfunction validateOpaqueReference(value: string): void {\n if (\n typeof value !== \"string\" ||\n value.length < 1 ||\n value.length > 2048 ||\n value.trim() !== value ||\n /[\\u0000-\\u001f\\u007f]/.test(value)\n ) {\n throw new BoundedObjectWriteError(\"backend_failure\");\n }\n}\n\nasync function scrubWriteBackend<T>(operation: () => Promise<T>): Promise<T> {\n try {\n return await operation();\n } catch (error) {\n if (error instanceof BoundedObjectWriteError) throw error;\n throw new BoundedObjectWriteError(\"backend_failure\");\n }\n}\n\nfunction mapWriteFailure(error: unknown, signal: AbortSignal | undefined): BoundedObjectWriteError {\n if (error instanceof BoundedObjectWriteError) return error;\n if (signal?.aborted) return new BoundedObjectWriteError(\"aborted\");\n return new BoundedObjectWriteError(\"backend_failure\");\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new BoundedObjectWriteError(\"aborted\");\n}\n\nfunction writeErrorMessage(code: BoundedObjectWriteErrorCode): string {\n switch (code) {\n case \"aborted\":\n return \"Bounded object write was cancelled\";\n case \"backend_failure\":\n return \"Bounded object write failed\";\n case \"content_hash_mismatch\":\n return \"Bounded object digest does not match expected canonical bytes\";\n case \"invalid_request\":\n return \"Bounded object write request is invalid\";\n case \"readback_mismatch\":\n return \"Immutable object read-back verification failed\";\n case \"size_limit\":\n return \"Bounded object write exceeds the configured limit\";\n case \"truncated\":\n return \"Bounded object write length does not match expected canonical bytes\";\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { chmod, mkdtemp, open, rm, type FileHandle } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport {\n createBoundedObjectReadPort,\n type BoundedObjectReadPort,\n type VersionedRangeObjectBackend,\n} from \"./bounded-object-read\";\nimport {\n createBoundedImmutableObjectWritePort,\n type BoundedImmutableObjectWritePort,\n type ImmutableContentAddressedWriteBackend,\n type ImmutableContentAddressedWriteSession,\n} from \"./bounded-object-write\";\nimport type { ObjectStorage } from \"./index\";\n\nconst SNAPSHOT_KEY_PREFIX = \"editable-artifacts/snapshots/sha256/\";\n\nexport type ObjectStorageBoundedPorts = Readonly<{\n read: BoundedObjectReadPort;\n write: BoundedImmutableObjectWritePort;\n}>;\n\nexport type ObjectStorageBoundedPortsOptions = Readonly<{\n /** Static trusted namespace ending in `/sha256/`. */\n keyPrefix?: string;\n}>;\n\n/**\n * Bounded immutable snapshot ports over the standalone object-storage driver.\n * Reads are provider-version pinned. Writes use a canonical digest key and are\n * independently range-read and hashed by the shared verification layer.\n *\n * Provider uploads and readback are streaming. Staging uses one private local\n * file so content-addressed naming never requires retaining the object in RAM.\n * There is no whole-object fallback when a provider lacks these primitives.\n */\nexport function createObjectStorageBoundedPorts(\n storage: ObjectStorage,\n options: ObjectStorageBoundedPortsOptions = {},\n): ObjectStorageBoundedPorts {\n if (!storage.headObject || !storage.getObjectRange || !storage.putObjectStreamIfAbsent) {\n throw new Error(\"Object storage lacks streaming immutable create/versioned range primitives\");\n }\n const keyPrefix = validateKeyPrefix(options.keyPrefix ?? SNAPSHOT_KEY_PREFIX);\n const referenceHash = (reference: string) => hashForReference(reference, keyPrefix);\n const read = createBoundedObjectReadPort(versionedBackend(storage, referenceHash));\n const write = createBoundedImmutableObjectWritePort({\n backend: immutableWriteBackend(storage, keyPrefix),\n readback: read,\n });\n return Object.freeze({ read, write });\n}\n\nfunction versionedBackend(\n storage: ObjectStorage,\n hashForReferenceValue: (reference: string) => string,\n): VersionedRangeObjectBackend {\n const headObject = storage.headObject!;\n const getObjectRange = storage.getObjectRange!;\n return Object.freeze({\n async describe(input: Parameters<VersionedRangeObjectBackend[\"describe\"]>[0]) {\n const expectedHash = hashForReferenceValue(input.opaqueReference);\n throwIfAborted(input.signal);\n const head = await headObject(input.opaqueReference);\n throwIfAborted(input.signal);\n if (!head) return null;\n if (\n !Number.isSafeInteger(head.ContentLength) ||\n head.ContentLength! < 0 ||\n typeof head.VersionToken !== \"string\" ||\n head.VersionToken.length < 1 ||\n head.VersionToken.length > 2048 ||\n head.Metadata?.sha256 !== expectedHash\n ) {\n throw new Error(\"Immutable object metadata is invalid\");\n }\n return Object.freeze({\n byteSize: head.ContentLength!,\n versionToken: head.VersionToken,\n immutableReference: true as const,\n ...(head.ContentType ? { contentType: head.ContentType } : {}),\n });\n },\n async readRange(input: Parameters<VersionedRangeObjectBackend[\"readRange\"]>[0]) {\n hashForReferenceValue(input.opaqueReference);\n throwIfAborted(input.signal);\n const result = await getObjectRange({\n key: input.opaqueReference,\n start: input.start,\n endInclusive: input.endInclusive,\n expectedVersionToken: input.expectedVersionToken,\n });\n throwIfAborted(input.signal);\n if (!result) return null;\n return Object.freeze({\n bytes: result.bytes.slice(),\n versionToken: result.versionToken,\n });\n },\n });\n}\n\nfunction immutableWriteBackend(\n storage: ObjectStorage,\n keyPrefix: string,\n): ImmutableContentAddressedWriteBackend {\n return Object.freeze({\n async begin(\n input: Parameters<ImmutableContentAddressedWriteBackend[\"begin\"]>[0],\n ): Promise<ImmutableContentAddressedWriteSession> {\n validateContentType(input.contentType);\n throwIfAborted(input.signal);\n const stagingDirectory = await mkdtemp(join(tmpdir(), \"opengeni-artifact-write-\"));\n const stagingPath = join(stagingDirectory, \"payload\");\n let handle: FileHandle | null = null;\n try {\n await chmod(stagingDirectory, 0o700);\n throwIfAborted(input.signal);\n handle = await open(stagingPath, \"wx\", 0o600);\n } catch (error) {\n await rm(stagingDirectory, { recursive: true, force: true });\n throw error;\n }\n let byteSize = 0;\n let closed = false;\n let cleaned = false;\n const digest = createHash(\"sha256\");\n const cleanup = async () => {\n if (cleaned) return;\n cleaned = true;\n if (handle) {\n const closing = handle;\n handle = null;\n await closing.close().catch(() => undefined);\n }\n await rm(stagingDirectory, { recursive: true, force: true });\n };\n return {\n async write(chunk: Uint8Array, signal?: AbortSignal) {\n if (closed) throw new Error(\"Immutable write session is closed\");\n throwIfAborted(signal);\n if (!(chunk instanceof Uint8Array) || chunk.byteLength === 0) {\n throw new Error(\"Immutable write chunk is invalid\");\n }\n await writeAll(handle!, chunk, byteSize);\n digest.update(chunk);\n byteSize += chunk.byteLength;\n },\n async commit(commit: Parameters<ImmutableContentAddressedWriteSession[\"commit\"]>[0]) {\n if (closed) throw new Error(\"Immutable write session is closed\");\n closed = true;\n try {\n throwIfAborted(commit.signal);\n if (commit.contentType !== input.contentType || commit.byteSize !== byteSize) {\n throw new Error(\"Immutable write commit metadata changed\");\n }\n const contentHash = `sha256:${digest.digest(\"hex\")}`;\n if (contentHash !== commit.contentHash) {\n throw new Error(\"Immutable write digest changed\");\n }\n const opaqueReference = `${keyPrefix}${contentHash.slice(\"sha256:\".length)}`;\n const closing = handle!;\n handle = null;\n await closing.close();\n const existing = await storage.headObject!(opaqueReference);\n if (existing) {\n assertStoredObject(existing, byteSize, contentHash, input.contentType);\n } else {\n await storage.putObjectStreamIfAbsent!({\n key: opaqueReference,\n contentType: input.contentType,\n chunks: fileChunks(stagingPath, byteSize, commit.signal),\n byteSize,\n sha256: contentHash,\n ...(commit.signal ? { signal: commit.signal } : {}),\n });\n const stored = await storage.headObject!(opaqueReference);\n if (!stored) throw new Error(\"Immutable object was not visible after write\");\n assertStoredObject(stored, byteSize, contentHash, input.contentType);\n }\n throwIfAborted(commit.signal);\n return Object.freeze({ opaqueReference });\n } finally {\n await cleanup();\n }\n },\n async abort() {\n closed = true;\n byteSize = 0;\n await cleanup();\n },\n };\n },\n });\n}\n\nfunction assertStoredObject(\n head: Awaited<ReturnType<NonNullable<ObjectStorage[\"headObject\"]>>>,\n byteSize: number,\n contentHash: string,\n contentType: string,\n): void {\n if (\n !head ||\n head.ContentLength !== byteSize ||\n head.Metadata?.sha256 !== contentHash ||\n head.ContentType !== contentType ||\n typeof head.VersionToken !== \"string\" ||\n head.VersionToken.length < 1\n ) {\n throw new Error(\"Immutable content-addressed object conflicts with stored metadata\");\n }\n}\n\nfunction hashForReference(reference: string, keyPrefix: string): string {\n const match = new RegExp(`^${escapeRegExp(keyPrefix)}([0-9a-f]{64})$`, \"u\").exec(reference);\n if (!match) throw new Error(\"Immutable snapshot reference is malformed\");\n return `sha256:${match[1]}`;\n}\n\nfunction validateKeyPrefix(value: string): string {\n if (\n typeof value !== \"string\" ||\n !/^editable-artifacts\\/[a-z0-9/-]+\\/sha256\\/$/u.test(value) ||\n value.includes(\"//\") ||\n value.includes(\"..\")\n ) {\n throw new Error(\"Immutable object key prefix is invalid\");\n }\n return value;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n}\n\nfunction validateContentType(value: string): void {\n if (\n typeof value !== \"string\" ||\n value.length < 1 ||\n value.length > 256 ||\n /[\\u0000-\\u001f\\u007f]/u.test(value)\n ) {\n throw new Error(\"Immutable object content type is invalid\");\n }\n}\n\nasync function* fileChunks(\n path: string,\n expectedByteSize: number,\n signal: AbortSignal | undefined,\n): AsyncIterableIterator<Uint8Array> {\n const handle = await open(path, \"r\");\n try {\n const buffer = new Uint8Array(1024 * 1024);\n let offset = 0;\n while (offset < expectedByteSize) {\n throwIfAborted(signal);\n const length = Math.min(buffer.byteLength, expectedByteSize - offset);\n let filled = 0;\n while (filled < length) {\n const { bytesRead } = await handle.read(buffer, filled, length - filled, offset + filled);\n if (bytesRead <= 0) throw new Error(\"Immutable staging file was truncated\");\n filled += bytesRead;\n }\n offset += filled;\n yield buffer.slice(0, filled);\n }\n const extra = new Uint8Array(1);\n if ((await handle.read(extra, 0, 1, expectedByteSize)).bytesRead !== 0) {\n throw new Error(\"Immutable staging file exceeded its committed size\");\n }\n } finally {\n await handle.close();\n }\n}\n\nasync function writeAll(handle: FileHandle, bytes: Uint8Array, position: number): Promise<void> {\n let offset = 0;\n while (offset < bytes.byteLength) {\n const { bytesWritten } = await handle.write(\n bytes,\n offset,\n bytes.byteLength - offset,\n position + offset,\n );\n if (bytesWritten <= 0) throw new Error(\"Immutable staging write was truncated\");\n offset += bytesWritten;\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new Error(\"Object storage operation was cancelled\");\n}\n"],"mappings":"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","names":["throwIfAborted","createHash","throwIfAborted","createHash"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/bounded-object-read.ts","../src/bounded-object-write.ts","../src/retry-while-missing.ts","../src/object-storage-bounded.ts"],"sourcesContent":["import type { Settings } from \"@opengeni/config\";\nimport { RETAINED_OUTPUT_MAX_PAGE_BYTES, type FileAsset } from \"@opengeni/contracts\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport {\n BlobSASPermissions,\n BlobServiceClient,\n generateBlobSASQueryParameters,\n StorageSharedKeyCredential,\n type BlobDownloadResponseParsed,\n type BlobGetPropertiesResponse,\n} from \"@azure/storage-blob\";\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n PutObjectCommand,\n S3Client,\n type S3ClientConfig,\n} from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport {\n Storage as GcsClient,\n type GetSignedUrlConfig,\n type StorageOptions,\n} from \"@google-cloud/storage\";\n\nexport * from \"./bounded-object-read\";\nexport * from \"./bounded-object-write\";\nexport * from \"./object-storage-bounded\";\nexport * from \"./retry-while-missing\";\n\nexport const MAX_SINGLE_PUT_SIZE_BYTES = 5_000_000_000;\nexport const UPLOAD_URL_TTL_SECONDS = 15 * 60;\nexport const DOWNLOAD_URL_TTL_SECONDS = 5 * 60;\nconst INTERNAL_STREAM_BUFFER_BYTES = 1024 * 1024;\nconst INTERNAL_STREAM_CONCURRENCY = 2;\n\nexport type ObjectHead = {\n ContentLength?: number;\n ContentType?: string;\n Metadata?: Record<string, string>;\n /** Opaque provider generation/etag used only for conditional internal reads. */\n VersionToken?: string;\n};\n\nexport type ObjectStorage = {\n bucket: string;\n backend: \"s3-compatible\" | \"aws-s3\" | \"azure-blob\" | \"gcs\";\n maxSinglePutSizeBytes: number;\n createPutUrl: (args: {\n key: string;\n contentType: string;\n sha256?: string | null;\n expiresInSeconds?: number;\n /** Select the network endpoint embedded in the signed URL. */\n audience?: \"public\" | \"sandbox\";\n }) => Promise<{ url: string; requiredHeaders: Record<string, string>; expiresAt: Date }>;\n createGetUrl: (args: {\n key: string;\n expiresInSeconds?: number;\n /** Select the network endpoint embedded in the signed URL. */\n audience?: \"public\" | \"sandbox\";\n }) => Promise<{ url: string; expiresAt: Date }>;\n headFile: (file: FileAsset) => Promise<ObjectHead>;\n /** Check provider existence without downloading object bytes. */\n fileExists: (file: FileAsset) => Promise<boolean>;\n getFileBytes: (file: FileAsset) => Promise<Uint8Array>;\n /**\n * Fetch exactly one inclusive byte range without materializing the complete\n * object. Returns null when the provider reports that the object is missing.\n */\n getFileRange: (\n file: FileAsset,\n range: { start: number; end: number },\n ) => Promise<Uint8Array | null>;\n /** Fetch an object by raw storage key (not a tracked FileAsset). Returns null on 404/missing. */\n getObjectBytes: (key: string) => Promise<{ bytes: Uint8Array; contentType?: string } | null>;\n /** Provider-versioned raw-key primitives used by bounded immutable adapters. */\n headObject?: (key: string) => Promise<ObjectHead | null>;\n getObjectRange?: (args: {\n key: string;\n start: number;\n endInclusive: number;\n expectedVersionToken: string;\n }) => Promise<{ bytes: Uint8Array; versionToken: string } | null>;\n /**\n * SERVER-SIDE authenticated direct PUT (no presign + browser fetch). For an\n * in-process upload from a trusted holder of the storage credentials (e.g. the\n * worker writing a recording), this sends the bytes straight to the storage\n * backend over the configured endpoint with the in-process SDK client — bypassing\n * the presigned-URL round-trip, which on split public/internal topologies (a\n * public `objectStorageEndpoint` with no in-cluster route) would otherwise 401.\n * Browser uploads keep using `createPutUrl`; this is the trusted-server twin.\n * Repeating a PUT for the same deterministic key and verified sha256 is\n * permitted: storage backends converge to the same bytes, while the database\n * completion fence remains the source of truth.\n */\n putObject: (args: {\n key: string;\n contentType: string;\n body: Uint8Array;\n sha256?: string | null;\n }) => Promise<void>;\n /** Atomic create-only raw PUT. Returns false when the key already exists. */\n putObjectIfAbsent?: (args: {\n key: string;\n contentType: string;\n body: Uint8Array;\n sha256: string;\n }) => Promise<boolean>;\n /**\n * Atomic create-only raw upload from a bounded asynchronous byte stream.\n * Providers may buffer a small fixed number of chunks, never the whole body.\n */\n putObjectStreamIfAbsent?: (args: {\n key: string;\n contentType: string;\n chunks: AsyncIterable<Uint8Array>;\n byteSize: number;\n sha256: string;\n signal?: AbortSignal;\n }) => Promise<boolean>;\n /**\n * SERVER-SIDE authenticated delete of a single object by raw storage key.\n * Idempotent: a missing key is a no-op (S3/GCS/Azure delete-by-key does not\n * 404 on absent objects, or the 404 is swallowed). Used by the Workbench v2\n * capture GC (keep the latest 10) to reap after-image blobs that no\n * surviving revision references. Best-effort at the call site — a failed\n * delete leaves an orphan blob, never corrupts a live capture.\n */\n deleteObject: (key: string) => Promise<void>;\n};\n\nexport function createObjectStorage(settings: Settings): ObjectStorage | null {\n if (settings.objectStorageBackend === \"azure-blob\") {\n return createAzureBlobObjectStorage(settings);\n }\n if (settings.objectStorageBackend === \"gcs\") {\n return createGcsObjectStorage(settings);\n }\n return createS3CompatibleObjectStorage(settings);\n}\n\nfunction createS3CompatibleObjectStorage(settings: Settings): ObjectStorage | null {\n if (\n settings.objectStorageBackend === \"s3-compatible\" &&\n (!settings.objectStorageEndpoint ||\n !settings.objectStorageAccessKeyId ||\n !settings.objectStorageSecretAccessKey)\n ) {\n return null;\n }\n const sharedClientConfig: S3ClientConfig = {\n region: settings.objectStorageRegion,\n forcePathStyle: settings.objectStorageForcePathStyle,\n requestChecksumCalculation: \"WHEN_REQUIRED\",\n ...(settings.objectStorageAccessKeyId && settings.objectStorageSecretAccessKey\n ? {\n credentials: {\n accessKeyId: settings.objectStorageAccessKeyId,\n secretAccessKey: settings.objectStorageSecretAccessKey,\n },\n }\n : {}),\n };\n const presignClient = new S3Client({\n ...sharedClientConfig,\n ...(settings.objectStorageEndpoint ? { endpoint: settings.objectStorageEndpoint } : {}),\n });\n const sandboxPresignClient = settings.objectStorageSandboxEndpoint\n ? new S3Client({\n ...sharedClientConfig,\n endpoint: settings.objectStorageSandboxEndpoint,\n })\n : presignClient;\n const requestClient = settings.objectStorageInternalEndpoint\n ? new S3Client({\n ...sharedClientConfig,\n endpoint: settings.objectStorageInternalEndpoint,\n })\n : presignClient;\n return {\n bucket: settings.objectStorageBucket,\n backend: settings.objectStorageBackend === \"aws-s3\" ? \"aws-s3\" : \"s3-compatible\",\n maxSinglePutSizeBytes: MAX_SINGLE_PUT_SIZE_BYTES,\n async createPutUrl(args) {\n const expiresIn = args.expiresInSeconds ?? UPLOAD_URL_TTL_SECONDS;\n const requiredHeaders: Record<string, string> = {\n \"content-type\": args.contentType,\n };\n const command = new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n Metadata: args.sha256 ? { sha256: args.sha256 } : undefined,\n });\n return {\n url: await getSignedUrl(\n args.audience === \"sandbox\" ? sandboxPresignClient : presignClient,\n command,\n {\n expiresIn,\n },\n ),\n requiredHeaders,\n expiresAt: new Date(Date.now() + expiresIn * 1000),\n };\n },\n async createGetUrl(args) {\n const expiresIn = args.expiresInSeconds ?? DOWNLOAD_URL_TTL_SECONDS;\n return {\n url: await getSignedUrl(\n args.audience === \"sandbox\" ? sandboxPresignClient : presignClient,\n new GetObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n }),\n { expiresIn },\n ),\n expiresAt: new Date(Date.now() + expiresIn * 1000),\n };\n },\n async putObject(args) {\n // Authenticated in-process PUT against the configured (in-cluster) endpoint.\n // A presigned URL buys nothing here — the worker already holds the creds — and\n // on a split public/internal endpoint topology the presigned URL points at the\n // PUBLIC host (no MinIO route → 401). This sends bytes straight to the backend.\n await requestClient.send(\n new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n Body: args.body,\n Metadata: args.sha256 ? { sha256: args.sha256 } : undefined,\n }),\n );\n },\n async putObjectIfAbsent(args) {\n try {\n await requestClient.send(\n new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n Body: args.body,\n Metadata: { sha256: args.sha256 },\n IfNoneMatch: \"*\",\n }),\n );\n return true;\n } catch (error) {\n if (isS3VersionMismatch(error)) return false;\n throw error;\n }\n },\n async putObjectStreamIfAbsent(args) {\n try {\n await requestClient.send(\n new PutObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n ContentType: args.contentType,\n ContentLength: args.byteSize,\n Body: Readable.from(args.chunks),\n Metadata: { sha256: args.sha256 },\n IfNoneMatch: \"*\",\n }),\n args.signal ? { abortSignal: args.signal } : undefined,\n );\n return true;\n } catch (error) {\n if (isS3VersionMismatch(error)) return false;\n throw error;\n }\n },\n async headFile(file) {\n const head = await requestClient.send(\n new HeadObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n }),\n );\n return objectHead({\n contentLength: head.ContentLength,\n contentType: head.ContentType,\n metadata: head.Metadata,\n });\n },\n async fileExists(file) {\n try {\n await requestClient.send(\n new HeadObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n }),\n );\n return true;\n } catch (error) {\n if (isS3NotFound(error)) return false;\n throw error;\n }\n },\n async getFileBytes(file) {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n }),\n );\n return await s3BodyToBytes(result.Body, file.objectKey);\n },\n async getFileRange(file, range) {\n const length = assertFileByteRange(file, range);\n try {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: file.bucket,\n Key: file.objectKey,\n Range: `bytes=${range.start}-${range.end}`,\n }),\n );\n return await s3BodyToBoundedBytes(result.Body, file.objectKey, length);\n } catch (error) {\n if (isS3NotFound(error)) return null;\n throw error;\n }\n },\n async headObject(key) {\n try {\n const head = await requestClient.send(\n new HeadObjectCommand({ Bucket: settings.objectStorageBucket, Key: key }),\n );\n return objectHead({\n contentLength: head.ContentLength,\n contentType: head.ContentType,\n metadata: head.Metadata,\n versionToken: head.ETag,\n });\n } catch (error) {\n if (isS3NotFound(error)) return null;\n throw error;\n }\n },\n async getObjectRange(args) {\n const length = assertRawObjectByteRange(args.key, args.start, args.endInclusive);\n try {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: args.key,\n Range: `bytes=${args.start}-${args.endInclusive}`,\n IfMatch: args.expectedVersionToken,\n }),\n );\n if (!result.ETag || result.ETag !== args.expectedVersionToken) return null;\n return {\n bytes: await s3BodyToBoundedBytes(result.Body, args.key, length),\n versionToken: result.ETag,\n };\n } catch (error) {\n if (isS3NotFound(error) || isS3VersionMismatch(error)) return null;\n throw error;\n }\n },\n async getObjectBytes(key) {\n try {\n const result = await requestClient.send(\n new GetObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: key,\n }),\n );\n const bytes = await s3BodyToBytes(result.Body, key);\n return { bytes, ...(result.ContentType ? { contentType: result.ContentType } : {}) };\n } catch (error) {\n if (isS3NotFound(error)) {\n return null;\n }\n throw error;\n }\n },\n async deleteObject(key) {\n // S3 DeleteObject is idempotent — deleting an absent key returns 204.\n await requestClient.send(\n new DeleteObjectCommand({\n Bucket: settings.objectStorageBucket,\n Key: key,\n }),\n );\n },\n };\n}\n\nasync function s3BodyToBytes(body: unknown, objectKey: string): Promise<Uint8Array> {\n if (!body) {\n throw new Error(`Object body is empty: ${objectKey}`);\n }\n const withTransform = body as { transformToByteArray?: () => Promise<Uint8Array> };\n if (typeof withTransform.transformToByteArray === \"function\") {\n return await withTransform.transformToByteArray();\n }\n const chunks: Uint8Array[] = [];\n for await (const chunk of body as AsyncIterable<Uint8Array | Buffer | string>) {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n }\n return Buffer.concat(chunks);\n}\n\nasync function s3BodyToBoundedBytes(\n body: unknown,\n objectKey: string,\n expectedBytes: number,\n): Promise<Uint8Array> {\n if (!body) {\n throw new Error(`Object body is empty: ${objectKey}`);\n }\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n for await (const chunk of body as AsyncIterable<Uint8Array | Buffer | string>) {\n const normalized = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n bytes += normalized.byteLength;\n if (bytes > expectedBytes) {\n throw new Error(`Object range exceeded requested length: ${objectKey}`);\n }\n chunks.push(normalized);\n }\n if (bytes !== expectedBytes) {\n throw new Error(\n `Object range length mismatch for ${objectKey}: expected ${expectedBytes}, received ${bytes}`,\n );\n }\n return Buffer.concat(chunks, bytes);\n}\n\nfunction isS3NotFound(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const name = \"name\" in error ? (error as { name?: unknown }).name : undefined;\n if (name === \"NoSuchKey\" || name === \"NotFound\") {\n return true;\n }\n const metadata =\n \"$metadata\" in error\n ? (error as { $metadata?: { httpStatusCode?: number } }).$metadata\n : undefined;\n return metadata?.httpStatusCode === 404;\n}\n\nfunction isS3VersionMismatch(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const metadata =\n \"$metadata\" in error\n ? (error as { $metadata?: { httpStatusCode?: number } }).$metadata\n : undefined;\n return metadata?.httpStatusCode === 412;\n}\n\nfunction createGcsObjectStorage(settings: Settings): ObjectStorage {\n const client = new GcsClient(gcsClientOptions(settings));\n const bucket = client.bucket(settings.objectStorageBucket);\n return {\n bucket: settings.objectStorageBucket,\n backend: \"gcs\",\n maxSinglePutSizeBytes: MAX_SINGLE_PUT_SIZE_BYTES,\n async createPutUrl(args) {\n const expiresIn = args.expiresInSeconds ?? UPLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const config: GetSignedUrlConfig = {\n version: \"v4\",\n action: \"write\",\n expires: expiresAt,\n contentType: args.contentType,\n };\n if (args.sha256) {\n config.extensionHeaders = { \"x-goog-meta-sha256\": args.sha256 };\n }\n const [url] = await bucket.file(args.key).getSignedUrl(config);\n return {\n url,\n requiredHeaders: {\n \"content-type\": args.contentType,\n ...(args.sha256 ? { \"x-goog-meta-sha256\": args.sha256 } : {}),\n },\n expiresAt,\n };\n },\n async createGetUrl(args) {\n const expiresIn = args.expiresInSeconds ?? DOWNLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const [url] = await bucket.file(args.key).getSignedUrl({\n version: \"v4\",\n action: \"read\",\n expires: expiresAt,\n });\n return { url, expiresAt };\n },\n async putObject(args) {\n // Authenticated in-process PUT via the GCS SDK (the server holds the creds).\n await bucket.file(args.key).save(Buffer.from(args.body), {\n contentType: args.contentType,\n ...(args.sha256 ? { metadata: { metadata: { sha256: args.sha256 } } } : {}),\n });\n },\n async putObjectIfAbsent(args) {\n try {\n await bucket.file(args.key).save(Buffer.from(args.body), {\n contentType: args.contentType,\n metadata: { metadata: { sha256: args.sha256 } },\n preconditionOpts: { ifGenerationMatch: 0 },\n });\n return true;\n } catch (error) {\n if (isGcsVersionMismatch(error)) return false;\n throw error;\n }\n },\n async putObjectStreamIfAbsent(args) {\n const destination = bucket.file(args.key).createWriteStream({\n resumable: false,\n contentType: args.contentType,\n highWaterMark: INTERNAL_STREAM_BUFFER_BYTES,\n metadata: { metadata: { sha256: args.sha256 } },\n preconditionOpts: { ifGenerationMatch: 0 },\n });\n try {\n if (args.signal) {\n await pipeline(Readable.from(args.chunks), destination, { signal: args.signal });\n } else {\n await pipeline(Readable.from(args.chunks), destination);\n }\n return true;\n } catch (error) {\n if (isGcsVersionMismatch(error)) return false;\n throw error;\n }\n },\n async headFile(file) {\n const [metadata] = await bucket.file(file.objectKey).getMetadata();\n return objectHead({\n contentLength: parseContentLength(metadata.size),\n contentType: metadata.contentType,\n metadata: stringMetadata(metadata.metadata),\n });\n },\n async fileExists(file) {\n try {\n await bucket.file(file.objectKey).getMetadata();\n return true;\n } catch (error) {\n if (isGcsNotFound(error)) return false;\n throw error;\n }\n },\n async getFileBytes(file) {\n const [bytes] = await bucket.file(file.objectKey).download();\n return bytes;\n },\n async getFileRange(file, range) {\n const length = assertFileByteRange(file, range);\n try {\n const [bytes] = await bucket\n .file(file.objectKey)\n .download({ start: range.start, end: range.end });\n return exactRangeBytes(bytes, file.objectKey, length);\n } catch (error) {\n if (isGcsNotFound(error)) return null;\n throw error;\n }\n },\n async headObject(key) {\n try {\n const [metadata] = await bucket.file(key).getMetadata();\n return objectHead({\n contentLength: parseContentLength(metadata.size),\n contentType: metadata.contentType,\n metadata: stringMetadata(metadata.metadata),\n versionToken: metadata.generation === undefined ? undefined : String(metadata.generation),\n });\n } catch (error) {\n if (isGcsNotFound(error)) return null;\n throw error;\n }\n },\n async getObjectRange(args) {\n const length = assertRawObjectByteRange(args.key, args.start, args.endInclusive);\n try {\n const [bytes] = await bucket\n .file(args.key, { generation: args.expectedVersionToken })\n .download({ start: args.start, end: args.endInclusive });\n return {\n bytes: exactRangeBytes(bytes, args.key, length),\n versionToken: args.expectedVersionToken,\n };\n } catch (error) {\n if (isGcsNotFound(error) || isGcsVersionMismatch(error)) return null;\n throw error;\n }\n },\n async getObjectBytes(key) {\n try {\n const [bytes] = await bucket.file(key).download();\n return { bytes };\n } catch (error) {\n if (isGcsNotFound(error)) {\n return null;\n }\n throw error;\n }\n },\n async deleteObject(key) {\n // ignoreNotFound keeps the delete idempotent (a missing blob is a no-op).\n await bucket.file(key).delete({ ignoreNotFound: true });\n },\n };\n}\n\nfunction isGcsNotFound(error: unknown): boolean {\n return Boolean(error) && typeof error === \"object\" && (error as { code?: unknown }).code === 404;\n}\n\nfunction isGcsVersionMismatch(error: unknown): boolean {\n return Boolean(error) && typeof error === \"object\" && (error as { code?: unknown }).code === 412;\n}\n\nfunction createAzureBlobObjectStorage(settings: Settings): ObjectStorage | null {\n const sharedKey = azureSharedKeyCredential(settings);\n const requestServiceClient = settings.objectStorageAzureConnectionString\n ? BlobServiceClient.fromConnectionString(settings.objectStorageAzureConnectionString)\n : new BlobServiceClient(azureBlobServiceUrl(settings), sharedKey);\n const presignServiceClient = settings.objectStorageAzureEndpoint\n ? new BlobServiceClient(azureBlobServiceUrl(settings), sharedKey)\n : requestServiceClient;\n const requestContainerClient = requestServiceClient.getContainerClient(\n settings.objectStorageBucket,\n );\n const presignContainerClient = presignServiceClient.getContainerClient(\n settings.objectStorageBucket,\n );\n\n return {\n bucket: settings.objectStorageBucket,\n backend: \"azure-blob\",\n maxSinglePutSizeBytes: MAX_SINGLE_PUT_SIZE_BYTES,\n async createPutUrl(args) {\n const expiresIn = args.expiresInSeconds ?? UPLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const blobClient = presignContainerClient.getBlockBlobClient(args.key);\n const sas = generateBlobSASQueryParameters(\n {\n containerName: settings.objectStorageBucket,\n blobName: args.key,\n permissions: BlobSASPermissions.parse(\"cw\"),\n expiresOn: expiresAt,\n contentType: args.contentType,\n },\n sharedKey,\n ).toString();\n return {\n url: `${blobClient.url}?${sas}`,\n requiredHeaders: {\n \"content-type\": args.contentType,\n \"x-ms-blob-type\": \"BlockBlob\",\n ...(args.sha256 ? { \"x-ms-meta-sha256\": args.sha256 } : {}),\n },\n expiresAt,\n };\n },\n async createGetUrl(args) {\n const expiresIn = args.expiresInSeconds ?? DOWNLOAD_URL_TTL_SECONDS;\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n const blobClient = presignContainerClient.getBlobClient(args.key);\n const sas = generateBlobSASQueryParameters(\n {\n containerName: settings.objectStorageBucket,\n blobName: args.key,\n permissions: BlobSASPermissions.parse(\"r\"),\n expiresOn: expiresAt,\n },\n sharedKey,\n ).toString();\n return {\n url: `${blobClient.url}?${sas}`,\n expiresAt,\n };\n },\n async putObject(args) {\n // Authenticated in-process upload via the shared-key Azure client (no SAS).\n const blobClient = requestContainerClient.getBlockBlobClient(args.key);\n const body = Buffer.from(args.body);\n await blobClient.upload(body, body.byteLength, {\n blobHTTPHeaders: { blobContentType: args.contentType },\n ...(args.sha256 ? { metadata: { sha256: args.sha256 } } : {}),\n });\n },\n async putObjectIfAbsent(args) {\n const blobClient = requestContainerClient.getBlockBlobClient(args.key);\n const body = Buffer.from(args.body);\n try {\n await blobClient.upload(body, body.byteLength, {\n blobHTTPHeaders: { blobContentType: args.contentType },\n metadata: { sha256: args.sha256 },\n conditions: { ifNoneMatch: \"*\" },\n });\n return true;\n } catch (error) {\n if (isAzureVersionMismatch(error)) return false;\n throw error;\n }\n },\n async putObjectStreamIfAbsent(args) {\n const blobClient = requestContainerClient.getBlockBlobClient(args.key);\n try {\n await blobClient.uploadStream(\n Readable.from(args.chunks),\n INTERNAL_STREAM_BUFFER_BYTES,\n INTERNAL_STREAM_CONCURRENCY,\n {\n blobHTTPHeaders: { blobContentType: args.contentType },\n metadata: { sha256: args.sha256 },\n conditions: { ifNoneMatch: \"*\" },\n ...(args.signal ? { abortSignal: args.signal } : {}),\n },\n );\n return true;\n } catch (error) {\n if (isAzureVersionMismatch(error)) return false;\n throw error;\n }\n },\n async headFile(file) {\n return azureHeadToObjectHead(\n await requestContainerClient.getBlobClient(file.objectKey).getProperties(),\n );\n },\n async fileExists(file) {\n try {\n await requestContainerClient.getBlobClient(file.objectKey).getProperties();\n return true;\n } catch (error) {\n if (isAzureNotFound(error)) return false;\n throw error;\n }\n },\n async getFileBytes(file) {\n return await azureDownloadToBytes(\n await requestContainerClient.getBlobClient(file.objectKey).download(),\n );\n },\n async getFileRange(file, range) {\n const length = assertFileByteRange(file, range);\n try {\n return await azureDownloadToBoundedBytes(\n await requestContainerClient.getBlobClient(file.objectKey).download(range.start, length),\n file.objectKey,\n length,\n );\n } catch (error) {\n if (isAzureNotFound(error)) return null;\n throw error;\n }\n },\n async headObject(key) {\n try {\n const properties = await requestContainerClient.getBlobClient(key).getProperties();\n return objectHead({\n contentLength: properties.contentLength,\n contentType: properties.contentType,\n metadata: properties.metadata,\n versionToken: properties.etag,\n });\n } catch (error) {\n if (isAzureNotFound(error)) return null;\n throw error;\n }\n },\n async getObjectRange(args) {\n const length = assertRawObjectByteRange(args.key, args.start, args.endInclusive);\n try {\n const download = await requestContainerClient\n .getBlobClient(args.key)\n .download(args.start, length, { conditions: { ifMatch: args.expectedVersionToken } });\n if (!download.etag || download.etag !== args.expectedVersionToken) return null;\n return {\n bytes: await azureDownloadToBoundedBytes(download, args.key, length),\n versionToken: download.etag,\n };\n } catch (error) {\n if (isAzureNotFound(error) || isAzureVersionMismatch(error)) return null;\n throw error;\n }\n },\n async getObjectBytes(key) {\n try {\n const download = await requestContainerClient.getBlobClient(key).download();\n const bytes = await azureDownloadToBytes(download);\n return { bytes, ...(download.contentType ? { contentType: download.contentType } : {}) };\n } catch (error) {\n if (isAzureNotFound(error)) {\n return null;\n }\n throw error;\n }\n },\n async deleteObject(key) {\n // deleteIfExists keeps the delete idempotent (a missing blob is a no-op).\n await requestContainerClient.getBlockBlobClient(key).deleteIfExists();\n },\n };\n}\n\nfunction isAzureNotFound(error: unknown): boolean {\n return (\n Boolean(error) &&\n typeof error === \"object\" &&\n (error as { statusCode?: unknown }).statusCode === 404\n );\n}\n\nfunction isAzureVersionMismatch(error: unknown): boolean {\n return (\n Boolean(error) &&\n typeof error === \"object\" &&\n (error as { statusCode?: unknown }).statusCode === 412\n );\n}\n\nfunction azureSharedKeyCredential(settings: Settings): StorageSharedKeyCredential {\n if (settings.objectStorageAzureConnectionString) {\n const parsed = parseConnectionString(settings.objectStorageAzureConnectionString);\n if (parsed.AccountName && parsed.AccountKey) {\n return new StorageSharedKeyCredential(parsed.AccountName, parsed.AccountKey);\n }\n throw new Error(\n \"Azure Blob connection string must include AccountName and AccountKey to create presigned URLs\",\n );\n }\n if (!settings.objectStorageAzureAccountName || !settings.objectStorageAzureAccountKey) {\n throw new Error(\"Azure Blob storage requires account name and account key\");\n }\n return new StorageSharedKeyCredential(\n settings.objectStorageAzureAccountName,\n settings.objectStorageAzureAccountKey,\n );\n}\n\nfunction azureBlobServiceUrl(settings: Settings): string {\n if (settings.objectStorageAzureEndpoint) {\n return settings.objectStorageAzureEndpoint.replace(/\\/+$/, \"\");\n }\n if (!settings.objectStorageAzureAccountName) {\n throw new Error(\"Azure Blob storage requires account name\");\n }\n return `https://${settings.objectStorageAzureAccountName}.blob.core.windows.net`;\n}\n\nfunction parseConnectionString(value: string): Record<string, string> {\n return Object.fromEntries(\n value\n .split(\";\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => {\n const index = part.indexOf(\"=\");\n return index === -1 ? [part, \"\"] : [part.slice(0, index), part.slice(index + 1)];\n }),\n );\n}\n\nfunction gcsClientOptions(settings: Settings): StorageOptions {\n const options: StorageOptions = {\n ...(settings.objectStorageGcsProjectId\n ? { projectId: settings.objectStorageGcsProjectId }\n : {}),\n ...(settings.objectStorageGcsKeyFilename\n ? { keyFilename: settings.objectStorageGcsKeyFilename }\n : {}),\n ...(settings.objectStorageGcsApiEndpoint\n ? { apiEndpoint: settings.objectStorageGcsApiEndpoint }\n : {}),\n };\n if (settings.objectStorageGcsCredentialsJson) {\n options.credentials = parseGcsCredentials(settings.objectStorageGcsCredentialsJson);\n }\n return options;\n}\n\nfunction parseGcsCredentials(raw: string): Record<string, string> {\n const parsed = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"GCS credentials JSON must be an object\");\n }\n return parsed as Record<string, string>;\n}\n\nfunction parseContentLength(value: string | number | undefined): number | undefined {\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value !== \"string\" || value.length === 0) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction stringMetadata(\n value: Record<string, string | number | boolean | null> | undefined,\n): Record<string, string> | undefined {\n if (!value) {\n return undefined;\n }\n return Object.fromEntries(\n Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n ),\n );\n}\n\nfunction azureHeadToObjectHead(head: BlobGetPropertiesResponse): ObjectHead {\n return objectHead({\n contentLength: head.contentLength,\n contentType: head.contentType,\n metadata: head.metadata,\n });\n}\n\nasync function azureDownloadToBytes(download: BlobDownloadResponseParsed): Promise<Uint8Array> {\n if (!download.readableStreamBody) {\n throw new Error(\"Azure Blob download response did not include a readable body\");\n }\n const chunks: Uint8Array[] = [];\n for await (const chunk of download.readableStreamBody as AsyncIterable<\n Uint8Array | Buffer | string\n >) {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n }\n return Buffer.concat(chunks);\n}\n\nasync function azureDownloadToBoundedBytes(\n download: BlobDownloadResponseParsed,\n objectKey: string,\n expectedBytes: number,\n): Promise<Uint8Array> {\n if (!download.readableStreamBody) {\n throw new Error(\"Azure Blob download response did not include a readable body\");\n }\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n for await (const chunk of download.readableStreamBody as AsyncIterable<\n Uint8Array | Buffer | string\n >) {\n const normalized = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n bytes += normalized.byteLength;\n if (bytes > expectedBytes) {\n throw new Error(`Object range exceeded requested length: ${objectKey}`);\n }\n chunks.push(normalized);\n }\n if (bytes !== expectedBytes) {\n throw new Error(\n `Object range length mismatch for ${objectKey}: expected ${expectedBytes}, received ${bytes}`,\n );\n }\n return Buffer.concat(chunks, bytes);\n}\n\nfunction assertFileByteRange(\n file: Pick<FileAsset, \"sizeBytes\" | \"objectKey\">,\n range: { start: number; end: number },\n): number {\n if (\n !Number.isSafeInteger(range.start) ||\n !Number.isSafeInteger(range.end) ||\n range.start < 0 ||\n range.end < range.start ||\n range.end >= file.sizeBytes\n ) {\n throw new RangeError(`Invalid object byte range for ${file.objectKey}`);\n }\n const length = range.end - range.start + 1;\n if (length > RETAINED_OUTPUT_MAX_PAGE_BYTES) {\n throw new RangeError(\n `Object byte range exceeds ${RETAINED_OUTPUT_MAX_PAGE_BYTES} bytes for ${file.objectKey}`,\n );\n }\n return length;\n}\n\nfunction assertRawObjectByteRange(key: string, start: number, endInclusive: number): number {\n if (\n typeof key !== \"string\" ||\n key.length < 1 ||\n key.length > 2048 ||\n !Number.isSafeInteger(start) ||\n !Number.isSafeInteger(endInclusive) ||\n start < 0 ||\n endInclusive < start\n ) {\n throw new RangeError(\"Invalid raw object byte range\");\n }\n const length = endInclusive - start + 1;\n if (length > RETAINED_OUTPUT_MAX_PAGE_BYTES) {\n throw new RangeError(\"Raw object byte range exceeds the bounded page limit\");\n }\n return length;\n}\n\nfunction exactRangeBytes(bytes: Uint8Array, objectKey: string, expectedBytes: number): Uint8Array {\n if (bytes.byteLength !== expectedBytes) {\n throw new Error(\n `Object range length mismatch for ${objectKey}: expected ${expectedBytes}, received ${bytes.byteLength}`,\n );\n }\n return bytes;\n}\n\nfunction objectHead(input: {\n contentLength?: number | undefined;\n contentType?: string | undefined;\n metadata?: Record<string, string> | undefined;\n versionToken?: string | undefined;\n}): ObjectHead {\n return {\n ...(input.contentLength !== undefined ? { ContentLength: input.contentLength } : {}),\n ...(input.contentType !== undefined ? { ContentType: input.contentType } : {}),\n ...(input.metadata !== undefined ? { Metadata: input.metadata } : {}),\n ...(input.versionToken !== undefined ? { VersionToken: input.versionToken } : {}),\n };\n}\n\nexport function bytesToDataUrl(bytes: Uint8Array, contentType: string): string {\n return `data:${contentType};base64,${Buffer.from(bytes).toString(\"base64\")}`;\n}\n","/**\n * Version-pinned, bounded object reads for large trusted-server workloads.\n *\n * This surface deliberately deals in opaque references. Provider keys, bucket\n * names, signed URLs, and provider diagnostics stay behind the backend\n * callback and are never included in returned values or public errors.\n */\n\nexport const DEFAULT_BOUNDED_OBJECT_CHUNK_BYTES = 1024 * 1024;\nexport const MAX_BOUNDED_OBJECT_CHUNK_BYTES = 8 * 1024 * 1024;\n\nexport type BoundedObjectReadErrorCode =\n | \"aborted\"\n | \"backend_failure\"\n | \"invalid_request\"\n | \"object_changed\"\n | \"object_missing\"\n | \"size_limit\"\n | \"truncated\";\n\nexport class BoundedObjectReadError extends Error {\n readonly code: BoundedObjectReadErrorCode;\n\n constructor(code: BoundedObjectReadErrorCode) {\n super(messageForCode(code));\n this.name = \"BoundedObjectReadError\";\n this.code = code;\n }\n}\n\nexport type VersionedObjectDescription = Readonly<{\n byteSize: number;\n /** Opaque provider generation/etag token. It never crosses this package. */\n versionToken: string;\n /**\n * Explicit adapter assertion that the opaque reference resolves forever to\n * this provider generation (for example a version id or immutable\n * content-addressed object). Mutable raw keys must never set this flag.\n */\n immutableReference: true;\n contentType?: string;\n}>;\n\nexport type VersionedObjectRange = Readonly<{\n bytes: Uint8Array;\n versionToken: string;\n}>;\n\n/**\n * Provider adapter used by the range reader. Implementations should use a\n * provider-native generation/version/If-Match condition whenever available.\n * Returning a different version is treated as replacement, never as data.\n */\nexport interface VersionedRangeObjectBackend {\n describe(input: {\n opaqueReference: string;\n signal?: AbortSignal;\n }): Promise<VersionedObjectDescription | null>;\n readRange(input: {\n opaqueReference: string;\n start: number;\n endInclusive: number;\n expectedVersionToken: string;\n signal?: AbortSignal;\n }): Promise<VersionedObjectRange | null>;\n close?(input: { opaqueReference: string }): void | Promise<void>;\n}\n\nexport interface BoundedObjectRead {\n readonly byteSize: number;\n readonly contentType: string | undefined;\n /** A read handle is intentionally single-use. */\n chunks(input?: { chunkBytes?: number; signal?: AbortSignal }): AsyncIterable<Uint8Array>;\n /** Revalidate the immutable provider generation after all consumers finish. */\n assertUnchanged(signal?: AbortSignal): Promise<void>;\n close(): Promise<void>;\n}\n\nexport interface BoundedObjectReadPort {\n open(input: {\n opaqueReference: string;\n maxBytes: number;\n expectedByteSize?: number;\n signal?: AbortSignal;\n }): Promise<BoundedObjectRead>;\n}\n\n/**\n * Adds uniform limits, exact-range checks, replacement fencing, cancellation,\n * and diagnostic scrubbing around a provider-specific range backend.\n */\nexport function createBoundedObjectReadPort(\n backend: VersionedRangeObjectBackend,\n): BoundedObjectReadPort {\n return Object.freeze({\n async open(input: {\n opaqueReference: string;\n maxBytes: number;\n expectedByteSize?: number;\n signal?: AbortSignal;\n }): Promise<BoundedObjectRead> {\n validateReference(input.opaqueReference);\n assertPositiveSafeInteger(input.maxBytes);\n if (input.expectedByteSize !== undefined) {\n assertNonnegativeSafeInteger(input.expectedByteSize);\n }\n throwIfAborted(input.signal);\n const description = await scrubBackendFailure(async () =>\n backend.describe({\n opaqueReference: input.opaqueReference,\n ...(input.signal ? { signal: input.signal } : {}),\n }),\n );\n // Provider adapters are allowed to receive AbortSignal, but correctness\n // cannot depend on every SDK honouring it while an I/O promise is active.\n throwIfAborted(input.signal);\n if (!description) throw new BoundedObjectReadError(\"object_missing\");\n validateDescription(description);\n if (description.byteSize > input.maxBytes) {\n throw new BoundedObjectReadError(\"size_limit\");\n }\n if (input.expectedByteSize !== undefined && description.byteSize !== input.expectedByteSize) {\n throw new BoundedObjectReadError(\"truncated\");\n }\n return new VersionPinnedBoundedObjectRead(backend, input.opaqueReference, description);\n },\n });\n}\n\nclass VersionPinnedBoundedObjectRead implements BoundedObjectRead {\n readonly byteSize: number;\n readonly contentType: string | undefined;\n readonly #backend: VersionedRangeObjectBackend;\n readonly #opaqueReference: string;\n readonly #versionToken: string;\n #claimed = false;\n #closed = false;\n\n constructor(\n backend: VersionedRangeObjectBackend,\n opaqueReference: string,\n description: VersionedObjectDescription,\n ) {\n this.#backend = backend;\n this.#opaqueReference = opaqueReference;\n this.#versionToken = description.versionToken;\n this.byteSize = description.byteSize;\n this.contentType = description.contentType;\n }\n\n chunks(\n input: {\n chunkBytes?: number;\n signal?: AbortSignal;\n } = {},\n ): AsyncIterable<Uint8Array> {\n if (this.#closed || this.#claimed) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n const chunkBytes = input.chunkBytes ?? DEFAULT_BOUNDED_OBJECT_CHUNK_BYTES;\n assertPositiveSafeInteger(chunkBytes);\n if (chunkBytes > MAX_BOUNDED_OBJECT_CHUNK_BYTES) {\n throw new BoundedObjectReadError(\"size_limit\");\n }\n this.#claimed = true;\n return this.#streamChunks(chunkBytes, input.signal);\n }\n\n async *#streamChunks(\n chunkBytes: number,\n signal: AbortSignal | undefined,\n ): AsyncIterableIterator<Uint8Array> {\n let offset = 0;\n let completed = false;\n try {\n while (offset < this.byteSize) {\n throwIfAborted(signal);\n if (this.#closed) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n const endInclusive = Math.min(this.byteSize - 1, offset + chunkBytes - 1);\n const range = await scrubBackendFailure(async () =>\n this.#backend.readRange({\n opaqueReference: this.#opaqueReference,\n start: offset,\n endInclusive,\n expectedVersionToken: this.#versionToken,\n ...(signal ? { signal } : {}),\n }),\n );\n throwIfAborted(signal);\n if (!range) {\n throw new BoundedObjectReadError(\"object_changed\");\n }\n if (range.versionToken !== this.#versionToken) {\n throw new BoundedObjectReadError(\"object_changed\");\n }\n const expectedLength = endInclusive - offset + 1;\n if (range.bytes.byteLength !== expectedLength) {\n throw new BoundedObjectReadError(\"truncated\");\n }\n offset += range.bytes.byteLength;\n // Detach consumers from mutable provider buffers.\n yield range.bytes.slice();\n }\n throwIfAborted(signal);\n completed = true;\n } finally {\n // Keep a successfully consumed handle live for the mandatory final\n // generation check. Early return, failure, and cancellation clean up\n // immediately; normal callers close after assertUnchanged().\n if (!completed) await this.close();\n }\n }\n\n async assertUnchanged(signal?: AbortSignal): Promise<void> {\n if (this.#closed) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n throwIfAborted(signal);\n const current = await scrubBackendFailure(async () =>\n this.#backend.describe({\n opaqueReference: this.#opaqueReference,\n ...(signal ? { signal } : {}),\n }),\n );\n throwIfAborted(signal);\n if (\n !current ||\n current.versionToken !== this.#versionToken ||\n current.byteSize !== this.byteSize\n ) {\n throw new BoundedObjectReadError(\"object_changed\");\n }\n }\n\n async close(): Promise<void> {\n if (this.#closed) return;\n this.#closed = true;\n if (!this.#backend.close) return;\n try {\n await this.#backend.close({ opaqueReference: this.#opaqueReference });\n } catch {\n // Cleanup is best-effort and must not replace the verification result.\n }\n }\n}\n\nasync function scrubBackendFailure<T>(operation: () => Promise<T>): Promise<T> {\n try {\n return await operation();\n } catch (error) {\n if (error instanceof BoundedObjectReadError) throw error;\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n}\n\nfunction validateReference(value: string): void {\n if (\n typeof value !== \"string\" ||\n value.length < 1 ||\n value.length > 2048 ||\n value.trim() !== value ||\n /[\\u0000-\\u001f\\u007f]/.test(value)\n ) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n}\n\nfunction validateDescription(value: VersionedObjectDescription): void {\n assertNonnegativeSafeInteger(value.byteSize);\n if (value.immutableReference !== true) {\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n if (\n typeof value.versionToken !== \"string\" ||\n value.versionToken.length < 1 ||\n value.versionToken.length > 2048\n ) {\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n if (\n value.contentType !== undefined &&\n (value.contentType.length < 1 || value.contentType.length > 256)\n ) {\n throw new BoundedObjectReadError(\"backend_failure\");\n }\n}\n\nfunction assertPositiveSafeInteger(value: number): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n}\n\nfunction assertNonnegativeSafeInteger(value: number): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new BoundedObjectReadError(\"invalid_request\");\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new BoundedObjectReadError(\"aborted\");\n}\n\nfunction messageForCode(code: BoundedObjectReadErrorCode): string {\n switch (code) {\n case \"aborted\":\n return \"Bounded object read was cancelled\";\n case \"backend_failure\":\n return \"Bounded object read failed\";\n case \"invalid_request\":\n return \"Bounded object read request is invalid\";\n case \"object_changed\":\n return \"Bounded object changed during verification\";\n case \"object_missing\":\n return \"Bounded object is unavailable\";\n case \"size_limit\":\n return \"Bounded object exceeds the configured limit\";\n case \"truncated\":\n return \"Bounded object length does not match its immutable metadata\";\n }\n}\n","import { createHash } from \"node:crypto\";\nimport {\n BoundedObjectReadError,\n MAX_BOUNDED_OBJECT_CHUNK_BYTES,\n type BoundedObjectReadPort,\n} from \"./bounded-object-read\";\nimport { retryWhileMissing } from \"./retry-while-missing\";\n\nexport type BoundedObjectWriteErrorCode =\n | \"aborted\"\n | \"backend_failure\"\n | \"content_hash_mismatch\"\n | \"invalid_request\"\n | \"readback_mismatch\"\n | \"size_limit\"\n | \"truncated\";\n\nexport class BoundedObjectWriteError extends Error {\n readonly code: BoundedObjectWriteErrorCode;\n\n constructor(code: BoundedObjectWriteErrorCode) {\n super(writeErrorMessage(code));\n this.name = \"BoundedObjectWriteError\";\n this.code = code;\n }\n}\n\nexport interface ImmutableContentAddressedWriteSession {\n write(chunk: Uint8Array, signal?: AbortSignal): Promise<void>;\n /**\n * Atomically promotes staged bytes to an immutable content-addressed object.\n * The returned reference must resolve forever to this exact generation.\n */\n commit(input: {\n byteSize: number;\n contentHash: string;\n contentType: string;\n signal?: AbortSignal;\n }): Promise<{ opaqueReference: string }>;\n abort(): void | Promise<void>;\n}\n\nexport interface ImmutableContentAddressedWriteBackend {\n begin(input: {\n contentType: string;\n signal?: AbortSignal;\n }): Promise<ImmutableContentAddressedWriteSession>;\n}\n\nexport type BoundedImmutableObjectWriteResult = Readonly<{\n opaqueReference: string;\n byteSize: number;\n contentHash: string;\n contentType: string;\n}>;\n\nexport interface BoundedImmutableObjectWritePort {\n write(input: {\n chunks: AsyncIterable<Uint8Array>;\n contentType: string;\n maxBytes: number;\n expectedByteSize?: number;\n expectedContentHash?: string;\n signal?: AbortSignal;\n }): Promise<BoundedImmutableObjectWriteResult>;\n}\n\n/**\n * Streams to provider staging, atomically promotes by digest, then streams the\n * immutable object back and hashes it independently before returning its\n * opaque reference. Neither direction accumulates the complete object.\n */\nexport function createBoundedImmutableObjectWritePort(input: {\n backend: ImmutableContentAddressedWriteBackend;\n readback: BoundedObjectReadPort;\n}): BoundedImmutableObjectWritePort {\n return Object.freeze({\n async write(request: {\n chunks: AsyncIterable<Uint8Array>;\n contentType: string;\n maxBytes: number;\n expectedByteSize?: number;\n expectedContentHash?: string;\n signal?: AbortSignal;\n }): Promise<BoundedImmutableObjectWriteResult> {\n validateWriteRequest(request);\n throwIfAborted(request.signal);\n let session: ImmutableContentAddressedWriteSession | undefined;\n let committed = false;\n try {\n session = await scrubWriteBackend(async () =>\n input.backend.begin({\n contentType: request.contentType,\n ...(request.signal ? { signal: request.signal } : {}),\n }),\n );\n const digest = createHash(\"sha256\");\n let byteSize = 0;\n for await (const sourceChunk of request.chunks) {\n throwIfAborted(request.signal);\n if (!(sourceChunk instanceof Uint8Array) || sourceChunk.byteLength === 0) {\n throw new BoundedObjectWriteError(\"truncated\");\n }\n if (sourceChunk.byteLength > MAX_BOUNDED_OBJECT_CHUNK_BYTES) {\n throw new BoundedObjectWriteError(\"size_limit\");\n }\n byteSize += sourceChunk.byteLength;\n if (byteSize > request.maxBytes) {\n throw new BoundedObjectWriteError(\"size_limit\");\n }\n const chunk = sourceChunk.slice();\n digest.update(chunk);\n await scrubWriteBackend(async () => session!.write(chunk, request.signal));\n }\n // A backend may ignore AbortSignal and resolve the final write after the\n // caller has cancelled. Recheck before publishing staged bytes; without\n // this fence a one-chunk upload could still be committed after abort.\n throwIfAborted(request.signal);\n if (request.expectedByteSize !== undefined && byteSize !== request.expectedByteSize) {\n throw new BoundedObjectWriteError(\"truncated\");\n }\n const contentHash = `sha256:${digest.digest(\"hex\")}`;\n if (\n request.expectedContentHash !== undefined &&\n contentHash !== request.expectedContentHash\n ) {\n throw new BoundedObjectWriteError(\"content_hash_mismatch\");\n }\n const promoted = await scrubWriteBackend(async () =>\n session!.commit({\n byteSize,\n contentHash,\n contentType: request.contentType,\n ...(request.signal ? { signal: request.signal } : {}),\n }),\n );\n validateOpaqueReference(promoted.opaqueReference);\n committed = true;\n // A provider may finish promotion after cancellation despite receiving\n // the signal. The immutable object can be swept, but it must never be\n // returned to a caller as a successful publication candidate.\n throwIfAborted(request.signal);\n\n const reader = await retryWhileMissing(\n async () => {\n try {\n return await input.readback.open({\n opaqueReference: promoted.opaqueReference,\n maxBytes: request.maxBytes,\n expectedByteSize: byteSize,\n ...(request.signal ? { signal: request.signal } : {}),\n });\n } catch (error) {\n if (error instanceof BoundedObjectReadError && error.code === \"object_missing\") {\n return null;\n }\n throw error;\n }\n },\n request.signal ? { signal: request.signal } : {},\n );\n if (!reader) throw new BoundedObjectWriteError(\"readback_mismatch\");\n try {\n if (reader.contentType !== undefined && reader.contentType !== request.contentType) {\n throw new BoundedObjectWriteError(\"readback_mismatch\");\n }\n const readbackHash = createHash(\"sha256\");\n let readbackBytes = 0;\n for await (const chunk of reader.chunks({\n ...(request.signal ? { signal: request.signal } : {}),\n })) {\n readbackBytes += chunk.byteLength;\n if (readbackBytes > byteSize) {\n throw new BoundedObjectWriteError(\"readback_mismatch\");\n }\n readbackHash.update(chunk);\n }\n const readbackContentHash = `sha256:${readbackHash.digest(\"hex\")}`;\n if (readbackBytes !== byteSize || readbackContentHash !== contentHash) {\n throw new BoundedObjectWriteError(\"readback_mismatch\");\n }\n await reader.assertUnchanged(request.signal);\n throwIfAborted(request.signal);\n } finally {\n await reader.close();\n }\n return Object.freeze({\n opaqueReference: promoted.opaqueReference,\n byteSize,\n contentHash,\n contentType: request.contentType,\n });\n } catch (error) {\n throw mapWriteFailure(error, request.signal);\n } finally {\n if (session && !committed) {\n try {\n await session.abort();\n } catch {\n // Best-effort staging cleanup; a sweeper remains the final guard.\n }\n }\n }\n },\n });\n}\n\nfunction validateWriteRequest(input: {\n contentType: string;\n maxBytes: number;\n expectedByteSize?: number;\n expectedContentHash?: string;\n}): void {\n if (!Number.isSafeInteger(input.maxBytes) || input.maxBytes <= 0) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n if (\n input.expectedByteSize !== undefined &&\n (!Number.isSafeInteger(input.expectedByteSize) || input.expectedByteSize < 0)\n ) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n if (\n typeof input.contentType !== \"string\" ||\n input.contentType.length < 1 ||\n input.contentType.length > 256 ||\n /[\\u0000-\\u001f\\u007f]/.test(input.contentType)\n ) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n if (\n input.expectedContentHash !== undefined &&\n !/^sha256:[0-9a-f]{64}$/.test(input.expectedContentHash)\n ) {\n throw new BoundedObjectWriteError(\"invalid_request\");\n }\n}\n\nfunction validateOpaqueReference(value: string): void {\n if (\n typeof value !== \"string\" ||\n value.length < 1 ||\n value.length > 2048 ||\n value.trim() !== value ||\n /[\\u0000-\\u001f\\u007f]/.test(value)\n ) {\n throw new BoundedObjectWriteError(\"backend_failure\");\n }\n}\n\nasync function scrubWriteBackend<T>(operation: () => Promise<T>): Promise<T> {\n try {\n return await operation();\n } catch (error) {\n if (error instanceof BoundedObjectWriteError) throw error;\n throw new BoundedObjectWriteError(\"backend_failure\");\n }\n}\n\nfunction mapWriteFailure(error: unknown, signal: AbortSignal | undefined): BoundedObjectWriteError {\n if (error instanceof BoundedObjectWriteError) return error;\n if (signal?.aborted) return new BoundedObjectWriteError(\"aborted\");\n return new BoundedObjectWriteError(\"backend_failure\");\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new BoundedObjectWriteError(\"aborted\");\n}\n\nfunction writeErrorMessage(code: BoundedObjectWriteErrorCode): string {\n switch (code) {\n case \"aborted\":\n return \"Bounded object write was cancelled\";\n case \"backend_failure\":\n return \"Bounded object write failed\";\n case \"content_hash_mismatch\":\n return \"Bounded object digest does not match expected canonical bytes\";\n case \"invalid_request\":\n return \"Bounded object write request is invalid\";\n case \"readback_mismatch\":\n return \"Immutable object read-back verification failed\";\n case \"size_limit\":\n return \"Bounded object write exceeds the configured limit\";\n case \"truncated\":\n return \"Bounded object write length does not match expected canonical bytes\";\n }\n}\n","/**\n * Retry a load that treats `null` as \"not visible yet\".\n *\n * A resolved write is already durable. This helper is only for reads that\n * assume the object exists (a ready row, a client upload we are completing,\n * or a key we just persisted). Other errors fail immediately. Still missing\n * after the budget is a real miss.\n */\n\nexport const OBJECT_VISIBILITY_RETRY_DELAYS_MS = [50, 100, 200, 400, 400, 400, 400] as const;\n\nexport type RetryWhileMissingOptions = {\n signal?: AbortSignal;\n sleep?: (ms: number) => Promise<void>;\n delaysMs?: readonly number[];\n};\n\nexport async function retryWhileMissing<T>(\n load: () => Promise<T | null>,\n options: RetryWhileMissingOptions = {},\n): Promise<T | null> {\n const delays = options.delaysMs ?? OBJECT_VISIBILITY_RETRY_DELAYS_MS;\n const sleep = options.sleep ?? defaultSleep;\n for (let attempt = 0; ; attempt += 1) {\n throwIfAborted(options.signal);\n const value = await load();\n if (value !== null) return value;\n if (attempt >= delays.length) return null;\n await sleep(delays[attempt]!);\n throwIfAborted(options.signal);\n }\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n const error = signal.reason;\n throw error instanceof Error ? error : new Error(\"Object visibility wait was cancelled\");\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { chmod, mkdtemp, open, rm, type FileHandle } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport {\n createBoundedObjectReadPort,\n type BoundedObjectReadPort,\n type VersionedRangeObjectBackend,\n} from \"./bounded-object-read\";\nimport {\n createBoundedImmutableObjectWritePort,\n type BoundedImmutableObjectWritePort,\n type ImmutableContentAddressedWriteBackend,\n type ImmutableContentAddressedWriteSession,\n} from \"./bounded-object-write\";\nimport type { ObjectStorage } from \"./index\";\nimport { retryWhileMissing } from \"./retry-while-missing\";\n\nconst SNAPSHOT_KEY_PREFIX = \"editable-artifacts/snapshots/sha256/\";\n\nexport type ObjectStorageBoundedPorts = Readonly<{\n read: BoundedObjectReadPort;\n write: BoundedImmutableObjectWritePort;\n}>;\n\nexport type ObjectStorageBoundedPortsOptions = Readonly<{\n /** Static trusted namespace ending in `/sha256/`. */\n keyPrefix?: string;\n}>;\n\n/**\n * Bounded immutable snapshot ports over the standalone object-storage driver.\n * Reads are provider-version pinned. Writes use a canonical digest key and are\n * independently range-read and hashed by the shared verification layer.\n *\n * Provider uploads and readback are streaming. Staging uses one private local\n * file so content-addressed naming never requires retaining the object in RAM.\n * There is no whole-object fallback when a provider lacks these primitives.\n */\nexport function createObjectStorageBoundedPorts(\n storage: ObjectStorage,\n options: ObjectStorageBoundedPortsOptions = {},\n): ObjectStorageBoundedPorts {\n if (!storage.headObject || !storage.getObjectRange || !storage.putObjectStreamIfAbsent) {\n throw new Error(\"Object storage lacks streaming immutable create/versioned range primitives\");\n }\n const keyPrefix = validateKeyPrefix(options.keyPrefix ?? SNAPSHOT_KEY_PREFIX);\n const referenceHash = (reference: string) => hashForReference(reference, keyPrefix);\n const read = createBoundedObjectReadPort(versionedBackend(storage, referenceHash));\n const write = createBoundedImmutableObjectWritePort({\n backend: immutableWriteBackend(storage, keyPrefix),\n readback: read,\n });\n return Object.freeze({ read, write });\n}\n\nfunction versionedBackend(\n storage: ObjectStorage,\n hashForReferenceValue: (reference: string) => string,\n): VersionedRangeObjectBackend {\n const headObject = storage.headObject!;\n const getObjectRange = storage.getObjectRange!;\n return Object.freeze({\n async describe(input: Parameters<VersionedRangeObjectBackend[\"describe\"]>[0]) {\n const expectedHash = hashForReferenceValue(input.opaqueReference);\n throwIfAborted(input.signal);\n const head = await headObject(input.opaqueReference);\n throwIfAborted(input.signal);\n if (!head) return null;\n if (\n !Number.isSafeInteger(head.ContentLength) ||\n head.ContentLength! < 0 ||\n typeof head.VersionToken !== \"string\" ||\n head.VersionToken.length < 1 ||\n head.VersionToken.length > 2048 ||\n head.Metadata?.sha256 !== expectedHash\n ) {\n throw new Error(\"Immutable object metadata is invalid\");\n }\n return Object.freeze({\n byteSize: head.ContentLength!,\n versionToken: head.VersionToken,\n immutableReference: true as const,\n ...(head.ContentType ? { contentType: head.ContentType } : {}),\n });\n },\n async readRange(input: Parameters<VersionedRangeObjectBackend[\"readRange\"]>[0]) {\n hashForReferenceValue(input.opaqueReference);\n throwIfAborted(input.signal);\n const result = await getObjectRange({\n key: input.opaqueReference,\n start: input.start,\n endInclusive: input.endInclusive,\n expectedVersionToken: input.expectedVersionToken,\n });\n throwIfAborted(input.signal);\n if (!result) return null;\n return Object.freeze({\n bytes: result.bytes.slice(),\n versionToken: result.versionToken,\n });\n },\n });\n}\n\nfunction immutableWriteBackend(\n storage: ObjectStorage,\n keyPrefix: string,\n): ImmutableContentAddressedWriteBackend {\n return Object.freeze({\n async begin(\n input: Parameters<ImmutableContentAddressedWriteBackend[\"begin\"]>[0],\n ): Promise<ImmutableContentAddressedWriteSession> {\n validateContentType(input.contentType);\n throwIfAborted(input.signal);\n const stagingDirectory = await mkdtemp(join(tmpdir(), \"opengeni-artifact-write-\"));\n const stagingPath = join(stagingDirectory, \"payload\");\n let handle: FileHandle | null = null;\n try {\n await chmod(stagingDirectory, 0o700);\n throwIfAborted(input.signal);\n handle = await open(stagingPath, \"wx\", 0o600);\n } catch (error) {\n await rm(stagingDirectory, { recursive: true, force: true });\n throw error;\n }\n let byteSize = 0;\n let closed = false;\n let cleaned = false;\n const digest = createHash(\"sha256\");\n const cleanup = async () => {\n if (cleaned) return;\n cleaned = true;\n if (handle) {\n const closing = handle;\n handle = null;\n await closing.close().catch(() => undefined);\n }\n await rm(stagingDirectory, { recursive: true, force: true });\n };\n return {\n async write(chunk: Uint8Array, signal?: AbortSignal) {\n if (closed) throw new Error(\"Immutable write session is closed\");\n throwIfAborted(signal);\n if (!(chunk instanceof Uint8Array) || chunk.byteLength === 0) {\n throw new Error(\"Immutable write chunk is invalid\");\n }\n await writeAll(handle!, chunk, byteSize);\n digest.update(chunk);\n byteSize += chunk.byteLength;\n },\n async commit(commit: Parameters<ImmutableContentAddressedWriteSession[\"commit\"]>[0]) {\n if (closed) throw new Error(\"Immutable write session is closed\");\n closed = true;\n try {\n throwIfAborted(commit.signal);\n if (commit.contentType !== input.contentType || commit.byteSize !== byteSize) {\n throw new Error(\"Immutable write commit metadata changed\");\n }\n const contentHash = `sha256:${digest.digest(\"hex\")}`;\n if (contentHash !== commit.contentHash) {\n throw new Error(\"Immutable write digest changed\");\n }\n const opaqueReference = `${keyPrefix}${contentHash.slice(\"sha256:\".length)}`;\n const closing = handle!;\n handle = null;\n await closing.close();\n const existing = await storage.headObject!(opaqueReference);\n if (existing) {\n assertStoredObject(existing, byteSize, contentHash, input.contentType);\n } else {\n const created = await storage.putObjectStreamIfAbsent!({\n key: opaqueReference,\n contentType: input.contentType,\n chunks: fileChunks(stagingPath, byteSize, commit.signal),\n byteSize,\n sha256: contentHash,\n ...(commit.signal ? { signal: commit.signal } : {}),\n });\n if (!created) {\n const stored = await retryWhileMissing(\n async () => await storage.headObject!(opaqueReference),\n commit.signal ? { signal: commit.signal } : {},\n );\n if (!stored) throw new Error(\"Immutable content-addressed object is missing\");\n assertStoredObject(stored, byteSize, contentHash, input.contentType);\n }\n }\n throwIfAborted(commit.signal);\n return Object.freeze({ opaqueReference });\n } finally {\n await cleanup();\n }\n },\n async abort() {\n closed = true;\n byteSize = 0;\n await cleanup();\n },\n };\n },\n });\n}\n\nfunction assertStoredObject(\n head: Awaited<ReturnType<NonNullable<ObjectStorage[\"headObject\"]>>>,\n byteSize: number,\n contentHash: string,\n contentType: string,\n): void {\n if (\n !head ||\n head.ContentLength !== byteSize ||\n head.Metadata?.sha256 !== contentHash ||\n head.ContentType !== contentType ||\n typeof head.VersionToken !== \"string\" ||\n head.VersionToken.length < 1\n ) {\n throw new Error(\"Immutable content-addressed object conflicts with stored metadata\");\n }\n}\n\nfunction hashForReference(reference: string, keyPrefix: string): string {\n const match = new RegExp(`^${escapeRegExp(keyPrefix)}([0-9a-f]{64})$`, \"u\").exec(reference);\n if (!match) throw new Error(\"Immutable snapshot reference is malformed\");\n return `sha256:${match[1]}`;\n}\n\nfunction validateKeyPrefix(value: string): string {\n if (\n typeof value !== \"string\" ||\n !/^editable-artifacts\\/[a-z0-9/-]+\\/sha256\\/$/u.test(value) ||\n value.includes(\"//\") ||\n value.includes(\"..\")\n ) {\n throw new Error(\"Immutable object key prefix is invalid\");\n }\n return value;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n}\n\nfunction validateContentType(value: string): void {\n if (\n typeof value !== \"string\" ||\n value.length < 1 ||\n value.length > 256 ||\n /[\\u0000-\\u001f\\u007f]/u.test(value)\n ) {\n throw new Error(\"Immutable object content type is invalid\");\n }\n}\n\nasync function* fileChunks(\n path: string,\n expectedByteSize: number,\n signal: AbortSignal | undefined,\n): AsyncIterableIterator<Uint8Array> {\n const handle = await open(path, \"r\");\n try {\n const buffer = new Uint8Array(1024 * 1024);\n let offset = 0;\n while (offset < expectedByteSize) {\n throwIfAborted(signal);\n const length = Math.min(buffer.byteLength, expectedByteSize - offset);\n let filled = 0;\n while (filled < length) {\n const { bytesRead } = await handle.read(buffer, filled, length - filled, offset + filled);\n if (bytesRead <= 0) throw new Error(\"Immutable staging file was truncated\");\n filled += bytesRead;\n }\n offset += filled;\n yield buffer.slice(0, filled);\n }\n const extra = new Uint8Array(1);\n if ((await handle.read(extra, 0, 1, expectedByteSize)).bytesRead !== 0) {\n throw new Error(\"Immutable staging file exceeded its committed size\");\n }\n } finally {\n await handle.close();\n }\n}\n\nasync function writeAll(handle: FileHandle, bytes: Uint8Array, position: number): Promise<void> {\n let offset = 0;\n while (offset < bytes.byteLength) {\n const { bytesWritten } = await handle.write(\n bytes,\n offset,\n bytes.byteLength - offset,\n position + offset,\n );\n if (bytesWritten <= 0) throw new Error(\"Immutable staging write was truncated\");\n offset += bytesWritten;\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new Error(\"Object storage operation was cancelled\");\n}\n"],"mappings":"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","names":["throwIfAborted","throwIfAborted","createHash","throwIfAborted","createHash"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Retry a load that treats `null` as "not visible yet".
3
+ *
4
+ * A resolved write is already durable. This helper is only for reads that
5
+ * assume the object exists (a ready row, a client upload we are completing,
6
+ * or a key we just persisted). Other errors fail immediately. Still missing
7
+ * after the budget is a real miss.
8
+ */
9
+ export declare const OBJECT_VISIBILITY_RETRY_DELAYS_MS: readonly [50, 100, 200, 400, 400, 400, 400];
10
+ export type RetryWhileMissingOptions = {
11
+ signal?: AbortSignal;
12
+ sleep?: (ms: number) => Promise<void>;
13
+ delaysMs?: readonly number[];
14
+ };
15
+ export declare function retryWhileMissing<T>(load: () => Promise<T | null>, options?: RetryWhileMissingOptions): Promise<T | null>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/storage",
3
- "version": "0.2.96",
3
+ "version": "0.2.106-canary.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,7 +35,7 @@
35
35
  "@aws-sdk/s3-request-presigner": "^3.1044.0",
36
36
  "@azure/storage-blob": "^12.29.1",
37
37
  "@google-cloud/storage": "^7.19.0",
38
- "@opengeni/config": "^0.16.4",
39
- "@opengeni/contracts": "^1.0.1"
38
+ "@opengeni/config": "^0.19.1-canary.0",
39
+ "@opengeni/contracts": "^2.3.0-canary.0"
40
40
  }
41
41
  }
@@ -1,5 +1,10 @@
1
1
  import { createHash } from "node:crypto";
2
- import { MAX_BOUNDED_OBJECT_CHUNK_BYTES, type BoundedObjectReadPort } from "./bounded-object-read";
2
+ import {
3
+ BoundedObjectReadError,
4
+ MAX_BOUNDED_OBJECT_CHUNK_BYTES,
5
+ type BoundedObjectReadPort,
6
+ } from "./bounded-object-read";
7
+ import { retryWhileMissing } from "./retry-while-missing";
3
8
 
4
9
  export type BoundedObjectWriteErrorCode =
5
10
  | "aborted"
@@ -136,12 +141,25 @@ export function createBoundedImmutableObjectWritePort(input: {
136
141
  // returned to a caller as a successful publication candidate.
137
142
  throwIfAborted(request.signal);
138
143
 
139
- const reader = await input.readback.open({
140
- opaqueReference: promoted.opaqueReference,
141
- maxBytes: request.maxBytes,
142
- expectedByteSize: byteSize,
143
- ...(request.signal ? { signal: request.signal } : {}),
144
- });
144
+ const reader = await retryWhileMissing(
145
+ async () => {
146
+ try {
147
+ return await input.readback.open({
148
+ opaqueReference: promoted.opaqueReference,
149
+ maxBytes: request.maxBytes,
150
+ expectedByteSize: byteSize,
151
+ ...(request.signal ? { signal: request.signal } : {}),
152
+ });
153
+ } catch (error) {
154
+ if (error instanceof BoundedObjectReadError && error.code === "object_missing") {
155
+ return null;
156
+ }
157
+ throw error;
158
+ }
159
+ },
160
+ request.signal ? { signal: request.signal } : {},
161
+ );
162
+ if (!reader) throw new BoundedObjectWriteError("readback_mismatch");
145
163
  try {
146
164
  if (reader.contentType !== undefined && reader.contentType !== request.contentType) {
147
165
  throw new BoundedObjectWriteError("readback_mismatch");
package/src/index.ts CHANGED
@@ -28,6 +28,7 @@ import {
28
28
  export * from "./bounded-object-read";
29
29
  export * from "./bounded-object-write";
30
30
  export * from "./object-storage-bounded";
31
+ export * from "./retry-while-missing";
31
32
 
32
33
  export const MAX_SINGLE_PUT_SIZE_BYTES = 5_000_000_000;
33
34
  export const UPLOAD_URL_TTL_SECONDS = 15 * 60;
@@ -15,6 +15,7 @@ import {
15
15
  type ImmutableContentAddressedWriteSession,
16
16
  } from "./bounded-object-write";
17
17
  import type { ObjectStorage } from "./index";
18
+ import { retryWhileMissing } from "./retry-while-missing";
18
19
 
19
20
  const SNAPSHOT_KEY_PREFIX = "editable-artifacts/snapshots/sha256/";
20
21
 
@@ -169,7 +170,7 @@ function immutableWriteBackend(
169
170
  if (existing) {
170
171
  assertStoredObject(existing, byteSize, contentHash, input.contentType);
171
172
  } else {
172
- await storage.putObjectStreamIfAbsent!({
173
+ const created = await storage.putObjectStreamIfAbsent!({
173
174
  key: opaqueReference,
174
175
  contentType: input.contentType,
175
176
  chunks: fileChunks(stagingPath, byteSize, commit.signal),
@@ -177,9 +178,14 @@ function immutableWriteBackend(
177
178
  sha256: contentHash,
178
179
  ...(commit.signal ? { signal: commit.signal } : {}),
179
180
  });
180
- const stored = await storage.headObject!(opaqueReference);
181
- if (!stored) throw new Error("Immutable object was not visible after write");
182
- assertStoredObject(stored, byteSize, contentHash, input.contentType);
181
+ if (!created) {
182
+ const stored = await retryWhileMissing(
183
+ async () => await storage.headObject!(opaqueReference),
184
+ commit.signal ? { signal: commit.signal } : {},
185
+ );
186
+ if (!stored) throw new Error("Immutable content-addressed object is missing");
187
+ assertStoredObject(stored, byteSize, contentHash, input.contentType);
188
+ }
183
189
  }
184
190
  throwIfAborted(commit.signal);
185
191
  return Object.freeze({ opaqueReference });
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Retry a load that treats `null` as "not visible yet".
3
+ *
4
+ * A resolved write is already durable. This helper is only for reads that
5
+ * assume the object exists (a ready row, a client upload we are completing,
6
+ * or a key we just persisted). Other errors fail immediately. Still missing
7
+ * after the budget is a real miss.
8
+ */
9
+
10
+ export const OBJECT_VISIBILITY_RETRY_DELAYS_MS = [50, 100, 200, 400, 400, 400, 400] as const;
11
+
12
+ export type RetryWhileMissingOptions = {
13
+ signal?: AbortSignal;
14
+ sleep?: (ms: number) => Promise<void>;
15
+ delaysMs?: readonly number[];
16
+ };
17
+
18
+ export async function retryWhileMissing<T>(
19
+ load: () => Promise<T | null>,
20
+ options: RetryWhileMissingOptions = {},
21
+ ): Promise<T | null> {
22
+ const delays = options.delaysMs ?? OBJECT_VISIBILITY_RETRY_DELAYS_MS;
23
+ const sleep = options.sleep ?? defaultSleep;
24
+ for (let attempt = 0; ; attempt += 1) {
25
+ throwIfAborted(options.signal);
26
+ const value = await load();
27
+ if (value !== null) return value;
28
+ if (attempt >= delays.length) return null;
29
+ await sleep(delays[attempt]!);
30
+ throwIfAborted(options.signal);
31
+ }
32
+ }
33
+
34
+ function defaultSleep(ms: number): Promise<void> {
35
+ return new Promise((resolve) => {
36
+ setTimeout(resolve, ms);
37
+ });
38
+ }
39
+
40
+ function throwIfAborted(signal: AbortSignal | undefined): void {
41
+ if (signal?.aborted) {
42
+ const error = signal.reason;
43
+ throw error instanceof Error ? error : new Error("Object visibility wait was cancelled");
44
+ }
45
+ }