@opengeni/storage 0.2.126 → 0.2.127-canary.1
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 +14 -0
- package/dist/index.js +339 -1
- package/dist/index.js.map +1 -1
- package/dist/workspace-archive-spool.d.ts +28 -0
- package/package.json +3 -3
- package/src/index.ts +103 -0
- package/src/workspace-archive-spool.ts +308 -0
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/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: args.sha256 ? { sha256: args.sha256 } : undefined,\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: args.sha256 ? { sha256: args.sha256 } : undefined,\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 ...(args.sha256 ? { 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 ...(args.sha256 ? { 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 ...(args.sha256 ? { 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 ...(args.sha256 ? { 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"]}
|
|
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","../src/workspace-archive-spool.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 {\n uploadWorkspaceArchiveSpool,\n downloadWorkspaceArchiveSpool,\n WorkspaceArchiveStorageError,\n} from \"./workspace-archive-spool\";\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 /**\n * Unconditional authenticated upload from a bounded byte stream. May overwrite\n * an existing key; this is NOT an atomic create-only operation. Callers needing\n * write isolation must supply a fresh unique key and verify stored content.\n */\n putObjectStream?: (args: {\n key: string;\n contentType: string;\n chunks: AsyncIterable<Uint8Array>;\n byteSize: number;\n sha256?: string;\n signal?: AbortSignal;\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: args.sha256 ? { sha256: args.sha256 } : undefined,\n IfNoneMatch: \"*\",\n }),\n );\n return true;\n } catch (error) {\n if (isS3VersionMismatch(error)) return false;\n throw error;\n }\n },\n async putObjectStream(args) {\n const body = Readable.from(args.chunks, {\n objectMode: false,\n highWaterMark: INTERNAL_STREAM_BUFFER_BYTES,\n });\n // A producer error can leave the HTTP request waiting for its advertised\n // ContentLength. Abort this request explicitly; never abort the caller's\n // controller or rely on provider timeouts to settle the failed upload.\n const request = new AbortController();\n let producerFailed = false;\n let producerError: unknown;\n const onBodyError = (error: unknown) => {\n producerFailed = true;\n producerError = error;\n request.abort(error);\n };\n const onCallerAbort = () => request.abort(args.signal?.reason);\n body.once(\"error\", onBodyError);\n // Keep an error listener through asynchronous destruction, then release it.\n const detachBodyError = () => body.off(\"error\", onBodyError);\n body.once(\"close\", detachBodyError);\n args.signal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n if (args.signal?.aborted) onCallerAbort();\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: body,\n Metadata: args.sha256 ? { sha256: args.sha256 } : undefined,\n }),\n { abortSignal: request.signal },\n );\n if (producerFailed) throw producerError;\n } catch (error) {\n // The SDK commonly rejects with AbortError after our producer abort;\n // preserve the original integrity/source failure for its caller.\n if (producerFailed) throw producerError;\n throw error;\n } finally {\n args.signal?.removeEventListener(\"abort\", onCallerAbort);\n body.destroy();\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: args.sha256 ? { sha256: args.sha256 } : undefined,\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 ...(args.sha256 ? { 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 putObjectStream(args) {\n const destination = bucket.file(args.key).createWriteStream({\n resumable: false,\n contentType: args.contentType,\n highWaterMark: INTERNAL_STREAM_BUFFER_BYTES,\n ...(args.sha256 ? { metadata: { metadata: { sha256: args.sha256 } } } : {}),\n });\n const source = Readable.from(args.chunks, {\n objectMode: false,\n highWaterMark: INTERNAL_STREAM_BUFFER_BYTES,\n });\n if (args.signal) {\n await pipeline(source, destination, { signal: args.signal });\n } else {\n await pipeline(source, destination);\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 ...(args.sha256 ? { 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 ...(args.sha256 ? { 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 putObjectStream(args) {\n const blobClient = requestContainerClient.getBlockBlobClient(args.key);\n const source = Readable.from(args.chunks, {\n objectMode: false,\n highWaterMark: INTERNAL_STREAM_BUFFER_BYTES,\n });\n try {\n await blobClient.uploadStream(\n source,\n INTERNAL_STREAM_BUFFER_BYTES,\n INTERNAL_STREAM_CONCURRENCY,\n {\n blobHTTPHeaders: { blobContentType: args.contentType },\n ...(args.sha256 ? { metadata: { sha256: args.sha256 } } : {}),\n ...(args.signal ? { abortSignal: args.signal } : {}),\n },\n );\n } finally {\n source.destroy();\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 ...(args.sha256 ? { 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","import { createHash } from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport { chmod, mkdtemp, open, rm, type FileHandle } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { ObjectStorage } from \"./index\";\nimport { DEFAULT_BOUNDED_OBJECT_CHUNK_BYTES } from \"./bounded-object-read\";\n\n/** Structural runtime-compatible contract; storage must not depend on runtime. */\nexport type WorkspaceArchiveSpool = {\n path: string;\n byteSize: number;\n sha256: string;\n open: () => AsyncIterable<Uint8Array>;\n dispose: () => Promise<void>;\n};\n\n// Transfer granularity, not an archive size limit.\nconst CHUNK_BYTES = DEFAULT_BOUNDED_OBJECT_CHUNK_BYTES;\ntype ExpectedArchive = { bytes: number; sha256: string };\n\n/** Restore classification shared with runtime without importing runtime. */\nexport class WorkspaceArchiveStorageError extends Error {\n constructor(\n readonly code: \"archive_base64_invalid\" | \"archive_hash_mismatch\" | \"archive_hydration_failed\",\n message: string,\n readonly retryable: boolean,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = \"WorkspaceArchiveStorageError\";\n }\n}\n\n/**\n * Uploads at a caller-owned fresh unique key and independently verifies readback.\n * Unconditional PUT may overwrite: callers must never reuse published keys.\n * Never owns/disposes the input spool or deletes a failed/unpublished object.\n */\nexport async function uploadWorkspaceArchiveSpool(\n storage: ObjectStorage,\n key: string,\n spool: WorkspaceArchiveSpool,\n): Promise<void> {\n requireBoundedReads(storage);\n if (!storage.putObjectStream) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive storage unsupported: unconditional streaming upload required\",\n false,\n );\n }\n const expected = { bytes: spool.byteSize, sha256: spool.sha256 };\n validateExpected(expected);\n let validated = false;\n let streamFailed = false;\n let streamFailure: unknown;\n const chunks = (async function* () {\n const digest = createHash(\"sha256\");\n let bytes = 0;\n try {\n for await (const chunk of spool.open()) {\n if (!(chunk instanceof Uint8Array) || chunk.byteLength > expected.bytes - bytes) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hash_mismatch\",\n \"Workspace archive upload stream has invalid size\",\n false,\n );\n }\n bytes += chunk.byteLength;\n digest.update(chunk);\n yield chunk;\n }\n if (bytes !== expected.bytes || digest.digest(\"hex\") !== expected.sha256) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hash_mismatch\",\n \"Workspace archive upload stream digest or size mismatch\",\n false,\n );\n }\n validated = true;\n } catch (error) {\n streamFailed = true;\n streamFailure = error;\n throw error;\n }\n })();\n try {\n await storage.putObjectStream({\n key,\n contentType: \"application/x-tar\",\n chunks,\n byteSize: expected.bytes,\n sha256: expected.sha256,\n });\n if (!validated) {\n if (streamFailed) throw streamFailure;\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive upload provider did not completely consume and validate the stream\",\n false,\n );\n }\n // A successful PUT and SHA metadata are not proof of stored content.\n await verifyRanges(storage, key, expected);\n } catch (error) {\n const failure = streamFailed ? streamFailure : error;\n if (failure instanceof WorkspaceArchiveStorageError) throw failure;\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive upload or readback failed\",\n true,\n { cause: failure },\n );\n } finally {\n // Close an early-terminated provider's iterator without owning the spool.\n await chunks.return(undefined);\n }\n}\n\n/** Caller owns the returned private spool and must dispose it after use. */\nexport async function downloadWorkspaceArchiveSpool(\n storage: ObjectStorage,\n key: string,\n inputExpected: ExpectedArchive,\n): Promise<WorkspaceArchiveSpool> {\n const expected = { bytes: inputExpected.bytes, sha256: inputExpected.sha256 };\n requireBoundedReads(storage);\n validateExpected(expected);\n const directory = await mkdtemp(join(tmpdir(), \"opengeni-workspace-archive-\"));\n const path = join(directory, \"archive.tar\");\n let handle: FileHandle | undefined;\n try {\n await chmod(directory, 0o700);\n handle = await open(path, \"wx\", 0o600);\n await verifyRanges(storage, key, expected, async (chunk) => {\n let offset = 0;\n while (offset < chunk.byteLength) {\n const { bytesWritten } = await handle!.write(chunk, offset, chunk.byteLength - offset);\n if (bytesWritten <= 0)\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive spool write made no progress\",\n true,\n );\n offset += bytesWritten;\n }\n });\n await handle.close();\n handle = undefined;\n let disposed = false;\n return {\n path,\n byteSize: expected.bytes,\n sha256: expected.sha256,\n async *open() {\n if (disposed) throw new Error(\"Workspace archive spool is disposed\");\n const stream = createReadStream(path, { highWaterMark: CHUNK_BYTES });\n try {\n for await (const chunk of stream) yield chunk as Uint8Array;\n } finally {\n stream.destroy();\n }\n },\n async dispose() {\n disposed = true;\n await rm(directory, { recursive: true, force: true });\n },\n };\n } catch (error) {\n await handle?.close().catch(() => undefined);\n await rm(directory, { recursive: true, force: true });\n if (error instanceof WorkspaceArchiveStorageError) throw error;\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive download failed\",\n true,\n { cause: error },\n );\n }\n}\n\nfunction requireBoundedReads(storage: ObjectStorage): void {\n if (!storage.headObject || !storage.getObjectRange) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive storage unsupported: versioned head/range reads required\",\n false,\n );\n }\n}\n\nfunction validateExpected(expected: ExpectedArchive): void {\n if (\n !Number.isSafeInteger(expected.bytes) ||\n expected.bytes < 0 ||\n !/^[0-9a-f]{64}$/u.test(expected.sha256)\n ) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive expected size or SHA-256 is invalid\",\n false,\n );\n }\n}\n\nasync function verifyRanges(\n storage: ObjectStorage,\n key: string,\n expected: ExpectedArchive,\n consume?: (bytes: Uint8Array) => Promise<void>,\n): Promise<void> {\n const head = await storage.headObject!(key);\n if (!head)\n throw new WorkspaceArchiveStorageError(\n \"archive_base64_invalid\",\n \"Workspace archive object is missing\",\n false,\n );\n if (head.ContentLength !== expected.bytes)\n throw new WorkspaceArchiveStorageError(\n \"archive_hash_mismatch\",\n \"Workspace archive object size mismatch\",\n false,\n );\n const version = head.VersionToken;\n if (typeof version !== \"string\" || version.length === 0 || version.length > 2048) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive storage unsupported: valid object version token required\",\n false,\n );\n }\n const digest = createHash(\"sha256\");\n let bytes = 0;\n while (bytes < expected.bytes) {\n const length = Math.min(CHUNK_BYTES, expected.bytes - bytes);\n const result = await storage.getObjectRange!({\n key,\n start: bytes,\n endInclusive: bytes + length - 1,\n expectedVersionToken: version,\n });\n if (!result) {\n // Adapters also return null for failed If-Match/generation reads. Do not\n // classify replacement as permanent loss or retry without a version pin.\n const current = await storage.headObject!(key);\n if (!current) {\n throw new WorkspaceArchiveStorageError(\n \"archive_base64_invalid\",\n \"Workspace archive object is missing during range read\",\n false,\n );\n }\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n current.VersionToken !== version\n ? \"Workspace archive object version changed\"\n : \"Workspace archive pinned range is temporarily unavailable\",\n true,\n );\n }\n if (result.versionToken !== version)\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive object version changed\",\n true,\n );\n if (!(result.bytes instanceof Uint8Array) || result.bytes.byteLength !== length) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hash_mismatch\",\n \"Workspace archive object range is truncated or has invalid size\",\n false,\n );\n }\n digest.update(result.bytes);\n await consume?.(result.bytes);\n bytes += result.bytes.byteLength;\n }\n const finalHead = await storage.headObject!(key);\n if (!finalHead)\n throw new WorkspaceArchiveStorageError(\n \"archive_base64_invalid\",\n \"Workspace archive object is missing after range read\",\n false,\n );\n if (finalHead.VersionToken !== version) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hydration_failed\",\n \"Workspace archive object version changed\",\n true,\n );\n }\n if (finalHead.ContentLength !== expected.bytes) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hash_mismatch\",\n \"Workspace archive object size changed\",\n false,\n );\n }\n if (bytes !== expected.bytes || digest.digest(\"hex\") !== expected.sha256) {\n throw new WorkspaceArchiveStorageError(\n \"archive_hash_mismatch\",\n \"Workspace archive object digest or size mismatch\",\n false,\n );\n }\n}\n"],"mappings":"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","names":["throwIfAborted","throwIfAborted","createHash","throwIfAborted","createHash","createHash","chmod","mkdtemp","open","rm","tmpdir","join","createHash","mkdtemp","join","tmpdir","chmod","open","rm"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ObjectStorage } from "./index.js";
|
|
2
|
+
/** Structural runtime-compatible contract; storage must not depend on runtime. */
|
|
3
|
+
export type WorkspaceArchiveSpool = {
|
|
4
|
+
path: string;
|
|
5
|
+
byteSize: number;
|
|
6
|
+
sha256: string;
|
|
7
|
+
open: () => AsyncIterable<Uint8Array>;
|
|
8
|
+
dispose: () => Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
type ExpectedArchive = {
|
|
11
|
+
bytes: number;
|
|
12
|
+
sha256: string;
|
|
13
|
+
};
|
|
14
|
+
/** Restore classification shared with runtime without importing runtime. */
|
|
15
|
+
export declare class WorkspaceArchiveStorageError extends Error {
|
|
16
|
+
readonly code: "archive_base64_invalid" | "archive_hash_mismatch" | "archive_hydration_failed";
|
|
17
|
+
readonly retryable: boolean;
|
|
18
|
+
constructor(code: "archive_base64_invalid" | "archive_hash_mismatch" | "archive_hydration_failed", message: string, retryable: boolean, options?: ErrorOptions);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Uploads at a caller-owned fresh unique key and independently verifies readback.
|
|
22
|
+
* Unconditional PUT may overwrite: callers must never reuse published keys.
|
|
23
|
+
* Never owns/disposes the input spool or deletes a failed/unpublished object.
|
|
24
|
+
*/
|
|
25
|
+
export declare function uploadWorkspaceArchiveSpool(storage: ObjectStorage, key: string, spool: WorkspaceArchiveSpool): Promise<void>;
|
|
26
|
+
/** Caller owns the returned private spool and must dispose it after use. */
|
|
27
|
+
export declare function downloadWorkspaceArchiveSpool(storage: ObjectStorage, key: string, inputExpected: ExpectedArchive): Promise<WorkspaceArchiveSpool>;
|
|
28
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/storage",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.127-canary.1",
|
|
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": "^1.1.1",
|
|
39
|
-
"@opengeni/contracts": "^3.0.1"
|
|
38
|
+
"@opengeni/config": "^1.1.2-canary.1",
|
|
39
|
+
"@opengeni/contracts": "^3.0.2-canary.1"
|
|
40
40
|
}
|
|
41
41
|
}
|