@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.
@@ -0,0 +1,186 @@
1
+ import { RequestOptions } from 'node:https';
2
+ import { IncomingHttpHeaders } from 'node:http';
3
+ import { Readable } from 'node:stream';
4
+ import { HeadObjectCommandInput, HeadObjectCommandOutput, PutObjectCommandInput } from '@aws-sdk/client-s3';
5
+ import { C as ConversationPreparedProductImage, a as ConversationProductImageSource } from '../../../wrapper-contracts-BcxDQPon.js';
6
+ import 'zod';
7
+
8
+ /** ARCH-049-BACKGROUND-001: one untrusted source in, one verified immutable image out. */
9
+ declare const SHOP_BRAND_CANVAS: Readonly<{
10
+ width: 1125;
11
+ height: 600;
12
+ }>;
13
+ declare const SHOP_BRAND_MAX_SOURCE_BYTES: number;
14
+ declare const SHOP_BRAND_MAX_OUTPUT_BYTES: number;
15
+ declare const SHOP_BRAND_TARGET_OUTPUT_BYTES: number;
16
+ declare const SHOP_BRAND_MAX_INPUT_PIXELS = 40000000;
17
+ type ShopBrandImageRole = "LOGO" | "SQUARE_LOGO" | "COVER_IMAGE";
18
+ type ShopBrandImageMime = "image/jpeg" | "image/png";
19
+ type ShopBrandMediaErrorCode = "INVALID_INPUT" | "UNSAFE_SOURCE" | "DNS_FAILURE" | "DNS_TEMPORARY_FAILURE" | "SOURCE_TIMEOUT" | "SOURCE_HTTP_FAILURE" | "SOURCE_UNAVAILABLE" | "SOURCE_TOO_LARGE" | "UNSUPPORTED_ENCODING" | "INVALID_IMAGE" | "INPUT_PIXELS_EXCEEDED" | "OUTPUT_TOO_LARGE" | "OUTPUT_VERIFICATION_FAILED" | "R2_CONFIGURATION_INVALID" | "R2_UNAVAILABLE" | "R2_OBJECT_MISMATCH" | "PUBLIC_MEDIA_UNAVAILABLE" | "PUBLIC_MEDIA_MISMATCH" | "UNEXPECTED_FAILURE";
20
+ /** The message is a bounded code, not a provider exception or a URL containing credentials. */
21
+ declare class ShopBrandMediaError extends Error {
22
+ readonly code: ShopBrandMediaErrorCode;
23
+ readonly retryable: boolean;
24
+ readonly providerMessage?: string | undefined;
25
+ constructor(code: ShopBrandMediaErrorCode, retryable?: boolean, providerMessage?: string | undefined);
26
+ }
27
+ /** Bounded diagnostic provenance for provider/library failures; never retain a source URL or common secrets. */
28
+ declare function boundedMediaProviderMessage(error: unknown): string | undefined;
29
+ interface VerifiedBrandImage {
30
+ bytes: Buffer;
31
+ contentType: ShopBrandImageMime;
32
+ width: number;
33
+ height: number;
34
+ sizeBytes: number;
35
+ contentSha256: string;
36
+ }
37
+ interface FetchedBrandSource {
38
+ bytes: Buffer;
39
+ /** The response's declared type; never trusted for decoding. */
40
+ declaredContentType: string | null;
41
+ }
42
+ interface SafeFetcher {
43
+ fetch(url: string, signal?: AbortSignal): Promise<FetchedBrandSource>;
44
+ }
45
+ interface ImageTransformer {
46
+ transform(bytes: Buffer, role: ShopBrandImageRole): Promise<VerifiedBrandImage>;
47
+ }
48
+ interface PublicMediaProbe {
49
+ verify(input: {
50
+ url: string;
51
+ image: VerifiedBrandImage;
52
+ }, signal?: AbortSignal): Promise<void>;
53
+ }
54
+ /** Host-supplied validated credentials; Shared performs no configuration lookup. */
55
+ type ShopBrandR2Credentials = Readonly<{
56
+ endpoint: string;
57
+ accessKeyId: string;
58
+ secretAccessKey: string;
59
+ }>;
60
+
61
+ declare const MERCHANT_KNOWLEDGE_ACQUISITION_ERROR_CODES: readonly ["INVALID_URL", "DENIED_DESTINATION", "DNS_NO_ADDRESSES", "DNS_TEMPORARY_FAILURE", "DNS_FAILURE", "TOO_MANY_REDIRECTS", "INVALID_REDIRECT", "REQUEST_DEADLINE", "CONNECTION_PEER_MISMATCH", "HTTP_STATUS_TRANSIENT", "HTTP_STATUS_PERMANENT", "UNSUPPORTED_MEDIA_TYPE", "UNSUPPORTED_CONTENT_ENCODING", "BODY_TOO_LARGE", "RESPONSE_READ_FAILED"];
62
+ type MerchantKnowledgeAcquisitionErrorCode = (typeof MERCHANT_KNOWLEDGE_ACQUISITION_ERROR_CODES)[number];
63
+ declare class MerchantKnowledgeAcquisitionError extends Error {
64
+ readonly code: MerchantKnowledgeAcquisitionErrorCode;
65
+ readonly retryable: boolean;
66
+ constructor(code: MerchantKnowledgeAcquisitionErrorCode, message: string, retryable?: boolean);
67
+ }
68
+ interface MerchantKnowledgeResolvedAddress {
69
+ address: string;
70
+ family: 4 | 6;
71
+ }
72
+ type MerchantKnowledgeResolver = (hostname: string) => Promise<readonly MerchantKnowledgeResolvedAddress[]>;
73
+ declare function normalizeIpAddress(address: string): string | null;
74
+ declare function isPublicIpAddress(address: string): boolean;
75
+ declare function resolveAllDnsAnswers(hostname: string): Promise<readonly MerchantKnowledgeResolvedAddress[]>;
76
+ declare function resolveAndValidateDestination(hostnameInput: string, resolver?: MerchantKnowledgeResolver): Promise<MerchantKnowledgeResolvedAddress>;
77
+ declare function addressesMatch(left: string, right: string): boolean;
78
+ declare function createPinnedLookup(address: MerchantKnowledgeResolvedAddress): NonNullable<RequestOptions["lookup"]>;
79
+
80
+ declare const REQUEST_HEADERS: Readonly<{
81
+ Accept: "image/avif,image/webp,image/png,image/jpeg,image/gif,image/svg+xml,*/*;q=0.2";
82
+ "Accept-Encoding": "identity";
83
+ "User-Agent": "ModaInteract-ShopBrandMedia/1.0";
84
+ }>;
85
+ type PinnedImageRequest = Readonly<{
86
+ hostname: string;
87
+ path: string;
88
+ address: MerchantKnowledgeResolvedAddress;
89
+ servername?: string;
90
+ headers: typeof REQUEST_HEADERS;
91
+ }>;
92
+ interface ImageHttpResponse {
93
+ statusCode: number;
94
+ headers: IncomingHttpHeaders;
95
+ body: Readable;
96
+ peerAddress: string;
97
+ }
98
+ type PinnedImageHttpRequest = (input: PinnedImageRequest, signal: AbortSignal) => Promise<ImageHttpResponse>;
99
+ interface SafeImageFetcherOptions {
100
+ resolveAll?: MerchantKnowledgeResolver;
101
+ request?: PinnedImageHttpRequest;
102
+ /** Narrow deployments can prohibit redirects and lower the byte ceiling. */
103
+ maxRedirects?: number;
104
+ maxBytes?: number;
105
+ }
106
+ declare function createSafeImageFetcher(options?: SafeImageFetcherOptions): SafeFetcher;
107
+
108
+ /** Deny SVG constructs capable of loading secondary, unpinned network/file resources. */
109
+ declare function assertSelfContainedSvg(bytes: Buffer): void;
110
+ /** Sharp/libvips is the sole decoder; metadata is a hint, not proof of source MIME. */
111
+ declare function createShopBrandImageTransformer(): ImageTransformer;
112
+
113
+ type OutreachProductImageTransformer = Readonly<{
114
+ transform(bytes: Buffer, signal?: AbortSignal): Promise<VerifiedBrandImage>;
115
+ }>;
116
+ /** Standard product preset: preserve the complete product, pad white, and emit only metadata-free JPEG. */
117
+ declare function createOutreachProductImageTransformer(): OutreachProductImageTransformer;
118
+
119
+ /** Independently re-decode the final *encoded* bytes; neither extensions nor encoder claims suffice. */
120
+ declare function verifyEncodedBrandImage(bytes: Buffer, contentType: ShopBrandImageMime): Promise<VerifiedBrandImage>;
121
+
122
+ declare const SHOP_BRAND_CACHE_CONTROL = "public, max-age=31536000, immutable";
123
+ /** Narrow injectable S3 boundary; no other R2 operation or credentials reach the processor. */
124
+ interface BrandR2Transport {
125
+ head(input: HeadObjectCommandInput, signal?: AbortSignal): Promise<HeadObjectCommandOutput>;
126
+ put(input: PutObjectCommandInput, signal?: AbortSignal): Promise<void>;
127
+ close?(): void;
128
+ safeErrorMessage?(error: unknown): string | undefined;
129
+ }
130
+ declare function sanitizeR2ProviderMessage(error: unknown, credentials: ShopBrandR2Credentials): string | undefined;
131
+ declare function createBrandR2S3Transport(credentials: ShopBrandR2Credentials): BrandR2Transport;
132
+ declare function validBucket(bucket: string): boolean;
133
+ /** Shared guarded immutable PUT/HEAD mechanics; each caller supplies its own strict key policy. */
134
+ declare function putGuardedImmutableR2Object(input: Readonly<{
135
+ transportOrFactory: BrandR2Transport | (() => Promise<BrandR2Transport>);
136
+ bucket: string;
137
+ objectKey: string;
138
+ image: VerifiedBrandImage;
139
+ acceptsKey: (objectKey: string) => boolean;
140
+ signal?: AbortSignal;
141
+ expectedDimensions?: Readonly<{
142
+ width: number;
143
+ height: number;
144
+ }>;
145
+ }>): Promise<void>;
146
+
147
+ /** A HEAD-only check is insufficient: GET the current custom domain and match the stored bytes. */
148
+ declare function createShopBrandPublicMediaProbe(fetcher: SafeFetcher): PublicMediaProbe;
149
+
150
+ type ConversationProductImageOmission = 'CONFIGURATION_UNAVAILABLE' | 'UNSAFE_IMAGE_SOURCE' | 'SOURCE_UNAVAILABLE' | 'IMAGE_TRANSFORM_FAILED' | 'R2_UNAVAILABLE' | 'PUBLIC_IMAGE_UNAVAILABLE' | 'MEDIA_DEADLINE';
151
+ type ConversationProductImageStage = 'CONFIGURATION' | 'SOURCE' | 'TRANSFORM' | 'R2' | 'PUBLIC_PROBE' | 'READY';
152
+ type ConversationProductImagePreparation = {
153
+ kind: 'READY';
154
+ image: ConversationPreparedProductImage;
155
+ stage: 'READY';
156
+ durationMs: number;
157
+ } | {
158
+ kind: 'OMITTED';
159
+ reason: ConversationProductImageOmission;
160
+ stage: ConversationProductImageStage;
161
+ durationMs: number;
162
+ };
163
+ type ConversationProductImagePreparationInput = {
164
+ source: ConversationProductImageSource;
165
+ publicOrigin: string;
166
+ bucketName: string;
167
+ r2: ShopBrandR2Credentials;
168
+ signal?: AbortSignal;
169
+ /** Original turn deadline in epoch milliseconds. A caller may instead supply an already bounded child signal. */
170
+ deadlineAt?: number;
171
+ };
172
+ type ConversationProductImagePreparationDependencies = {
173
+ fetcher?: SafeFetcher;
174
+ transformer?: {
175
+ transform(bytes: Buffer, signal?: AbortSignal): Promise<VerifiedBrandImage>;
176
+ };
177
+ transportFactory?: (credentials: ShopBrandR2Credentials) => BrandR2Transport;
178
+ probe?: PublicMediaProbe;
179
+ now?: () => number;
180
+ };
181
+ declare const isConversationProductObjectKey: (key: string) => boolean;
182
+ declare function conversationProductObjectKey(source: ConversationProductImageSource, contentSha256: string): string;
183
+ /** One optional preparation, no host authorization/config reads, provider sends or logs. */
184
+ declare function prepareConversationProductImage(input: ConversationProductImagePreparationInput, deps?: ConversationProductImagePreparationDependencies): Promise<ConversationProductImagePreparation>;
185
+
186
+ export { type BrandR2Transport, type ConversationProductImageOmission, type ConversationProductImagePreparation, type ConversationProductImagePreparationDependencies, type ConversationProductImagePreparationInput, type ConversationProductImageStage, type FetchedBrandSource, type ImageHttpResponse, type ImageTransformer, MERCHANT_KNOWLEDGE_ACQUISITION_ERROR_CODES, MerchantKnowledgeAcquisitionError, type MerchantKnowledgeAcquisitionErrorCode, type MerchantKnowledgeResolvedAddress, type MerchantKnowledgeResolver, type OutreachProductImageTransformer, type PinnedImageHttpRequest, type PinnedImageRequest, type PublicMediaProbe, SHOP_BRAND_CACHE_CONTROL, SHOP_BRAND_CANVAS, SHOP_BRAND_MAX_INPUT_PIXELS, SHOP_BRAND_MAX_OUTPUT_BYTES, SHOP_BRAND_MAX_SOURCE_BYTES, SHOP_BRAND_TARGET_OUTPUT_BYTES, type SafeFetcher, type SafeImageFetcherOptions, type ShopBrandImageMime, type ShopBrandImageRole, ShopBrandMediaError, type ShopBrandMediaErrorCode, type ShopBrandR2Credentials, type VerifiedBrandImage, addressesMatch, assertSelfContainedSvg, boundedMediaProviderMessage, conversationProductObjectKey, createBrandR2S3Transport, createOutreachProductImageTransformer, createPinnedLookup, createSafeImageFetcher, createShopBrandImageTransformer, createShopBrandPublicMediaProbe, isConversationProductObjectKey, isPublicIpAddress, validBucket as isValidMediaBucket, normalizeIpAddress, prepareConversationProductImage, putGuardedImmutableR2Object, resolveAllDnsAnswers, resolveAndValidateDestination, sanitizeR2ProviderMessage, verifyEncodedBrandImage };