@modainteract/moda-interact-shared 5.11.1 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-5BIYNMMT.js → chunk-JWX4ZVKK.js} +2 -101
- package/dist/chunk-JWX4ZVKK.js.map +1 -0
- package/dist/chunk-SOAGFZ7A.js +184 -0
- package/dist/chunk-SOAGFZ7A.js.map +1 -0
- package/dist/chunk-VJNXWDA5.js +105 -0
- package/dist/chunk-VJNXWDA5.js.map +1 -0
- package/dist/commerce/index.js +6 -4
- package/dist/commerce/index.js.map +1 -1
- package/dist/commerce/presentation/index.d.ts +5 -78
- package/dist/commerce/presentation/index.js +37 -87
- package/dist/commerce/presentation/index.js.map +1 -1
- package/dist/commerce/presentation/node/index.d.ts +186 -0
- package/dist/commerce/presentation/node/index.js +976 -0
- package/dist/commerce/presentation/node/index.js.map +1 -0
- package/dist/commerce/runner/index.js +6 -4
- package/dist/commerce/runner/index.js.map +1 -1
- package/dist/wrapper-contracts-BcxDQPon.d.ts +243 -0
- package/package.json +9 -2
- package/dist/chunk-5BIYNMMT.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commerce/presentation/node/contracts.ts","../../../../src/commerce/presentation/node/network-policy.ts","../../../../src/commerce/presentation/node/safe-fetch.ts","../../../../src/commerce/presentation/node/image-transformer.ts","../../../../src/commerce/presentation/node/metadata-verifier.ts","../../../../src/commerce/presentation/node/product-image-transformer.ts","../../../../src/commerce/presentation/node/r2-writer.ts","../../../../src/commerce/presentation/node/public-probe.ts","../../../../src/commerce/presentation/node/product-image.ts"],"sourcesContent":["/** ARCH-049-BACKGROUND-001: one untrusted source in, one verified immutable image out. */\nexport const SHOP_BRAND_CANVAS = Object.freeze({ width: 1125, height: 600 });\nexport const SHOP_BRAND_MAX_SOURCE_BYTES = 10 * 1024 * 1024;\nexport const SHOP_BRAND_MAX_OUTPUT_BYTES = 5 * 1024 * 1024;\nexport const SHOP_BRAND_TARGET_OUTPUT_BYTES = 1024 * 1024;\nexport const SHOP_BRAND_MAX_INPUT_PIXELS = 40_000_000;\n\nexport type ShopBrandImageRole = \"LOGO\" | \"SQUARE_LOGO\" | \"COVER_IMAGE\";\nexport type ShopBrandImageMime = \"image/jpeg\" | \"image/png\";\n\nexport type ShopBrandMediaErrorCode =\n | \"INVALID_INPUT\" | \"UNSAFE_SOURCE\" | \"DNS_FAILURE\" | \"DNS_TEMPORARY_FAILURE\"\n | \"SOURCE_TIMEOUT\" | \"SOURCE_HTTP_FAILURE\" | \"SOURCE_UNAVAILABLE\"\n | \"SOURCE_TOO_LARGE\" | \"UNSUPPORTED_ENCODING\" | \"INVALID_IMAGE\"\n | \"INPUT_PIXELS_EXCEEDED\" | \"OUTPUT_TOO_LARGE\" | \"OUTPUT_VERIFICATION_FAILED\"\n | \"R2_CONFIGURATION_INVALID\" | \"R2_UNAVAILABLE\" | \"R2_OBJECT_MISMATCH\"\n | \"PUBLIC_MEDIA_UNAVAILABLE\" | \"PUBLIC_MEDIA_MISMATCH\"\n | \"UNEXPECTED_FAILURE\";\n\n/** The message is a bounded code, not a provider exception or a URL containing credentials. */\nexport class ShopBrandMediaError extends Error {\n constructor(readonly code: ShopBrandMediaErrorCode, readonly retryable = false,\n readonly providerMessage?: string) {\n super(code);\n this.name = \"ShopBrandMediaError\";\n }\n}\n\n/** Bounded diagnostic provenance for provider/library failures; never retain a source URL or common secrets. */\nexport function boundedMediaProviderMessage(error: unknown): string | undefined {\n const raw = error instanceof Error ? error.message : typeof error === \"string\" ? error : undefined;\n if (!raw) return undefined;\n const message = [...raw].map((character) => {\n const code = character.codePointAt(0)!;\n return code <= 0x1f || code === 0x7f ? \" \" : character;\n }).join(\"\")\n .replace(/\\bhttps?:\\/\\/[^\\s,;]+/gi, \"[URL REDACTED]\")\n .replace(/(authorization\\s*[:=]\\s*)(?:bearer\\s+)?[^\\s,;]+/gi, \"$1[REDACTED]\")\n .replace(/\\b(bearer\\s+)[A-Za-z0-9._~+/-]+=*/gi, \"$1[REDACTED]\")\n .replace(/((?:access.?key(?:.?id)?|secret.?key|session.?token|security.?token|token|password|signature|credential|api.?key)\\s*[:=]\\s*)[^\\s,;&\"'<>]+/gi, \"$1[REDACTED]\")\n .replace(/[\\w.+-]+@[\\w.-]+\\.[A-Za-z]{2,}/g, \"[EMAIL REDACTED]\")\n .replace(/\\b(?:\\+?\\d[\\d ().-]{7,}\\d)\\b/g, \"[PHONE REDACTED]\")\n .replace(/\\s+/g, \" \").trim().slice(0, 300);\n return message || undefined;\n}\n\nexport interface VerifiedBrandImage {\n bytes: Buffer;\n contentType: ShopBrandImageMime;\n width: number;\n height: number;\n sizeBytes: number;\n contentSha256: string;\n}\n\n\nexport interface FetchedBrandSource {\n bytes: Buffer;\n /** The response's declared type; never trusted for decoding. */\n declaredContentType: string | null;\n}\n\nexport interface SafeFetcher {\n fetch(url: string, signal?: AbortSignal): Promise<FetchedBrandSource>;\n}\n\nexport interface ImageTransformer {\n transform(bytes: Buffer, role: ShopBrandImageRole): Promise<VerifiedBrandImage>;\n}\n\n\nexport interface PublicMediaProbe {\n verify(input: { url: string; image: VerifiedBrandImage }, signal?: AbortSignal): Promise<void>;\n}\n\n\n/** Host-supplied validated credentials; Shared performs no configuration lookup. */\nexport type ShopBrandR2Credentials = Readonly<{ endpoint: string; accessKeyId: string; secretAccessKey: string }>;\n","import { lookup as dnsLookup } from \"node:dns/promises\";\nimport type { RequestOptions } from \"node:https\";\nimport { BlockList, isIP } from \"node:net\";\n\nexport const MERCHANT_KNOWLEDGE_ACQUISITION_ERROR_CODES = [\n \"INVALID_URL\",\n \"DENIED_DESTINATION\",\n \"DNS_NO_ADDRESSES\",\n \"DNS_TEMPORARY_FAILURE\",\n \"DNS_FAILURE\",\n \"TOO_MANY_REDIRECTS\",\n \"INVALID_REDIRECT\",\n \"REQUEST_DEADLINE\",\n \"CONNECTION_PEER_MISMATCH\",\n \"HTTP_STATUS_TRANSIENT\",\n \"HTTP_STATUS_PERMANENT\",\n \"UNSUPPORTED_MEDIA_TYPE\",\n \"UNSUPPORTED_CONTENT_ENCODING\",\n \"BODY_TOO_LARGE\",\n \"RESPONSE_READ_FAILED\",\n] as const;\n\nexport type MerchantKnowledgeAcquisitionErrorCode =\n (typeof MERCHANT_KNOWLEDGE_ACQUISITION_ERROR_CODES)[number];\n\nexport class MerchantKnowledgeAcquisitionError extends Error {\n constructor(\n readonly code: MerchantKnowledgeAcquisitionErrorCode,\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"MerchantKnowledgeAcquisitionError\";\n }\n}\n\nexport interface MerchantKnowledgeResolvedAddress {\n address: string;\n family: 4 | 6;\n}\n\nexport type MerchantKnowledgeResolver = (\n hostname: string,\n) => Promise<readonly MerchantKnowledgeResolvedAddress[]>;\n\nconst GLOBAL_IPV4 = new BlockList();\nGLOBAL_IPV4.addSubnet(\"0.0.0.0\", 0, \"ipv4\");\n\nconst PUBLIC_IPV6_ALLOCATION_CIDRS: readonly [string, number][] = [\n [\"2001:200::\", 23],\n [\"2001:400::\", 23],\n [\"2001:600::\", 23],\n [\"2001:800::\", 22],\n [\"2001:c00::\", 23],\n [\"2001:e00::\", 23],\n [\"2001:1200::\", 23],\n [\"2001:1400::\", 22],\n [\"2001:1800::\", 23],\n [\"2001:1a00::\", 23],\n [\"2001:1c00::\", 22],\n [\"2001:2000::\", 19],\n [\"2001:4000::\", 23],\n [\"2001:4200::\", 23],\n [\"2001:4400::\", 23],\n [\"2001:4600::\", 23],\n [\"2001:4800::\", 23],\n [\"2001:4a00::\", 23],\n [\"2001:4c00::\", 23],\n [\"2001:5000::\", 20],\n [\"2001:8000::\", 19],\n [\"2001:a000::\", 20],\n [\"2001:b000::\", 20],\n [\"2003::\", 18],\n [\"2400::\", 12],\n [\"2410::\", 12],\n [\"2600::\", 12],\n [\"2610::\", 23],\n [\"2620::\", 23],\n [\"2630::\", 12],\n [\"2800::\", 12],\n [\"2a00::\", 12],\n [\"2a10::\", 12],\n [\"2c00::\", 12],\n];\nconst PUBLIC_IPV6_ALLOCATIONS = new BlockList();\nfor (const [network, prefix] of PUBLIC_IPV6_ALLOCATION_CIDRS) {\n PUBLIC_IPV6_ALLOCATIONS.addSubnet(network, prefix, \"ipv6\");\n}\n\nconst NON_PUBLIC_SPECIAL_USE_CIDRS: readonly [string, number, \"ipv4\" | \"ipv6\"][] = [\n [\"0.0.0.0\", 8, \"ipv4\"],\n [\"10.0.0.0\", 8, \"ipv4\"],\n [\"100.64.0.0\", 10, \"ipv4\"],\n [\"127.0.0.0\", 8, \"ipv4\"],\n [\"169.254.0.0\", 16, \"ipv4\"],\n [\"172.16.0.0\", 12, \"ipv4\"],\n [\"192.0.0.0\", 24, \"ipv4\"],\n [\"192.0.2.0\", 24, \"ipv4\"],\n [\"192.31.196.0\", 24, \"ipv4\"],\n [\"192.52.193.0\", 24, \"ipv4\"],\n [\"192.88.99.0\", 24, \"ipv4\"],\n [\"192.168.0.0\", 16, \"ipv4\"],\n [\"192.175.48.0\", 24, \"ipv4\"],\n [\"198.18.0.0\", 15, \"ipv4\"],\n [\"198.51.100.0\", 24, \"ipv4\"],\n [\"203.0.113.0\", 24, \"ipv4\"],\n [\"224.0.0.0\", 4, \"ipv4\"],\n [\"240.0.0.0\", 4, \"ipv4\"],\n [\"64:ff9b::\", 96, \"ipv6\"],\n [\"64:ff9b:1::\", 48, \"ipv6\"],\n [\"100::\", 64, \"ipv6\"],\n [\"2001::\", 23, \"ipv6\"],\n [\"2001:db8::\", 32, \"ipv6\"],\n [\"2002::\", 16, \"ipv6\"],\n [\"2620:4f:8000::\", 48, \"ipv6\"],\n [\"3fff::\", 20, \"ipv6\"],\n [\"5f00::\", 16, \"ipv6\"],\n];\nconst NON_PUBLIC_SPECIAL_USE = new BlockList();\nfor (const [network, prefix, family] of NON_PUBLIC_SPECIAL_USE_CIDRS) {\n NON_PUBLIC_SPECIAL_USE.addSubnet(network, prefix, family);\n}\nconst IPV4_MAPPED_IPV6 = new BlockList();\nIPV4_MAPPED_IPV6.addSubnet(\"::ffff:0:0\", 96, \"ipv6\");\n\nconst TEMPORARY_DNS_CODES = new Set([\"EAI_AGAIN\", \"ETIMEOUT\", \"ETIMEDOUT\"]);\n\nfunction errorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) {\n return undefined;\n }\n return typeof error.code === \"string\" ? error.code : undefined;\n}\n\nfunction hostnameWithoutBrackets(hostname: string): string {\n return hostname.startsWith(\"[\") && hostname.endsWith(\"]\")\n ? hostname.slice(1, -1)\n : hostname;\n}\n\nexport function normalizeIpAddress(address: string): string | null {\n const family = isIP(address);\n if (family === 4) return address;\n if (family !== 6) return null;\n\n try {\n const canonical = new URL(`http://[${address}]/`).hostname.slice(1, -1);\n if (!IPV4_MAPPED_IPV6.check(canonical, \"ipv6\")) return canonical;\n const groups = canonical.split(\":\");\n const first = Number.parseInt(groups.at(-2)!, 16);\n const second = Number.parseInt(groups.at(-1)!, 16);\n return [first >> 8, first & 255, second >> 8, second & 255].join(\".\");\n } catch {\n return null;\n }\n}\n\nexport function isPublicIpAddress(address: string): boolean {\n if (address.includes(\"%\")) return false;\n const family = isIP(address);\n if (family === 0) return false;\n if (family === 6 && IPV4_MAPPED_IPV6.check(address, \"ipv6\")) {\n const normalized = normalizeIpAddress(address);\n return normalized !== null && isPublicIpAddress(normalized);\n }\n const allowed = family === 4\n ? GLOBAL_IPV4.check(address, \"ipv4\")\n : PUBLIC_IPV6_ALLOCATIONS.check(address, \"ipv6\");\n return allowed && !NON_PUBLIC_SPECIAL_USE.check(address, family === 4 ? \"ipv4\" : \"ipv6\");\n}\n\nexport async function resolveAllDnsAnswers(\n hostname: string,\n): Promise<readonly MerchantKnowledgeResolvedAddress[]> {\n const addresses = await dnsLookup(hostname, { all: true, verbatim: true });\n return addresses.map(({ address, family }) => ({\n address,\n family: family === 4 ? 4 : 6,\n }));\n}\n\nexport async function resolveAndValidateDestination(\n hostnameInput: string,\n resolver: MerchantKnowledgeResolver = resolveAllDnsAnswers,\n): Promise<MerchantKnowledgeResolvedAddress> {\n const hostname = hostnameWithoutBrackets(hostnameInput);\n const literalFamily = isIP(hostname);\n\n if (literalFamily !== 0) {\n if (!isPublicIpAddress(hostname)) {\n throw new MerchantKnowledgeAcquisitionError(\n \"DENIED_DESTINATION\",\n \"The requested destination is not globally routable.\",\n );\n }\n return {\n address: normalizeIpAddress(hostname) ?? hostname,\n family: literalFamily as 4 | 6,\n };\n }\n\n let answers: readonly MerchantKnowledgeResolvedAddress[];\n try {\n answers = await resolver(hostname);\n } catch (error) {\n const code = errorCode(error);\n if (code && TEMPORARY_DNS_CODES.has(code)) {\n throw new MerchantKnowledgeAcquisitionError(\n \"DNS_TEMPORARY_FAILURE\",\n \"Temporary DNS resolution failure.\",\n true,\n );\n }\n throw new MerchantKnowledgeAcquisitionError(\n \"DNS_FAILURE\",\n \"DNS resolution failed.\",\n );\n }\n\n if (answers.length === 0) {\n throw new MerchantKnowledgeAcquisitionError(\n \"DNS_NO_ADDRESSES\",\n \"The destination has no DNS addresses.\",\n );\n }\n\n const validated = answers.map(({ address, family }) => {\n const actualFamily = isIP(address);\n if (\n (family !== 4 && family !== 6) ||\n actualFamily !== family ||\n !isPublicIpAddress(address)\n ) {\n throw new MerchantKnowledgeAcquisitionError(\n \"DENIED_DESTINATION\",\n \"The requested destination is not globally routable.\",\n );\n }\n return {\n address,\n family,\n } satisfies MerchantKnowledgeResolvedAddress;\n });\n\n validated.sort(\n (left, right) =>\n left.family - right.family ||\n (left.address < right.address ? -1 : left.address > right.address ? 1 : 0),\n );\n return validated[0]!;\n}\n\nexport function addressesMatch(left: string, right: string): boolean {\n const normalizedLeft = normalizeIpAddress(left);\n const normalizedRight = normalizeIpAddress(right);\n return normalizedLeft !== null && normalizedLeft === normalizedRight;\n}\n\nexport function createPinnedLookup(\n address: MerchantKnowledgeResolvedAddress,\n): NonNullable<RequestOptions[\"lookup\"]> {\n return (_hostname, options, callback) => {\n if (options.all) {\n callback(null, [{ address: address.address, family: address.family }]);\n return;\n }\n callback(null, address.address, address.family);\n };\n}","import https from \"node:https\";\nimport type { IncomingHttpHeaders } from \"node:http\";\nimport { isIP } from \"node:net\";\nimport type { Readable } from \"node:stream\";\nimport {\n addressesMatch, createPinnedLookup, MerchantKnowledgeAcquisitionError,\n resolveAllDnsAnswers, resolveAndValidateDestination,\n type MerchantKnowledgeResolvedAddress, type MerchantKnowledgeResolver,\n} from \"./network-policy.js\";\nimport {\n SHOP_BRAND_MAX_SOURCE_BYTES, ShopBrandMediaError, boundedMediaProviderMessage,\n type FetchedBrandSource, type SafeFetcher,\n} from \"./contracts.js\";\n\nconst MAX_URL_LENGTH = 2048;\nconst MAX_REDIRECTS = 3;\nconst DEADLINE_MS = 10_000;\nconst REDIRECTS = new Set([301, 302, 303, 307, 308]);\nconst TRANSIENT_HTTP = new Set([408, 425, 429, 500, 502, 503, 504]);\nconst TRANSIENT_NETWORK = new Set([\"ECONNRESET\", \"EAI_AGAIN\", \"ETIMEDOUT\", \"ETIMEOUT\", \"ECONNREFUSED\", \"ENETUNREACH\"]);\nconst REQUEST_HEADERS = Object.freeze({\n Accept: \"image/avif,image/webp,image/png,image/jpeg,image/gif,image/svg+xml,*/*;q=0.2\",\n \"Accept-Encoding\": \"identity\",\n \"User-Agent\": \"ModaInteract-ShopBrandMedia/1.0\",\n});\n\nexport type PinnedImageRequest = Readonly<{\n hostname: string;\n path: string;\n address: MerchantKnowledgeResolvedAddress;\n servername?: string;\n headers: typeof REQUEST_HEADERS;\n}>;\nexport interface ImageHttpResponse {\n statusCode: number;\n headers: IncomingHttpHeaders;\n body: Readable;\n peerAddress: string;\n}\nexport type PinnedImageHttpRequest = (input: PinnedImageRequest, signal: AbortSignal) => Promise<ImageHttpResponse>;\nexport interface SafeImageFetcherOptions {\n resolveAll?: MerchantKnowledgeResolver;\n request?: PinnedImageHttpRequest;\n /** Narrow deployments can prohibit redirects and lower the byte ceiling. */\n maxRedirects?: number;\n maxBytes?: number;\n}\n\nfunction safeUrl(input: string): URL {\n if (typeof input !== \"string\" || input.length > MAX_URL_LENGTH || /[\\s\\p{Cc}]/u.test(input)) {\n throw new ShopBrandMediaError(\"UNSAFE_SOURCE\");\n }\n try {\n const url = new URL(input);\n if (url.protocol !== \"https:\" || url.username || url.password || url.hash ||\n (url.port && url.port !== \"443\") || !url.hostname) {\n throw new Error(\"unapproved-url\");\n }\n return url;\n } catch {\n throw new ShopBrandMediaError(\"UNSAFE_SOURCE\");\n }\n}\nfunction header(headers: IncomingHttpHeaders, name: string): string | undefined {\n const value = headers[name];\n return typeof value === \"string\" ? value : undefined;\n}\nfunction networkCode(error: unknown): string | undefined {\n return error !== null && typeof error === \"object\" && \"code\" in error && typeof error.code === \"string\"\n ? error.code : undefined;\n}\nfunction sanitiseNetworkError(error: unknown): ShopBrandMediaError {\n if (error instanceof ShopBrandMediaError) return error;\n if (error instanceof MerchantKnowledgeAcquisitionError) {\n if (error.code === \"DENIED_DESTINATION\") return new ShopBrandMediaError(\"UNSAFE_SOURCE\", false, error.code);\n if (error.code === \"DNS_TEMPORARY_FAILURE\") return new ShopBrandMediaError(\"DNS_TEMPORARY_FAILURE\", true, error.code);\n return new ShopBrandMediaError(\"DNS_FAILURE\", error.retryable, error.code);\n }\n const code = networkCode(error);\n return new ShopBrandMediaError(\"SOURCE_UNAVAILABLE\", TRANSIENT_NETWORK.has(code ?? \"\"),\n boundedMediaProviderMessage(error));\n}\nfunction cancelled(signal: AbortSignal): ShopBrandMediaError {\n return signal.reason instanceof ShopBrandMediaError\n ? signal.reason : new ShopBrandMediaError(\"SOURCE_TIMEOUT\", true);\n}\n/** Ensure non-cooperative injected requests/resolvers cannot extend the single total deadline. */\nfunction deadline<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) return Promise.reject(cancelled(signal));\n return new Promise((resolve, reject) => {\n const onAbort = () => reject(cancelled(signal));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n promise.then((value) => { signal.removeEventListener(\"abort\", onAbort); resolve(value); },\n (error: unknown) => { signal.removeEventListener(\"abort\", onAbort); reject(error); });\n });\n}\n\nfunction pinnedHttpsRequest(input: PinnedImageRequest, signal: AbortSignal): Promise<ImageHttpResponse> {\n return new Promise((resolve, reject) => {\n let settled = false;\n const fail = (error: Error) => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n const request = https.request({\n hostname: input.hostname,\n port: 443,\n path: input.path,\n method: \"GET\",\n headers: input.headers,\n lookup: createPinnedLookup(input.address),\n agent: false,\n minVersion: \"TLSv1.2\",\n signal,\n ...(input.servername ? { servername: input.servername } : {}),\n }, (response) => {\n const peerAddress = response.socket.remoteAddress;\n if (!peerAddress || !addressesMatch(peerAddress, input.address.address)) {\n response.destroy();\n fail(new ShopBrandMediaError(\"UNSAFE_SOURCE\"));\n request.destroy();\n return;\n }\n if (settled) { response.destroy(); return; }\n settled = true;\n resolve({ statusCode: response.statusCode ?? 0, headers: response.headers,\n body: response, peerAddress });\n });\n request.once(\"socket\", (socket) => {\n socket.once(\"secureConnect\", () => {\n if (!socket.remoteAddress || !addressesMatch(socket.remoteAddress, input.address.address)) {\n fail(new ShopBrandMediaError(\"UNSAFE_SOURCE\"));\n request.destroy();\n }\n });\n });\n request.once(\"error\", fail);\n request.end();\n });\n}\n\nasync function boundedBody(response: ImageHttpResponse, signal: AbortSignal, maxBytes: number): Promise<Buffer> {\n const rawSize = header(response.headers, \"content-length\");\n if (rawSize !== undefined && (!/^\\d+$/.test(rawSize) || Number(rawSize) > maxBytes)) {\n response.body.destroy();\n throw new ShopBrandMediaError(\"SOURCE_TOO_LARGE\");\n }\n const encoding = header(response.headers, \"content-encoding\");\n // No transparent decompression: avoid another inflation stage before image pixel checks.\n if (encoding !== undefined && encoding.toLowerCase().trim() !== \"identity\") {\n response.body.destroy();\n throw new ShopBrandMediaError(\"UNSUPPORTED_ENCODING\");\n }\n const chunks: Buffer[] = [];\n let length = 0;\n const onAbort = () => response.body.destroy(cancelled(signal));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n try {\n for await (const chunk of response.body) {\n if (signal.aborted) throw cancelled(signal);\n const bytes: Buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as Uint8Array);\n length += bytes.length;\n if (length > maxBytes) {\n response.body.destroy();\n throw new ShopBrandMediaError(\"SOURCE_TOO_LARGE\");\n }\n chunks.push(bytes);\n }\n if (signal.aborted) throw cancelled(signal);\n return Buffer.concat(chunks, length);\n } catch (error) {\n if (signal.aborted) throw cancelled(signal);\n if (error instanceof ShopBrandMediaError) throw error;\n throw sanitiseNetworkError(error);\n } finally {\n signal.removeEventListener(\"abort\", onAbort);\n }\n}\n\nexport function createSafeImageFetcher(options: SafeImageFetcherOptions = {}): SafeFetcher {\n const resolveAll = options.resolveAll ?? resolveAllDnsAnswers;\n const request = options.request ?? pinnedHttpsRequest;\n const maxRedirects = options.maxRedirects ?? MAX_REDIRECTS;\n const maxBytes = options.maxBytes ?? SHOP_BRAND_MAX_SOURCE_BYTES;\n return {\n async fetch(sourceUrl: string, externalSignal?: AbortSignal): Promise<FetchedBrandSource> {\n const controller = new AbortController();\n const abortFromCaller = () => controller.abort(externalSignal?.reason);\n if (externalSignal?.aborted) abortFromCaller();\n else externalSignal?.addEventListener(\"abort\", abortFromCaller, { once: true });\n const timer = setTimeout(() => controller.abort(new ShopBrandMediaError(\"SOURCE_TIMEOUT\", true)), DEADLINE_MS);\n try {\n let next = safeUrl(sourceUrl);\n for (let redirects = 0; ; redirects += 1) {\n const host = next.hostname.startsWith(\"[\") ? next.hostname.slice(1, -1) : next.hostname;\n let address: MerchantKnowledgeResolvedAddress;\n try {\n address = await deadline(resolveAndValidateDestination(next.hostname, resolveAll), controller.signal);\n } catch (error) { throw sanitiseNetworkError(error); }\n const input: PinnedImageRequest = {\n hostname: host, path: `${next.pathname}${next.search}`, address, headers: REQUEST_HEADERS,\n ...(isIP(host) === 0 ? { servername: host } : {}),\n };\n let response: ImageHttpResponse;\n try { response = await deadline(request(input, controller.signal), controller.signal); }\n catch (error) { throw sanitiseNetworkError(error); }\n if (!addressesMatch(response.peerAddress, address.address)) {\n response.body.destroy();\n throw new ShopBrandMediaError(\"UNSAFE_SOURCE\");\n }\n if (REDIRECTS.has(response.statusCode)) {\n response.body.destroy();\n if (redirects >= maxRedirects) throw new ShopBrandMediaError(\"UNSAFE_SOURCE\");\n const location = header(response.headers, \"location\");\n if (!location) throw new ShopBrandMediaError(\"UNSAFE_SOURCE\");\n try { next = safeUrl(new URL(location, next).toString()); }\n catch { throw new ShopBrandMediaError(\"UNSAFE_SOURCE\"); }\n continue;\n }\n if (response.statusCode !== 200) {\n response.body.destroy();\n throw new ShopBrandMediaError(TRANSIENT_HTTP.has(response.statusCode)\n ? \"SOURCE_UNAVAILABLE\" : \"SOURCE_HTTP_FAILURE\", TRANSIENT_HTTP.has(response.statusCode));\n }\n const bytes = await boundedBody(response, controller.signal, maxBytes);\n if (!bytes.length) throw new ShopBrandMediaError(\"INVALID_IMAGE\");\n const declaredContentType = header(response.headers, \"content-type\")?.split(\";\", 1)[0]?.trim().toLowerCase() ?? null;\n return { bytes, declaredContentType };\n }\n } catch (error) {\n if (controller.signal.aborted) throw cancelled(controller.signal);\n if (error instanceof ShopBrandMediaError) throw error;\n throw sanitiseNetworkError(error);\n } finally {\n clearTimeout(timer);\n externalSignal?.removeEventListener(\"abort\", abortFromCaller);\n }\n },\n };\n}\n","import sharp from \"sharp\";\nimport {\n SHOP_BRAND_CANVAS, SHOP_BRAND_MAX_INPUT_PIXELS, SHOP_BRAND_MAX_OUTPUT_BYTES,\n SHOP_BRAND_TARGET_OUTPUT_BYTES, ShopBrandMediaError,\n type ImageTransformer, type ShopBrandImageRole, type ShopBrandImageMime,\n} from \"./contracts.js\";\nimport { verifyEncodedBrandImage } from \"./metadata-verifier.js\";\n\nconst SUPPORTED_SOURCES = new Set([\"jpeg\", \"png\", \"webp\", \"avif\", \"heif\", \"gif\", \"svg\", \"tiff\"]);\n\n/** Deny SVG constructs capable of loading secondary, unpinned network/file resources. */\nexport function assertSelfContainedSvg(bytes: Buffer): void {\n const markup = bytes.toString(\"utf8\");\n if (/(?:<!DOCTYPE|<!ENTITY|<\\s*(?:script|image|use|foreignObject|iframe|object|embed|style|feImage)\\b|(?:xlink:)?href\\s*=|url\\s*\\(|@import\\b|\\bon[a-z]+\\s*=)/i.test(markup)) {\n throw new ShopBrandMediaError(\"INVALID_IMAGE\");\n }\n}\n\n/** Sharp/libvips is the sole decoder; metadata is a hint, not proof of source MIME. */\nexport function createShopBrandImageTransformer(): ImageTransformer {\n return {\n async transform(bytes: Buffer, role: ShopBrandImageRole) {\n if (!Buffer.isBuffer(bytes) || !bytes.length || !([\"LOGO\", \"SQUARE_LOGO\", \"COVER_IMAGE\"] as const).includes(role)) {\n throw new ShopBrandMediaError(\"INVALID_IMAGE\");\n }\n let mime: ShopBrandImageMime;\n let output: Buffer | undefined;\n try {\n // Reject dangerous XML references before even allowing librsvg to inspect metadata.\n if (bytes.subarray(0, 512).toString(\"utf8\").replace(/^\\uFEFF/, \"\").trimStart().startsWith(\"<\")) {\n assertSelfContainedSvg(bytes);\n }\n const source = sharp(bytes, { limitInputPixels: SHOP_BRAND_MAX_INPUT_PIXELS,\n failOn: \"error\", animated: false, pages: 1 });\n const info = await source.metadata();\n if (!info.format || !SUPPORTED_SOURCES.has(info.format) || !info.width || !info.height) {\n throw new ShopBrandMediaError(\"INVALID_IMAGE\");\n }\n if (info.format === \"svg\") assertSelfContainedSvg(bytes);\n if (info.width * info.height > SHOP_BRAND_MAX_INPUT_PIXELS) {\n throw new ShopBrandMediaError(\"INPUT_PIXELS_EXCEEDED\");\n }\n const transparent = Boolean(info.hasAlpha);\n mime = transparent ? \"image/png\" : \"image/jpeg\";\n const build = () => {\n const image = sharp(bytes, { limitInputPixels: SHOP_BRAND_MAX_INPUT_PIXELS,\n failOn: \"error\", animated: false, pages: 1 })\n .rotate()\n .toColourspace(\"srgb\")\n .resize(SHOP_BRAND_CANVAS.width, SHOP_BRAND_CANVAS.height, {\n fit: role === \"COVER_IMAGE\" ? \"cover\" : \"contain\",\n position: \"centre\",\n background: transparent\n ? { r: 255, g: 255, b: 255, alpha: 0 }\n : { r: 255, g: 255, b: 255, alpha: 1 },\n withoutEnlargement: false,\n });\n return transparent ? image : image.flatten({ background: \"#ffffff\" }).removeAlpha();\n };\n if (transparent) {\n output = await build().png({ compressionLevel: 9, palette: false }).toBuffer();\n // Quantise only when necessary to meet the provider cap; keep alpha semantics.\n if (output.length > SHOP_BRAND_TARGET_OUTPUT_BYTES) {\n const compact = await build().png({ compressionLevel: 9, palette: true,\n quality: 100, dither: 0 }).toBuffer();\n if (compact.length < output.length &&\n (compact.length <= SHOP_BRAND_TARGET_OUTPUT_BYTES ||\n output.length >= SHOP_BRAND_MAX_OUTPUT_BYTES)) output = compact;\n }\n } else {\n for (const quality of [86, 76, 66, 56, 46]) {\n const encoded = await build().jpeg({ quality, mozjpeg: true,\n chromaSubsampling: \"4:2:0\" }).toBuffer();\n if (!output || encoded.length < output.length) output = encoded;\n if (encoded.length <= SHOP_BRAND_TARGET_OUTPUT_BYTES) break;\n }\n }\n } catch (error) {\n if (error instanceof ShopBrandMediaError) throw error;\n // libvips and codec exceptions may include paths or byte excerpts: never propagate them.\n throw new ShopBrandMediaError(\"INVALID_IMAGE\");\n }\n if (!output || output.length >= SHOP_BRAND_MAX_OUTPUT_BYTES) {\n throw new ShopBrandMediaError(\"OUTPUT_TOO_LARGE\");\n }\n return verifyEncodedBrandImage(output, mime);\n },\n };\n}\n","import { createHash } from \"node:crypto\";\nimport sharp from \"sharp\";\nimport {\n SHOP_BRAND_CANVAS, SHOP_BRAND_MAX_OUTPUT_BYTES, ShopBrandMediaError,\n type ShopBrandImageMime, type VerifiedBrandImage,\n} from \"./contracts.js\";\n\n/** Independently re-decode the final *encoded* bytes; neither extensions nor encoder claims suffice. */\nexport async function verifyEncodedBrandImage(\n bytes: Buffer, contentType: ShopBrandImageMime,\n): Promise<VerifiedBrandImage> {\n if (!bytes.length || bytes.length >= SHOP_BRAND_MAX_OUTPUT_BYTES ||\n (contentType !== \"image/jpeg\" && contentType !== \"image/png\")) {\n throw new ShopBrandMediaError(\"OUTPUT_TOO_LARGE\");\n }\n try {\n const actual = await sharp(bytes, { limitInputPixels: SHOP_BRAND_CANVAS.width * SHOP_BRAND_CANVAS.height + 1,\n failOn: \"error\", animated: false }).metadata();\n const format = contentType === \"image/jpeg\" ? \"jpeg\" : \"png\";\n if (actual.format !== format || actual.width !== SHOP_BRAND_CANVAS.width ||\n actual.height !== SHOP_BRAND_CANVAS.height || (actual.pages ?? 1) !== 1 ||\n actual.exif || actual.xmp || actual.iptc || actual.icc || actual.orientation && actual.orientation !== 1) {\n throw new ShopBrandMediaError(\"OUTPUT_VERIFICATION_FAILED\");\n }\n return {\n bytes, contentType, width: actual.width, height: actual.height,\n sizeBytes: bytes.length,\n contentSha256: createHash(\"sha256\").update(bytes).digest(\"hex\"),\n };\n } catch {\n throw new ShopBrandMediaError(\"OUTPUT_VERIFICATION_FAILED\");\n }\n}\n","import sharp from \"sharp\";\nimport {\n SHOP_BRAND_MAX_INPUT_PIXELS,\n SHOP_BRAND_MAX_OUTPUT_BYTES,\n ShopBrandMediaError,\n boundedMediaProviderMessage,\n type VerifiedBrandImage,\n} from \"./contracts.js\";\nimport { assertSelfContainedSvg } from \"./image-transformer.js\";\nimport { verifyEncodedBrandImage } from \"./metadata-verifier.js\";\n\nconst WIDTH = 1125;\nconst HEIGHT = 600;\nconst QUALITY_STEPS = [86, 76, 66, 56, 46] as const;\nconst SUPPORTED_SOURCES = new Set([\"jpeg\", \"png\", \"webp\", \"avif\", \"heif\", \"gif\", \"svg\", \"tiff\"]);\n\nexport type OutreachProductImageTransformer = Readonly<{\n transform(bytes: Buffer, signal?: AbortSignal): Promise<VerifiedBrandImage>;\n}>;\n\n/** Standard product preset: preserve the complete product, pad white, and emit only metadata-free JPEG. */\nexport function createOutreachProductImageTransformer(): OutreachProductImageTransformer {\n return {\n async transform(bytes, signal) {\n if (signal?.aborted) throw new ShopBrandMediaError(\"SOURCE_TIMEOUT\", true);\n if (!Buffer.isBuffer(bytes) || bytes.length === 0) throw new ShopBrandMediaError(\"INVALID_IMAGE\");\n try {\n if (bytes.subarray(0, 512).toString(\"utf8\").replace(/^\\uFEFF/, \"\").trimStart().startsWith(\"<\")) {\n assertSelfContainedSvg(bytes);\n }\n const source = sharp(bytes, {\n limitInputPixels: false,\n failOn: \"error\",\n animated: false,\n pages: 1,\n });\n const cancelSource = () => { source.destroy(); };\n signal?.addEventListener(\"abort\", cancelSource, { once: true });\n let info: Awaited<ReturnType<typeof source.metadata>>;\n try { info = await source.metadata(); } finally { signal?.removeEventListener(\"abort\", cancelSource); }\n if (signal?.aborted) throw new ShopBrandMediaError(\"SOURCE_TIMEOUT\", true);\n if (!info.format || !SUPPORTED_SOURCES.has(info.format) || !info.width || !info.height) {\n throw new ShopBrandMediaError(\"INVALID_IMAGE\");\n }\n if (info.width * info.height > SHOP_BRAND_MAX_INPUT_PIXELS) {\n throw new ShopBrandMediaError(\"INPUT_PIXELS_EXCEEDED\");\n }\n if (info.format === \"svg\") assertSelfContainedSvg(bytes);\n\n let output: Buffer | undefined;\n for (const quality of QUALITY_STEPS) {\n if (signal?.aborted) throw new ShopBrandMediaError(\"SOURCE_TIMEOUT\", true);\n const encoder = sharp(bytes, {\n limitInputPixels: SHOP_BRAND_MAX_INPUT_PIXELS,\n failOn: \"error\",\n animated: false,\n pages: 1,\n })\n .rotate()\n .toColourspace(\"srgb\")\n .resize(WIDTH, HEIGHT, {\n fit: \"contain\",\n position: \"centre\",\n background: { r: 255, g: 255, b: 255, alpha: 1 },\n withoutEnlargement: false,\n })\n .flatten({ background: \"#ffffff\" })\n .removeAlpha()\n .jpeg({ quality, mozjpeg: true, chromaSubsampling: \"4:2:0\" });\n const cancelEncoder = () => { encoder.destroy(); };\n signal?.addEventListener(\"abort\", cancelEncoder, { once: true });\n let encoded: Buffer;\n try { encoded = await encoder.toBuffer(); } finally { signal?.removeEventListener(\"abort\", cancelEncoder); }\n if (signal?.aborted) throw new ShopBrandMediaError(\"SOURCE_TIMEOUT\", true);\n if (!output || encoded.length < output.length) output = encoded;\n if (encoded.length <= 1024 * 1024) break;\n }\n if (!output || output.length >= SHOP_BRAND_MAX_OUTPUT_BYTES) {\n throw new ShopBrandMediaError(\"OUTPUT_TOO_LARGE\");\n }\n const verified = await verifyEncodedBrandImage(output, \"image/jpeg\");\n if (signal?.aborted) throw new ShopBrandMediaError(\"SOURCE_TIMEOUT\", true);\n if (verified.contentType !== \"image/jpeg\" || verified.width !== WIDTH ||\n verified.height !== HEIGHT || verified.bytes.subarray(0, 2).toString(\"hex\") !== \"ffd8\") {\n throw new ShopBrandMediaError(\"OUTPUT_VERIFICATION_FAILED\");\n }\n return verified;\n } catch (error) {\n if (error instanceof ShopBrandMediaError) throw error;\n throw new ShopBrandMediaError(\"INVALID_IMAGE\", false, boundedMediaProviderMessage(error));\n }\n },\n };\n}\n","import { createHash } from \"node:crypto\";\nimport {\n HeadObjectCommand, PutObjectCommand, S3Client,\n type HeadObjectCommandInput, type HeadObjectCommandOutput, type PutObjectCommandInput,\n} from \"@aws-sdk/client-s3\";\nimport {\n ShopBrandMediaError,\n type VerifiedBrandImage,\n} from \"./contracts.js\";\nimport type { ShopBrandR2Credentials } from \"./contracts.js\";\n\nexport const SHOP_BRAND_CACHE_CONTROL = \"public, max-age=31536000, immutable\";\n\n/** Narrow injectable S3 boundary; no other R2 operation or credentials reach the processor. */\nexport interface BrandR2Transport {\n head(input: HeadObjectCommandInput, signal?: AbortSignal): Promise<HeadObjectCommandOutput>;\n put(input: PutObjectCommandInput, signal?: AbortSignal): Promise<void>;\n close?(): void;\n safeErrorMessage?(error: unknown): string | undefined;\n}\n\nexport function sanitizeR2ProviderMessage(error: unknown, credentials: ShopBrandR2Credentials): string | undefined {\n if (!error || typeof error !== \"object\" || !(\"message\" in error) || typeof error.message !== \"string\") return undefined;\n let message = [...error.message].map((character) => {\n const code = character.charCodeAt(0);\n return code < 32 || code === 127 ? \" \" : character;\n }).join(\"\");\n for (const secret of [credentials.secretAccessKey, credentials.accessKeyId]) {\n if (secret) message = message.split(secret).join(\"[REDACTED]\");\n }\n message = message\n .replace(/(authorization\\s*[:=]\\s*)(?:bearer\\s+)?[^\\s,;]+/gi, \"$1[REDACTED]\")\n .replace(/\\b(bearer\\s+)[A-Za-z0-9._~+/-]+=*/gi, \"$1[REDACTED]\")\n .replace(/((?:access.?key(?:.?id)?|secret.?key|session.?token|security.?token|token|password|signature|credential|api.?key)\\s*[:=]\\s*)[^\\s,;&\"'<>]+/gi, \"$1[REDACTED]\")\n .replace(/\\bhttps?:\\/\\/[^\\s,;]+/gi, \"[URL REDACTED]\")\n .replace(/\\s+/g, \" \").trim().slice(0, 300);\n return message || undefined;\n}\n\nexport function createBrandR2S3Transport(credentials: ShopBrandR2Credentials): BrandR2Transport {\n const client = new S3Client({ endpoint: credentials.endpoint, region: \"auto\", forcePathStyle: true,\n credentials: { accessKeyId: credentials.accessKeyId, secretAccessKey: credentials.secretAccessKey },\n maxAttempts: 2 });\n return {\n close() { client.destroy(); },\n head(input, signal) {\n return client.send(new HeadObjectCommand(input), signal ? { abortSignal: signal } : {});\n },\n async put(input, signal) {\n await client.send(new PutObjectCommand(input), signal ? { abortSignal: signal } : {});\n },\n safeErrorMessage(error) { return sanitizeR2ProviderMessage(error, credentials); },\n };\n}\n\nfunction httpStatus(error: unknown): number | undefined {\n if (!error || typeof error !== \"object\" || !(\"$metadata\" in error)) return undefined;\n const metadata = error.$metadata;\n if (!metadata || typeof metadata !== \"object\" || !(\"httpStatusCode\" in metadata)) return undefined;\n return typeof metadata.httpStatusCode === \"number\" ? metadata.httpStatusCode : undefined;\n}\nfunction isMissing(error: unknown): boolean {\n if (httpStatus(error) === 404) return true;\n return error !== null && typeof error === \"object\" && \"name\" in error &&\n (error.name === \"NotFound\" || error.name === \"NoSuchKey\");\n}\nfunction r2Failure(error: unknown, transport: BrandR2Transport): ShopBrandMediaError {\n if (error instanceof ShopBrandMediaError) return error;\n const status = httpStatus(error);\n return new ShopBrandMediaError(\"R2_UNAVAILABLE\",\n status === undefined || status >= 500 || status === 429 || status === 408 || status === 409,\n transport.safeErrorMessage?.(error));\n}\nfunction validBucket(bucket: string): boolean {\n return /^(?!.*\\.\\.)(?!.*\\.-|.*-\\.)[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(bucket) &&\n !/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(bucket);\n}\n\n/** Shared guarded immutable PUT/HEAD mechanics; each caller supplies its own strict key policy. */\nexport async function putGuardedImmutableR2Object(input: Readonly<{\n transportOrFactory: BrandR2Transport | (() => Promise<BrandR2Transport>);\n bucket: string;\n objectKey: string;\n image: VerifiedBrandImage;\n acceptsKey: (objectKey: string) => boolean;\n signal?: AbortSignal;\n expectedDimensions?: Readonly<{width: number; height: number}>;\n}>): Promise<void> {\n const { bucket, objectKey, image } = input;\n const dimensions = input.expectedDimensions ?? { width: 1125, height: 600 };\n if (!validBucket(bucket) || !input.acceptsKey(objectKey) ||\n ![\"image/jpeg\", \"image/png\"].includes(image.contentType) ||\n !/^[a-f0-9]{64}$/.test(image.contentSha256) ||\n createHash(\"sha256\").update(image.bytes).digest(\"hex\") !== image.contentSha256 ||\n image.sizeBytes !== image.bytes.length || !Number.isSafeInteger(dimensions.width) || !Number.isSafeInteger(dimensions.height) || dimensions.width <= 0 || dimensions.height <= 0 || dimensions.width * dimensions.height > 40_000_000 || image.width !== dimensions.width || image.height !== dimensions.height) {\n throw new ShopBrandMediaError(\"OUTPUT_VERIFICATION_FAILED\");\n }\n const transport = typeof input.transportOrFactory === \"function\"\n ? await input.transportOrFactory() : input.transportOrFactory;\n const head = async (): Promise<HeadObjectCommandOutput | null> => {\n try { return input.signal\n ? await transport.head({ Bucket: bucket, Key: objectKey }, input.signal)\n : await transport.head({ Bucket: bucket, Key: objectKey }); }\n catch (error) { if (isMissing(error)) return null; throw r2Failure(error, transport); }\n };\n let existing = await head();\n if (existing === null) {\n try {\n const putInput = {\n Bucket: bucket, Key: objectKey, Body: image.bytes,\n ContentType: image.contentType, ContentLength: image.sizeBytes,\n CacheControl: SHOP_BRAND_CACHE_CONTROL,\n Metadata: { sha256: image.contentSha256 },\n IfNoneMatch: \"*\",\n } satisfies PutObjectCommandInput;\n if (input.signal) await transport.put(putInput, input.signal);\n else await transport.put(putInput);\n } catch (error) {\n if (httpStatus(error) !== 412 && httpStatus(error) !== 409) throw r2Failure(error, transport);\n }\n existing = await head();\n }\n if (existing === null) throw new ShopBrandMediaError(\"R2_UNAVAILABLE\", true);\n if (existing.ContentType !== image.contentType || existing.ContentLength !== image.sizeBytes ||\n existing.Metadata?.sha256 !== image.contentSha256 || existing.CacheControl !== SHOP_BRAND_CACHE_CONTROL) {\n throw new ShopBrandMediaError(\"R2_OBJECT_MISMATCH\");\n }\n}\n\nexport { validBucket as isValidMediaBucket };\n","import { createHash } from \"node:crypto\";\nimport { ShopBrandMediaError, boundedMediaProviderMessage, type PublicMediaProbe, type SafeFetcher } from \"./contracts.js\";\n\n/** A HEAD-only check is insufficient: GET the current custom domain and match the stored bytes. */\nexport function createShopBrandPublicMediaProbe(fetcher: SafeFetcher): PublicMediaProbe {\n return {\n async verify({ url, image }, signal) {\n try {\n const result = await fetcher.fetch(url, signal);\n if (result.declaredContentType !== image.contentType ||\n result.bytes.length !== image.sizeBytes ||\n createHash(\"sha256\").update(result.bytes).digest(\"hex\") !== image.contentSha256) {\n throw new ShopBrandMediaError(\"PUBLIC_MEDIA_MISMATCH\", true);\n }\n } catch (error) {\n if (error instanceof ShopBrandMediaError && error.code === \"PUBLIC_MEDIA_MISMATCH\") throw error;\n // Always withhold READY metadata when the custom domain cannot deliver the new object.\n throw new ShopBrandMediaError(\"PUBLIC_MEDIA_UNAVAILABLE\", true,\n (error instanceof ShopBrandMediaError ? error.providerMessage : undefined) ??\n boundedMediaProviderMessage(error));\n }\n },\n };\n}\n","import { createHash } from 'node:crypto';\nimport { isIP } from 'node:net';\nimport { ConversationPreparedProductImageSchema, ConversationProductImageSourceSchema, type ConversationPreparedProductImage, type ConversationProductImageSource } from '../product-image.js';\nimport { stableJson } from '../wrapper-projection.js';\nimport { type SafeFetcher, type PublicMediaProbe, type VerifiedBrandImage, type ShopBrandR2Credentials, ShopBrandMediaError } from './contracts.js';\nimport { createSafeImageFetcher } from './safe-fetch.js';\nimport { createOutreachProductImageTransformer } from './product-image-transformer.js';\nimport { createBrandR2S3Transport, putGuardedImmutableR2Object, type BrandR2Transport, isValidMediaBucket } from './r2-writer.js';\nimport { createShopBrandPublicMediaProbe } from './public-probe.js';\nimport { isPublicIpAddress } from './network-policy.js';\n\nexport type ConversationProductImageOmission = 'CONFIGURATION_UNAVAILABLE' | 'UNSAFE_IMAGE_SOURCE' | 'SOURCE_UNAVAILABLE' | 'IMAGE_TRANSFORM_FAILED' | 'R2_UNAVAILABLE' | 'PUBLIC_IMAGE_UNAVAILABLE' | 'MEDIA_DEADLINE';\nexport type ConversationProductImageStage = 'CONFIGURATION' | 'SOURCE' | 'TRANSFORM' | 'R2' | 'PUBLIC_PROBE' | 'READY';\nexport type ConversationProductImagePreparation = { kind: 'READY'; image: ConversationPreparedProductImage; stage: 'READY'; durationMs: number }\n | { kind: 'OMITTED'; reason: ConversationProductImageOmission; stage: ConversationProductImageStage; durationMs: number };\nexport type ConversationProductImagePreparationInput = {\n source: ConversationProductImageSource;\n publicOrigin: string; bucketName: string; r2: ShopBrandR2Credentials;\n signal?: AbortSignal;\n /** Original turn deadline in epoch milliseconds. A caller may instead supply an already bounded child signal. */\n deadlineAt?: number;\n};\nexport type ConversationProductImagePreparationDependencies = {\n fetcher?: SafeFetcher;\n transformer?: { transform(bytes: Buffer, signal?: AbortSignal): Promise<VerifiedBrandImage> };\n transportFactory?: (credentials: ShopBrandR2Credentials) => BrandR2Transport;\n probe?: PublicMediaProbe;\n now?: () => number;\n};\nconst KEY = /^conversation-products\\/v1\\/[a-f0-9]{64}\\/[a-f0-9]{64}\\/[a-f0-9]{64}\\.jpg$/;\nexport const isConversationProductObjectKey = (key: string): boolean => KEY.test(key);\nconst sha256 = (bytes: string | Buffer): string => createHash('sha256').update(bytes).digest('hex');\nexport function conversationProductObjectKey(source: ConversationProductImageSource, contentSha256: string): string {\n const parsed = ConversationProductImageSourceSchema.parse(source);\n if (!/^[a-f0-9]{64}$/.test(contentSha256)) throw new ShopBrandMediaError('OUTPUT_VERIFICATION_FAILED');\n return `conversation-products/v1/${sha256(parsed.shopId)}/${sha256(stableJson({ productId: parsed.productId, variantId: parsed.variantId }))}/${contentSha256}.jpg`;\n}\nfunction publicOrigin(value: string): string | null {\n try {\n const url = new URL(value), host = url.hostname.replace(/^\\[|\\]$/g, '');\n if (url.protocol !== 'https:' || url.username || url.password || url.port || url.pathname !== '/' || url.search || url.hash ||\n (value !== url.origin && value !== url.origin + '/') || host === 'localhost' || host.endsWith('.localhost') ||\n (isIP(host) && !isPublicIpAddress(host))) return null;\n return url.origin;\n } catch { return null; }\n}\nclass MediaDeadline extends Error {}\nfunction bounded<T>(operation: () => Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) return Promise.reject(new MediaDeadline());\n return new Promise((resolve, reject) => {\n const abort = () => reject(new MediaDeadline());\n signal.addEventListener('abort', abort, { once: true });\n Promise.resolve().then(() => { if (signal.aborted) throw new MediaDeadline(); return operation(); }).then(\n value => { signal.removeEventListener('abort', abort); if (signal.aborted) reject(new MediaDeadline()); else resolve(value); },\n error => { signal.removeEventListener('abort', abort); reject(error); },\n );\n });\n}\n/** One optional preparation, no host authorization/config reads, provider sends or logs. */\nexport async function prepareConversationProductImage(input: ConversationProductImagePreparationInput, deps: ConversationProductImagePreparationDependencies = {}): Promise<ConversationProductImagePreparation> {\n const now = deps.now ?? Date.now, start = now();\n const duration = () => { const elapsed = now() - start; return Number.isFinite(elapsed) ? Math.max(0, Math.min(5000, elapsed)) : 0; };\n let stage: ConversationProductImageStage = 'CONFIGURATION';\n const omitted = (reason: ConversationProductImageOmission): ConversationProductImagePreparation => ({ kind: 'OMITTED', reason, stage, durationMs: duration() });\n const budget = input.deadlineAt === undefined ? 5000 : Math.min(5000, input.deadlineAt - start - 1000);\n if (!Number.isFinite(start) || !Number.isFinite(budget) || budget <= 0 || input.signal?.aborted) return omitted('MEDIA_DEADLINE');\n const source = ConversationProductImageSourceSchema.safeParse(input.source);\n if (!source.success) return omitted('UNSAFE_IMAGE_SOURCE');\n const origin = publicOrigin(input.publicOrigin);\n if (!origin || typeof input.bucketName !== 'string' || !isValidMediaBucket(input.bucketName) || typeof input.r2?.accessKeyId !== 'string' || !input.r2.accessKeyId || typeof input.r2.secretAccessKey !== 'string' || !input.r2.secretAccessKey) return omitted('CONFIGURATION_UNAVAILABLE');\n try { const endpoint = new URL(input.r2.endpoint); if (endpoint.protocol !== 'https:' || endpoint.username || endpoint.password || endpoint.search || endpoint.hash) return omitted('CONFIGURATION_UNAVAILABLE'); }\n catch { return omitted('CONFIGURATION_UNAVAILABLE'); }\n const controller = new AbortController();\n const abort = () => controller.abort();\n input.signal?.addEventListener('abort', abort, { once: true });\n if (input.signal?.aborted) abort();\n const timer = setTimeout(abort, budget);\n const checkDeadline = () => { if (now() >= start + budget) abort(); if (controller.signal.aborted) throw new MediaDeadline(); };\n let transport: BrandR2Transport | undefined;\n try {\n checkDeadline();\n stage = 'SOURCE';\n const fetched = await bounded(() => (deps.fetcher ?? createSafeImageFetcher()).fetch(source.data.sourceUrl, controller.signal), controller.signal);\n checkDeadline();\n stage = 'TRANSFORM';\n const image = await bounded(() => (deps.transformer ?? createOutreachProductImageTransformer()).transform(fetched.bytes, controller.signal), controller.signal);\n checkDeadline();\n const objectKey = conversationProductObjectKey(source.data, image.contentSha256);\n const prepared = ConversationPreparedProductImageSchema.parse({ schemaVersion: 1, shopId: source.data.shopId, productId: source.data.productId, variantId: source.data.variantId,\n publicUrl: `${origin}/${objectKey}`, objectKey, contentSha256: image.contentSha256, contentType: image.contentType, byteLength: image.sizeBytes, width: image.width, height: image.height });\n stage = 'R2';\n if (controller.signal.aborted) throw new MediaDeadline();\n transport = (deps.transportFactory ?? createBrandR2S3Transport)(input.r2);\n checkDeadline();\n await bounded(() => putGuardedImmutableR2Object({ transportOrFactory: transport!, bucket: input.bucketName, objectKey, image,\n acceptsKey: key => isConversationProductObjectKey(key) && key === objectKey, signal: controller.signal }), controller.signal);\n checkDeadline();\n stage = 'PUBLIC_PROBE';\n const probe = deps.probe ?? createShopBrandPublicMediaProbe(createSafeImageFetcher({ maxRedirects: 0, maxBytes: 5 * 1024 * 1024 - 1 }));\n await bounded(() => probe.verify({ url: prepared.publicUrl, image }, controller.signal), controller.signal);\n checkDeadline();\n stage = 'READY';\n return { kind: 'READY', image: prepared, stage, durationMs: duration() };\n } catch (error) {\n if (controller.signal.aborted || error instanceof MediaDeadline || now() >= start + budget) return omitted('MEDIA_DEADLINE');\n if (stage === 'SOURCE') return omitted(error instanceof ShopBrandMediaError && error.code === 'UNSAFE_SOURCE' ? 'UNSAFE_IMAGE_SOURCE' : 'SOURCE_UNAVAILABLE');\n if (stage === 'TRANSFORM') return omitted('IMAGE_TRANSFORM_FAILED');\n return omitted(stage === 'PUBLIC_PROBE' ? 'PUBLIC_IMAGE_UNAVAILABLE' : 'R2_UNAVAILABLE');\n } finally {\n clearTimeout(timer); input.signal?.removeEventListener('abort', abort);\n try { transport?.close?.(); } catch { /* Closing an owned transport cannot change the bounded outcome. */ }\n }\n}\n"],"mappings":"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","names":["isIP","isIP","sharp","sharp","sharp","SUPPORTED_SOURCES","sharp","createHash","createHash","createHash","createHash","createHash","isIP","createHash","isIP"]}
|
|
@@ -3,16 +3,18 @@ import {
|
|
|
3
3
|
RUNTIME_DATA_AUTHORITY_INSTRUCTION,
|
|
4
4
|
composeTrustedInstructions
|
|
5
5
|
} from "../../chunk-5TBA3WLV.js";
|
|
6
|
-
import {
|
|
7
|
-
manifestMatchesGrant,
|
|
8
|
-
mergeConversationProductContext
|
|
9
|
-
} from "../../chunk-5BIYNMMT.js";
|
|
10
6
|
import {
|
|
11
7
|
CommerceModelInvocationFailure,
|
|
12
8
|
RunnerFailure,
|
|
13
9
|
mapRunnerFailure,
|
|
14
10
|
schemaIssueMetadata
|
|
15
11
|
} from "../../chunk-WONND3OK.js";
|
|
12
|
+
import {
|
|
13
|
+
mergeConversationProductContext
|
|
14
|
+
} from "../../chunk-JWX4ZVKK.js";
|
|
15
|
+
import {
|
|
16
|
+
manifestMatchesGrant
|
|
17
|
+
} from "../../chunk-VJNXWDA5.js";
|
|
16
18
|
import {
|
|
17
19
|
CommerceConversationGrantSchema,
|
|
18
20
|
CommerceEvidenceSchema,
|