@mesh-sync/worker-backend-client 4.0.21 → 4.0.24-pr.51.20260312133943

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/types.d.ts CHANGED
@@ -4,8 +4,6 @@
4
4
  export declare const MessageTypes: {
5
5
  readonly ANALYTICS_COLLECTION_REQUEST: "analytics-collection-request";
6
6
  readonly BACKEND_LOGGING_EVENT: "backend-logging-event";
7
- readonly EKG_EDGE_BATCH_CREATE_COMPLETED: "ekg-edge-batch-create-completed";
8
- readonly EKG_EDGE_BATCH_CREATE_REQUEST: "ekg-edge-batch-create-request";
9
7
  readonly ETSY_ANALYTICS_SYNC_COMPLETED: "etsy-analytics-sync-completed";
10
8
  readonly ETSY_ANALYTICS_SYNC_REQUEST: "etsy-analytics-sync-request";
11
9
  readonly ETSY_PUBLISH_LISTING_COMPLETED: "etsy-publish-listing-completed";
@@ -14,13 +12,15 @@ export declare const MessageTypes: {
14
12
  readonly FILE_DOWNLOAD_REQUEST: "file-download-request";
15
13
  readonly FILE_VECTORIZE_COMPLETED: "file-vectorize-completed";
16
14
  readonly FILE_VECTORIZE_REQUEST: "file-vectorize-request";
17
- readonly MARKETPLACE_ANALYTICS_SYNC_COMPLETED: "marketplace-analytics-sync-completed";
18
- readonly MARKETPLACE_ANALYTICS_SYNC_REQUEST: "marketplace-analytics-sync-request";
15
+ readonly IP_CHECK_COMPLETED: "ip-check-completed";
16
+ readonly IP_CHECK_REQUEST: "ip-check-request";
19
17
  readonly MARKETPLACE_CONNECTION_SYNC_COMPLETED: "marketplace-connection-sync-completed";
20
18
  readonly MARKETPLACE_CONNECTION_SYNC_REQUEST: "marketplace-connection-sync-request";
21
19
  readonly MARKETPLACE_CREDENTIAL_ROTATION_COMPLETED: "marketplace-credential-rotation-completed";
22
20
  readonly MARKETPLACE_CREDENTIAL_ROTATION_REQUEST: "marketplace-credential-rotation-request";
21
+ readonly MARKETPLACE_INTELLIGENCE_COMPLETED: "marketplace-intelligence-completed";
23
22
  readonly MARKETPLACE_INTELLIGENCE_EVENT: "marketplace-intelligence-event";
23
+ readonly MARKETPLACE_INTELLIGENCE_REQUEST: "marketplace-intelligence-request";
24
24
  readonly MARKETPLACE_LISTING_DESCRIPTION_GENERATION_COMPLETED: "marketplace-listing-description-generation-completed";
25
25
  readonly MARKETPLACE_LISTING_DESCRIPTION_GENERATION_REQUEST: "marketplace-listing-description-generation-request";
26
26
  readonly MARKETPLACE_LISTING_SYNC_COMPLETED: "marketplace-listing-sync-completed";
@@ -31,8 +31,6 @@ export declare const MessageTypes: {
31
31
  readonly MARKETPLACE_LISTING_TITLE_GENERATION_REQUEST: "marketplace-listing-title-generation-request";
32
32
  readonly MARKETPLACE_LISTING_UPDATE_COMPLETED: "marketplace-listing-update-completed";
33
33
  readonly MARKETPLACE_LISTING_UPDATE_REQUEST: "marketplace-listing-update-request";
34
- readonly MARKETPLACE_PUBLISH_LISTING_COMPLETED: "marketplace-publish-listing-completed";
35
- readonly MARKETPLACE_PUBLISH_LISTING_REQUEST: "marketplace-publish-listing-request";
36
34
  readonly MEDIA_BATCH_DOWNLOAD_COMPLETED: "media-batch-download-completed";
37
35
  readonly MEDIA_BATCH_DOWNLOAD_REQUEST: "media-batch-download-request";
38
36
  readonly METAMODEL_METADATA_GENERATION_COMPLETED: "metamodel-metadata-generation-completed";
@@ -49,12 +47,20 @@ export declare const MessageTypes: {
49
47
  readonly MODEL_METADATA_GENERATION_REQUEST: "model-metadata-generation-request";
50
48
  readonly MODEL_METAMODEL_DETECTION_FOUND: "model-metamodel-detection-found";
51
49
  readonly MODEL_METAMODEL_DETECTION_REQUEST: "model-metamodel-detection-request";
50
+ readonly MODEL_PRINT_ANALYSIS_COMPLETED: "model-print-analysis-completed";
51
+ readonly MODEL_PRINT_ANALYSIS_REQUEST: "model-print-analysis-request";
52
52
  readonly MODEL_SELLABILITY_ANALYSIS_COMPLETED: "model-sellability-analysis-completed";
53
53
  readonly MODEL_SELLABILITY_ANALYSIS_REQUEST: "model-sellability-analysis-request";
54
54
  readonly MODEL_SEMANTIC_ANALYSIS_COMPLETED: "model-semantic-analysis-completed";
55
55
  readonly MODEL_SEMANTIC_ANALYSIS_REQUEST: "model-semantic-analysis-request";
56
56
  readonly MODEL_TECHNICAL_METADATA_COMPLETED: "model-technical-metadata-completed";
57
57
  readonly MODEL_TECHNICAL_METADATA_REQUEST: "model-technical-metadata-request";
58
+ readonly SLICING_FDM_REQUEST: "slicing-fdm-request";
59
+ readonly SLICING_FDM_RESULT: "slicing-fdm-result";
60
+ readonly SLICING_SLA_REQUEST: "slicing-sla-request";
61
+ readonly SLICING_SLA_RESULT: "slicing-sla-result";
62
+ readonly TEXTURE_GENERATION_COMPLETED: "texture-generation-completed";
63
+ readonly TEXTURE_GENERATION_REQUEST: "texture-generation-request";
58
64
  readonly THUMBNAIL_GENERATION_COMPLETED: "thumbnail-generation-completed";
59
65
  readonly THUMBNAIL_GENERATION_REQUEST: "thumbnail-generation-request";
60
66
  readonly USER_ENGAGEMENT_EVENT: "user-engagement-event";
@@ -73,7 +79,9 @@ export interface AnalyticsCollectionRequestMessage {
73
79
  /** The search query to use */
74
80
  query: string;
75
81
  /** Collection options (pages, filters, etc.) */
76
- options?: Record<string, string | number | boolean>;
82
+ options?: {
83
+ pages?: number;
84
+ };
77
85
  }
78
86
  /**
79
87
  * Centralized logging event for capturing all warn/error/failure logs from meshsync-backend.
@@ -113,7 +121,7 @@ export interface BackendLoggingEventMessage {
113
121
  /** Request URL path (without query params for privacy) */
114
122
  httpUrl?: string;
115
123
  /** HTTP response status code */
116
- httpStatusCode?: string | number | boolean;
124
+ httpStatusCode?: number;
117
125
  /** Error class/type name */
118
126
  errorType?: string;
119
127
  /** Stack trace (sanitized, no sensitive data) */
@@ -121,7 +129,14 @@ export interface BackendLoggingEventMessage {
121
129
  /** Application-specific error code for categorization */
122
130
  errorCode?: string;
123
131
  /** Additional structured context (sanitized, no PII) */
124
- metadata?: Record<string, string | number | boolean>;
132
+ metadata?: {
133
+ modelId?: string;
134
+ storageId?: string;
135
+ workerId?: string;
136
+ jobId?: string;
137
+ marketplace?: string;
138
+ operation?: string;
139
+ };
125
140
  /** Deployment environment */
126
141
  environment?: string;
127
142
  /** Backend service version */
@@ -131,38 +146,6 @@ export interface BackendLoggingEventMessage {
131
146
  /** Operation duration in milliseconds (if applicable) */
132
147
  durationMs?: number;
133
148
  }
134
- /**
135
- * Completion event for EKG edge batch creation with propagation results.
136
- */
137
- export interface EkgEdgeBatchCreateCompletedMessage {
138
- /** Original request ID from ekg-edge-batch-create-request */
139
- requestId: string;
140
- /** Whether the batch operation succeeded */
141
- success: boolean;
142
- /** Batch operation statistics */
143
- statistics: Record<string, string | number | boolean>;
144
- /** List of high-conflict edges requiring review */
145
- conflicts?: Array<Record<string, string | number | boolean>>;
146
- /** Errors encountered during processing */
147
- errors?: Array<Record<string, string | number | boolean>>;
148
- /** Overall graph state after this batch */
149
- graphMetrics?: Record<string, string | number | boolean>;
150
- }
151
- /**
152
- * Create multiple EKG edges with Dempster-Shafer mass functions. Triggered by metamodel detection completion.
153
- */
154
- export interface EkgEdgeBatchCreateRequestMessage {
155
- /** Unique request ID for tracking (e.g., metamodel detection job ID) */
156
- requestId: string;
157
- /** Source of the edges: metamodel-heuristic, manual, taxonomy-import, etc. */
158
- source: string;
159
- /** Batch of edges to create/update in the EKG */
160
- edges: Array<Record<string, string | number | boolean>>;
161
- /** Options for evidential edge propagation after edge creation */
162
- propagationOptions?: Record<string, string | number | boolean>;
163
- /** Optional webhook URL for async completion notification */
164
- webhookUrl?: string;
165
- }
166
149
  /**
167
150
  * Contains synced analytics data for Etsy listings. Backend stores this in etsy_analytics_snapshots table and indexes to ELK.
168
151
 
@@ -173,15 +156,42 @@ export interface EtsyAnalyticsSyncCompletedMessage {
173
156
  /** */
174
157
  status?: string;
175
158
  /** Number of listings successfully synced */
176
- syncedCount?: string | number | boolean;
159
+ syncedCount?: number;
177
160
  /** Number of listings that failed */
178
- errorCount?: string | number | boolean;
161
+ errorCount?: number;
179
162
  /** Analytics for each synced listing */
180
- results?: Array<Record<string, string | number | boolean>>;
163
+ results?: Array<{
164
+ listingId?: string;
165
+ etsyListingId?: string;
166
+ materialName?: string;
167
+ analytics?: {
168
+ views?: number;
169
+ favorites?: number;
170
+ sales?: number;
171
+ revenue?: number;
172
+ conversionRate?: number;
173
+ averageOrderValue?: number;
174
+ topSearchTerms?: string[];
175
+ trafficSources?: Record<string, number>;
176
+ timeSeries?: Array<{
177
+ date?: string;
178
+ views?: number;
179
+ sales?: number;
180
+ }>;
181
+ };
182
+ status?: string;
183
+ }>;
181
184
  /** New credentials if token was refreshed during operation */
182
- credentialUpdate?: Record<string, string | number | boolean>;
185
+ credentialUpdate?: {
186
+ newAccessToken?: string;
187
+ newRefreshToken?: string;
188
+ expiresIn?: number;
189
+ };
183
190
  /** Errors for failed listings */
184
- errors?: Array<Record<string, string | number | boolean>>;
191
+ errors?: Array<{
192
+ listingId?: string;
193
+ error?: string;
194
+ }>;
185
195
  /** */
186
196
  syncedAt?: string;
187
197
  /** When next automatic sync should occur */
@@ -194,19 +204,34 @@ Can sync: - Specific listings (provide listingIds) - All user listings (provide
194
204
  */
195
205
  export interface EtsyAnalyticsSyncRequestMessage {
196
206
  /** Internal listing IDs to sync. Empty = sync all for user. */
197
- listingIds?: Array<Record<string, string | number | boolean>>;
207
+ listingIds?: string[];
198
208
  /** User whose listings to sync (if listingIds empty) */
199
209
  userId?: string;
200
210
  /** Etsy shop ID for shop-level analytics */
201
211
  shopId?: string;
202
212
  /** Etsy OAuth credentials */
203
- credentials?: Record<string, string | number | boolean>;
213
+ credentials?: {
214
+ apiKey?: string;
215
+ shopId?: string;
216
+ accessToken?: string;
217
+ refreshToken?: string;
218
+ };
204
219
  /** Date range for historical analytics */
205
- timeRange?: Record<string, string | number | boolean>;
220
+ timeRange?: {
221
+ startDate: string;
222
+ endDate: string;
223
+ };
206
224
  /** */
207
- syncOptions?: Record<string, string | number | boolean>;
225
+ syncOptions?: {
226
+ includeDetailedMetrics?: boolean;
227
+ includeTrafficSources?: boolean;
228
+ includeSearchTerms?: boolean;
229
+ };
208
230
  /** Encrypted Etsy OAuth credentials */
209
- etsyCredentials?: Record<string, string | number | boolean>;
231
+ etsyCredentials?: {
232
+ accessToken: string;
233
+ shopId: string;
234
+ };
210
235
  /** */
211
236
  webhookUrl?: string;
212
237
  }
@@ -230,15 +255,24 @@ export interface EtsyPublishListingCompletedMessage {
230
255
  /** URL to view listing on Etsy (only if status=SUCCESS) */
231
256
  etsyListingUrl?: string;
232
257
  /** New credentials if token was refreshed during operation */
233
- credentialUpdate?: Record<string, string | number | boolean>;
258
+ credentialUpdate?: {
259
+ newAccessToken?: string;
260
+ newRefreshToken?: string;
261
+ expiresIn?: number;
262
+ };
234
263
  /** Etsy digital file ID (only if status=SUCCESS) */
235
264
  etsyFileId?: string;
236
265
  /** Error details (only if status=FAILED) */
237
- error?: Record<string, string | number | boolean>;
266
+ error?: {
267
+ code?: string;
268
+ message?: string;
269
+ details?: Record<string, unknown>;
270
+ retryable?: boolean;
271
+ };
238
272
  /** When the listing was created (only if status=SUCCESS) */
239
273
  publishedAt?: string;
240
274
  /** Processing time in milliseconds */
241
- processingDuration?: string | number | boolean;
275
+ processingDuration?: number;
242
276
  }
243
277
  /**
244
278
  * Publishes a single metamodel listing to Etsy for a specific material variant. Creates Etsy listing, uploads digital file, and returns external listing ID.
@@ -254,17 +288,48 @@ export interface EtsyPublishListingRequestMessage {
254
288
  /** User ID who owns the metamodel */
255
289
  ownerId?: string;
256
290
  /** Etsy OAuth credentials */
257
- credentials?: Record<string, string | number | boolean>;
291
+ credentials?: {
292
+ apiKey?: string;
293
+ shopId?: string;
294
+ accessToken?: string;
295
+ refreshToken?: string;
296
+ };
258
297
  /** Material-specific listing configuration */
259
- materialVariant?: Record<string, string | number | boolean>;
298
+ materialVariant?: {
299
+ materialName: string;
300
+ price: number;
301
+ sku?: string;
302
+ currency?: string;
303
+ };
260
304
  /** Common listing information */
261
- baseListingData?: Record<string, string | number | boolean>;
305
+ baseListingData?: {
306
+ title: string;
307
+ description: string;
308
+ tags: string[];
309
+ taxonomyId: number;
310
+ whoMade?: string;
311
+ whenMade?: string;
312
+ isDigital?: boolean;
313
+ quantity?: number;
314
+ };
262
315
  /** */
263
- publishOptions?: Record<string, string | number | boolean>;
316
+ publishOptions?: {
317
+ autoActivate?: boolean;
318
+ shippingProfileId?: number;
319
+ };
264
320
  /** Encrypted Etsy OAuth credentials */
265
- etsyCredentials?: Record<string, string | number | boolean>;
321
+ etsyCredentials?: {
322
+ accessToken: string;
323
+ shopId: string;
324
+ expiresAt?: string;
325
+ };
266
326
  /** Digital file to upload */
267
- fileMetadata?: Record<string, string | number | boolean>;
327
+ fileMetadata?: {
328
+ storageItemId: string;
329
+ fileName: string;
330
+ fileSize?: number;
331
+ mimeType?: string;
332
+ };
268
333
  /** Callback URL for completion notification */
269
334
  webhookUrl?: string;
270
335
  }
@@ -279,7 +344,11 @@ export interface FileDownloadCompletedMessage {
279
344
  /** The final status of the download operation. */
280
345
  status?: string;
281
346
  /** Details of the file's location in Minio S3 (present on success). */
282
- s3Location?: Record<string, string | number | boolean>;
347
+ s3Location?: {
348
+ bucket: string;
349
+ key: string;
350
+ versionId?: string;
351
+ };
283
352
  /** Contains error details if the status is FAILED. */
284
353
  errorMessage?: string;
285
354
  /** The timestamp when the download was completed or failed. */
@@ -302,13 +371,31 @@ export interface FileDownloadRequestMessage {
302
371
  /** The identifier of the user who owns the model. Optional - if not provided, will be retrieved from StorageConnection. */
303
372
  ownerId?: string;
304
373
  /** The storage location of the model. */
305
- storageLocation?: Record<string, string | number | boolean>;
374
+ storageLocation?: {
375
+ storageConnectionId: string;
376
+ path: string;
377
+ };
306
378
  /** Optional metadata from discovery. For Thingiverse, contains downloadUrl for direct file access. */
307
- metadata?: Record<string, string | number | boolean>;
379
+ metadata?: {
380
+ downloadUrl?: string;
381
+ };
308
382
  /** Decrypted credentials required for this specific download operation. Injected by the backend. */
309
- credentials?: Record<string, string | number | boolean>;
383
+ credentials?: {
384
+ providerType?: string;
385
+ accessKeyId?: string;
386
+ secretAccessKey?: string;
387
+ region?: string;
388
+ accessToken?: string;
389
+ refreshToken?: string;
390
+ username?: string;
391
+ password?: string;
392
+ privateKey?: string;
393
+ };
310
394
  /** Destination in MinIO where file will be uploaded after download. */
311
- minioDestination?: Record<string, string | number | boolean>;
395
+ minioDestination?: {
396
+ bucket?: string;
397
+ path: string;
398
+ };
312
399
  /** Automatically enqueue thumbnail generation, technical metadata analysis, and metadata generation jobs after download completes. */
313
400
  autoEnqueueChildren?: boolean;
314
401
  /** Preview type for thumbnail generation (passed to child job). */
@@ -325,11 +412,11 @@ export interface FileVectorizeCompletedMessage {
325
412
  /** */
326
413
  fileId?: string;
327
414
  /** The computed embedding vector */
328
- vector?: Array<Record<string, string | number | boolean>>;
415
+ vector?: number[];
329
416
  /** */
330
417
  modelName?: string;
331
418
  /** Length of the vector (e.g., 512) */
332
- dimension?: string | number | boolean;
419
+ dimension?: number;
333
420
  }
334
421
  /**
335
422
  * Request to generate a vector embedding for an image file using CLIP.
@@ -338,55 +425,108 @@ export interface FileVectorizeRequestMessage {
338
425
  /** The ID of the file in the database */
339
426
  fileId?: string;
340
427
  /** Location of the image file */
341
- storageItem?: string | number | boolean;
428
+ storageItem?: unknown;
342
429
  /** Optional: Specific model version to use */
343
430
  modelName?: string;
344
431
  }
345
432
  /**
346
- * Contains synced analytics data for marketplace listings. Backend stores this in marketplace_analytics_snapshots table and indexes to ELK. Works with any marketplace provider.
433
+ * Contains IP verification results including trademark risk, copyright risk, detected brands/franchises, and analysis confidence scores
347
434
  */
348
- export interface MarketplaceAnalyticsSyncCompletedMessage {
349
- /** BullMQ job ID from original request */
350
- originalJobId?: string;
351
- /** Marketplace provider type (etsy, ebay, etc.) */
352
- marketplaceProvider?: string;
353
- /** Sync result (SUCCESS, PARTIAL_SUCCESS, or FAILED) */
435
+ export interface IpCheckCompletedMessage {
436
+ /** Model UUID that was analyzed */
437
+ modelId?: string;
438
+ /** Owner user ID */
439
+ ownerId?: string;
440
+ /** Type of entity checked: 'model' or 'metamodel' */
441
+ entityType?: string;
442
+ /** Overall IP check outcome: 'clear', 'flagged', or 'error' */
354
443
  status?: string;
355
- /** Number of listings successfully synced */
356
- syncedCount?: string | number | boolean;
357
- /** Number of listings that failed */
358
- errorCount?: string | number | boolean;
359
- /** Analytics for each synced listing */
360
- results?: Array<Record<string, string | number | boolean>>;
361
- /** Errors for failed listings */
362
- errors?: Array<Record<string, string | number | boolean>>;
363
- /** When sync completed (ISO 8601) */
364
- syncedAt?: string;
365
- /** When next automatic sync should occur (ISO 8601) */
366
- nextScheduledSync?: string;
444
+ /** Detected trademark infringement risk level: 'none', 'low', 'medium', 'high' */
445
+ trademarkRisk?: string;
446
+ /** Detected copyright infringement risk level: 'none', 'low', 'medium', 'high' */
447
+ copyrightRisk?: string;
448
+ /** Brand names detected in model name or content */
449
+ matchedBrands?: string[];
450
+ /** Franchise/character names detected */
451
+ matchedFranchises?: string[];
452
+ /** Number of visually similar models found */
453
+ similarModelsCount?: number;
454
+ /** Overall confidence score for the analysis (0.0-1.0) */
455
+ confidence?: number;
456
+ /** Risk score as 0-100 integer (FR-024: >70 HIGH, 40-70 MEDIUM, <40 LOW) */
457
+ riskScorePercent?: number;
458
+ /** Overall risk level: 'none', 'low', 'medium', 'high' */
459
+ riskLevel?: string;
460
+ /** Recommended action: 'block' (HIGH risk), 'warn' (MEDIUM risk), 'allow' (LOW/NONE risk) */
461
+ recommendation?: string;
462
+ /** Suggested modifications to reduce IP risk */
463
+ suggestedChanges?: {
464
+ title?: string;
465
+ tagsToRemove?: string[];
466
+ descriptionChanges?: string;
467
+ };
468
+ /** Detailed results from each heuristic check */
469
+ heuristicResults?: {
470
+ perceptualHash?: {
471
+ executed?: boolean;
472
+ matchesFound?: number;
473
+ highestSimilarity?: number;
474
+ flagged?: boolean;
475
+ };
476
+ trademark?: {
477
+ executed?: boolean;
478
+ brandsDetected?: string[];
479
+ flagged?: boolean;
480
+ };
481
+ franchise?: {
482
+ executed?: boolean;
483
+ franchisesDetected?: string[];
484
+ flagged?: boolean;
485
+ };
486
+ reverseSearch?: {
487
+ executed?: boolean;
488
+ provider?: string;
489
+ matchesFound?: number;
490
+ commercialMatchesFound?: number;
491
+ flagged?: boolean;
492
+ };
493
+ };
494
+ /** Error details if status is 'error' */
495
+ error?: {
496
+ code?: string;
497
+ message?: string;
498
+ };
499
+ /** Total processing time in milliseconds */
500
+ processingDurationMs?: number;
367
501
  }
368
502
  /**
369
- * Syncs analytics data from marketplace API for one or more listings. Fetches views, favorites, sales, revenue, and traffic source data. Can sync: specific listings, all user listings, or shop-level analytics. Works with any marketplace provider that supports analytics (etsy, ebay, etc.).
503
+ * Triggers intellectual property verification analysis for a model thumbnail, detecting potential trademark and copyright issues using perceptual hashing, text analysis, and optional reverse image search.
370
504
  */
371
- export interface MarketplaceAnalyticsSyncRequestMessage {
372
- /** Marketplace provider type (etsy, ebay, etc.) */
373
- marketplaceProvider?: string;
374
- /** UUID of the marketplace connection configuration */
375
- marketplaceConnectionId?: string;
376
- /** Internal listing UUIDs to sync. Empty array = sync all for user. */
377
- listingIds?: Array<Record<string, string | number | boolean>>;
378
- /** UUID of user whose listings to sync (if listingIds empty) */
379
- userId?: string;
380
- /** External marketplace shop ID for shop-level analytics */
381
- externalShopId?: string;
382
- /** Date range for historical analytics */
383
- timeRange?: Record<string, string | number | boolean>;
384
- /** Optional sync configuration */
385
- syncOptions?: Record<string, string | number | boolean>;
386
- /** Encrypted marketplace credentials (retrieved from marketplaceConnectionId) */
387
- marketplaceCredentials?: Record<string, string | number | boolean>;
388
- /** Callback URL for completion notification */
389
- webhookUrl?: string;
505
+ export interface IpCheckRequestMessage {
506
+ /** Unique identifier for the model to analyze */
507
+ modelId?: string;
508
+ /** User ID who owns the model */
509
+ ownerId?: string;
510
+ /** Type of entity being checked: 'model' or 'metamodel' */
511
+ entityType?: string;
512
+ /** Name of the model for trademark/franchise text detection */
513
+ modelName?: string;
514
+ /** Model tags for IP reference detection */
515
+ tags?: string[];
516
+ /** Model description for text-based IP analysis */
517
+ description?: string;
518
+ /** URL to fetch the thumbnail image for visual analysis */
519
+ thumbnailUrl?: string;
520
+ /** Path to thumbnail in MinIO if stored internally */
521
+ minioPath?: string;
522
+ /** Optional additional images for more comprehensive analysis (e.g., 360° views) */
523
+ additionalImageUrls?: string[];
524
+ /** Optional analysis configuration */
525
+ analysisOptions?: {
526
+ enableExternalSearch?: boolean;
527
+ strictMode?: boolean;
528
+ skipHeuristics?: string[];
529
+ };
390
530
  }
391
531
  /**
392
532
  * Notification that marketplace connection sync has completed. Contains updated connection metadata, profile information, and sync statistics.
@@ -406,15 +546,42 @@ export interface MarketplaceConnectionSyncCompletedMessage {
406
546
  /** Type of sync that was performed */
407
547
  syncType?: string;
408
548
  /** Updated connection information */
409
- connectionData?: Record<string, string | number | boolean>;
549
+ connectionData?: {
550
+ status?: string;
551
+ shopName?: string;
552
+ shopUrl?: string;
553
+ shopId?: string;
554
+ permissions?: string[];
555
+ rateLimit?: {
556
+ remaining?: number;
557
+ resetAt?: string;
558
+ };
559
+ };
410
560
  /** Available marketplace categories */
411
- categories?: Array<Record<string, string | number | boolean>>;
561
+ categories?: Array<{
562
+ id?: string;
563
+ name?: string;
564
+ path?: string;
565
+ level?: number;
566
+ }>;
412
567
  /** Sync operation statistics */
413
- statistics?: Record<string, string | number | boolean>;
568
+ statistics?: {
569
+ duration?: number;
570
+ itemsSynced?: number;
571
+ errors?: Array<{
572
+ type?: string;
573
+ message?: string;
574
+ timestamp?: string;
575
+ }>;
576
+ };
414
577
  /** When sync completed */
415
578
  completedAt?: string;
416
579
  /** Error details if sync failed */
417
- error?: Record<string, string | number | boolean>;
580
+ error?: {
581
+ code?: string;
582
+ message?: string;
583
+ details?: Record<string, unknown>;
584
+ };
418
585
  }
419
586
  /**
420
587
  * Requests synchronization of marketplace connection data including: - Profile information and shop details - Account status and permissions - Available categories and shipping profiles - Rate limits and API quotas
@@ -437,7 +604,10 @@ export interface MarketplaceConnectionSyncRequestMessage {
437
604
  /** Webhook URL to call when sync completes */
438
605
  webhookUrl?: string;
439
606
  /** Additional context data */
440
- metadata?: Record<string, string | number | boolean>;
607
+ metadata?: {
608
+ source?: string;
609
+ retryCount?: number;
610
+ };
441
611
  }
442
612
  /**
443
613
  * Notification that marketplace credential rotation has completed. Contains the rotation results, new credential metadata, and any issues encountered.
@@ -459,19 +629,62 @@ export interface MarketplaceCredentialRotationCompletedMessage {
459
629
  /** Original reason for rotation */
460
630
  reason?: string;
461
631
  /** Metadata about new credentials */
462
- newCredentials?: Record<string, string | number | boolean>;
632
+ newCredentials?: {
633
+ tokenType?: string;
634
+ createdAt?: string;
635
+ expiresAt?: string;
636
+ scope?: string[];
637
+ testResult?: {
638
+ tested?: boolean;
639
+ success?: boolean;
640
+ testedAt?: string;
641
+ testError?: string;
642
+ };
643
+ };
463
644
  /** Status of previous credentials */
464
- oldCredentials?: Record<string, string | number | boolean>;
645
+ oldCredentials?: {
646
+ revoked?: boolean;
647
+ revokedAt?: string;
648
+ preservedUntil?: string;
649
+ };
465
650
  /** Details of the rotation operation */
466
- operationDetails?: Record<string, string | number | boolean>;
651
+ operationDetails?: {
652
+ duration?: number;
653
+ attempts?: number;
654
+ method?: string;
655
+ completedAt?: string;
656
+ };
467
657
  /** Connection status after credential rotation */
468
- connectionStatus?: Record<string, string | number | boolean>;
658
+ connectionStatus?: {
659
+ status?: string;
660
+ lastTest?: {
661
+ success?: boolean;
662
+ timestamp?: string;
663
+ error?: string;
664
+ };
665
+ permissions?: string[];
666
+ };
469
667
  /** Information about next scheduled rotation */
470
- nextRotation?: Record<string, string | number | boolean>;
668
+ nextRotation?: {
669
+ scheduledAt?: string;
670
+ reason?: string;
671
+ reminderAt?: string;
672
+ };
471
673
  /** Error details if rotation failed */
472
- error?: Record<string, string | number | boolean>;
674
+ error?: {
675
+ code?: string;
676
+ message?: string;
677
+ details?: Record<string, unknown>;
678
+ retryable?: boolean;
679
+ nextRetryAt?: string;
680
+ };
473
681
  /** Notifications sent as part of rotation */
474
- notifications?: Array<Record<string, string | number | boolean>>;
682
+ notifications?: Array<{
683
+ type?: string;
684
+ recipient?: string;
685
+ status?: string;
686
+ sentAt?: string;
687
+ }>;
475
688
  }
476
689
  /**
477
690
  * Requests rotation/refresh of marketplace connection credentials. This is used for: - OAuth token refresh when tokens are near expiry - API key rotation for enhanced security - Re-authentication after connection errors - Scheduled credential updates
@@ -491,9 +704,20 @@ export interface MarketplaceCredentialRotationRequestMessage {
491
704
  /** How urgently the rotation is needed */
492
705
  urgency?: string;
493
706
  /** Current credential metadata (no actual secrets) */
494
- currentCredentials?: Record<string, string | number | boolean>;
707
+ currentCredentials?: {
708
+ tokenType?: string;
709
+ expiresAt?: string;
710
+ lastUsedAt?: string;
711
+ errorsSinceLastRotation?: number;
712
+ };
495
713
  /** Rotation configuration options */
496
- options?: Record<string, string | number | boolean>;
714
+ options?: {
715
+ preserveOldToken?: boolean;
716
+ testNewCredentials?: boolean;
717
+ notifyUser?: boolean;
718
+ retryOnFailure?: boolean;
719
+ maxRetries?: number;
720
+ };
497
721
  /** Unique request identifier */
498
722
  requestId?: string;
499
723
  /** Webhook URL for completion notification */
@@ -501,7 +725,70 @@ export interface MarketplaceCredentialRotationRequestMessage {
501
725
  /** When this rotation was scheduled (if scheduled) */
502
726
  scheduledAt?: string;
503
727
  /** Additional request context */
504
- metadata?: Record<string, string | number | boolean>;
728
+ metadata?: {
729
+ source?: string;
730
+ originalError?: {
731
+ code?: string;
732
+ message?: string;
733
+ timestamp?: string;
734
+ };
735
+ };
736
+ }
737
+ /**
738
+ * Response from marketplace intelligence scraping.
739
+ Contains aggregated similarity data from marketplace searches.
740
+
741
+ Consumed by worker-backend to update pipeline context before
742
+ sellability analysis runs.
743
+
744
+ */
745
+ export interface MarketplaceIntelligenceCompletedMessage {
746
+ /** UUID of the model that was researched */
747
+ modelId: string;
748
+ /** UUID of the model owner */
749
+ ownerId: string;
750
+ /** Result status */
751
+ status: string;
752
+ /** Aggregated market intelligence across all scraped marketplaces */
753
+ marketData?: {
754
+ totalListingsFound?: number;
755
+ averagePrice?: number;
756
+ priceRange?: {
757
+ min?: number;
758
+ max?: number;
759
+ median?: number;
760
+ };
761
+ averageRating?: number;
762
+ averageSalesCount?: number;
763
+ topTags?: string[];
764
+ competitorCount?: number;
765
+ hasDigitalDownloads?: boolean;
766
+ bestSellerPercentage?: number;
767
+ };
768
+ /** Results per marketplace */
769
+ marketplaceBreakdown?: Array<{
770
+ marketplace?: string;
771
+ listingsFound?: number;
772
+ averagePrice?: number;
773
+ topResult?: {
774
+ title?: string;
775
+ price?: number;
776
+ url?: string;
777
+ favorites?: number;
778
+ };
779
+ }>;
780
+ /** How saturated the market is for this model type (0=unique, 100=very common) */
781
+ similarityScore?: number;
782
+ /** Error information if status is FAILED */
783
+ error?: {
784
+ code?: string;
785
+ message?: string;
786
+ failedMarketplaces?: string[];
787
+ };
788
+ /** When the analysis completed */
789
+ analyzedAt?: string;
790
+ /** Version of the intelligence collector */
791
+ analysisVersion?: string;
505
792
  }
506
793
  /**
507
794
  * Public marketplace intelligence data scraped from external marketplaces.
@@ -527,13 +814,48 @@ export interface MarketplaceIntelligenceEventMessage {
527
814
  /** Marketplace-native listing ID */
528
815
  externalId: string;
529
816
  /** Core listing information */
530
- listing: Record<string, string | number | boolean>;
817
+ listing: {
818
+ title: string;
819
+ price: number;
820
+ currency: string;
821
+ url: string;
822
+ thumbnailUrl: string;
823
+ };
531
824
  /** Public engagement and sales metrics */
532
- metrics?: Record<string, string | number | boolean>;
825
+ metrics?: {
826
+ favorites?: number;
827
+ reviewsCount?: number;
828
+ averageRating?: number;
829
+ views?: number;
830
+ salesCount?: number;
831
+ salesVelocity?: number;
832
+ sentimentScore?: number;
833
+ };
533
834
  /** Additional listing context and categorization */
534
- metadata?: Record<string, string | number | boolean>;
835
+ metadata?: {
836
+ tags?: string[];
837
+ materials?: string[];
838
+ shopName?: string;
839
+ shopLocation?: string;
840
+ isDigital?: boolean;
841
+ isBestseller?: boolean;
842
+ isAd?: boolean;
843
+ isPopularNow?: boolean;
844
+ isStarSeller?: boolean;
845
+ hasFreeShipping?: boolean;
846
+ originalPrice?: number;
847
+ discountPercent?: number;
848
+ shopRating?: number;
849
+ shopReviewsCount?: number;
850
+ reviews?: string[];
851
+ };
535
852
  /** Search context that found this listing */
536
- queryContext?: Record<string, string | number | boolean>;
853
+ queryContext?: {
854
+ searchQuery?: string;
855
+ pageNumber?: number;
856
+ position?: number;
857
+ filters?: Record<string, unknown>;
858
+ };
537
859
  /** ISO 8601 timestamp when data was scraped */
538
860
  collectedAt: string;
539
861
  /** Version of collector that scraped this data */
@@ -541,6 +863,48 @@ export interface MarketplaceIntelligenceEventMessage {
541
863
  /** Method used for scraping */
542
864
  scrapingMethod?: string;
543
865
  }
866
+ /**
867
+ * Triggers automated marketplace scraping to find similar/competing listings
868
+ for a given model. This is a pipeline stage that runs after metadata generation
869
+ to inform sellability analysis with real market data.
870
+
871
+ The worker-analytic-collector (or marketplace-connectors worker) will:
872
+ 1. Use model metadata (title, tags, category) to build search queries
873
+ 2. Scrape connected marketplaces (Etsy, eBay, etc.) for similar listings
874
+ 3. Emit marketplace-intelligence-event results for Elasticsearch indexing
875
+ 4. Return aggregated similarity data to the pipeline context
876
+
877
+ Pipeline integration:
878
+ - Triggered after: metadata-generation (needs model title/tags/category)
879
+ - Results feed into: sellability-analysis (market positioning data)
880
+
881
+ */
882
+ export interface MarketplaceIntelligenceRequestMessage {
883
+ /** UUID of the model to research */
884
+ modelId: string;
885
+ /** UUID of the model owner */
886
+ ownerId: string;
887
+ /** Model metadata used to build marketplace search queries */
888
+ searchContext?: {
889
+ title?: string;
890
+ tags?: string[];
891
+ category?: string;
892
+ description?: string;
893
+ materials?: string[];
894
+ };
895
+ /** Configuration for the marketplace scraping */
896
+ scrapingOptions?: {
897
+ targetMarketplaces?: string[];
898
+ maxResultsPerMarketplace?: number;
899
+ maxPages?: number;
900
+ includeMetrics?: boolean;
901
+ includeReviews?: boolean;
902
+ };
903
+ /** Pipeline execution ID for correlation */
904
+ pipelineId?: string;
905
+ /** Pipeline execution UUID for correlation */
906
+ executionId?: string;
907
+ }
544
908
  /**
545
909
  * Notifies backend that marketplace description generation completed. Contains generated description with metadata tracking (AI model, confidence, generation timestamp) and suggested price.
546
910
  */
@@ -554,9 +918,21 @@ export interface MarketplaceListingDescriptionGenerationCompletedMessage {
554
918
  /** SEO-optimized marketplace description (3-5 sentences) */
555
919
  description: string;
556
920
  /** Content generation metadata for tracking */
557
- metadata: Record<string, string | number | boolean>;
921
+ metadata: {
922
+ source: string;
923
+ generatedAt: string;
924
+ aiModel: string;
925
+ confidence: number;
926
+ };
558
927
  /** Volume-based price calculation for 3D printed item */
559
- suggestedPrice?: Record<string, string | number | boolean>;
928
+ suggestedPrice?: {
929
+ suggestedPrice?: number;
930
+ currency?: string;
931
+ materialCost?: number;
932
+ laborCost?: number;
933
+ marketplaceMarkup?: number;
934
+ breakdown?: Record<string, unknown>;
935
+ };
560
936
  /** Error message if generation failed */
561
937
  error?: string;
562
938
  }
@@ -577,11 +953,17 @@ export interface MarketplaceListingDescriptionGenerationRequestMessage {
577
953
  /** Callback URL for completion notification */
578
954
  webhookUrl?: string;
579
955
  /** Technical analysis data for context */
580
- technicalMetadata?: Record<string, string | number | boolean>;
956
+ technicalMetadata?: {
957
+ vertices?: number;
958
+ faces?: number;
959
+ volumeMm3?: number;
960
+ dimensionsMm?: number[];
961
+ isWatertight?: boolean;
962
+ };
581
963
  /** URLs to 360-degree thumbnail views */
582
- thumbnailUrls?: Array<Record<string, string | number | boolean>>;
964
+ thumbnailUrls?: string[];
583
965
  /** Currently assigned tags for context */
584
- existingTags?: Array<Record<string, string | number | boolean>>;
966
+ existingTags?: string[];
585
967
  /** Current classification for context */
586
968
  existingCategory?: string;
587
969
  /** Desired tone/voice for the listing (e.g., 'professional', 'playful') */
@@ -589,7 +971,7 @@ export interface MarketplaceListingDescriptionGenerationRequestMessage {
589
971
  /** Target geographic market (e.g., 'US', 'EU') */
590
972
  targetMarket?: string;
591
973
  /** Specific keywords to include */
592
- keywords?: Array<Record<string, string | number | boolean>>;
974
+ keywords?: string[];
593
975
  }
594
976
  /**
595
977
  * Notification that marketplace listing sync operation has completed. Contains detailed results of the sync including created/updated listings, errors encountered, and performance statistics.
@@ -609,15 +991,56 @@ export interface MarketplaceListingSyncCompletedMessage {
609
991
  /** Direction of sync that was performed */
610
992
  syncDirection?: string;
611
993
  /** Detailed sync operation statistics */
612
- statistics?: Record<string, string | number | boolean>;
994
+ statistics?: {
995
+ duration?: number;
996
+ listingsProcessed?: number;
997
+ listingsCreated?: number;
998
+ listingsUpdated?: number;
999
+ listingsSkipped?: number;
1000
+ listingsFailed?: number;
1001
+ imagesProcessed?: number;
1002
+ variationsProcessed?: number;
1003
+ };
613
1004
  /** Detailed sync results by operation */
614
- results?: Record<string, string | number | boolean>;
1005
+ results?: {
1006
+ pull?: {
1007
+ listingsRetrieved?: number;
1008
+ newListingsCreated?: number;
1009
+ existingListingsUpdated?: number;
1010
+ };
1011
+ push?: {
1012
+ listingsPushed?: number;
1013
+ listingsCreated?: number;
1014
+ listingsUpdated?: number;
1015
+ };
1016
+ };
615
1017
  /** Details of successfully processed listings */
616
- successfulListings?: Array<Record<string, string | number | boolean>>;
1018
+ successfulListings?: Array<{
1019
+ internalId?: string;
1020
+ externalId?: string;
1021
+ title?: string;
1022
+ operation?: string;
1023
+ timestamp?: string;
1024
+ }>;
617
1025
  /** Details of listings that failed to sync */
618
- failedListings?: Array<Record<string, string | number | boolean>>;
1026
+ failedListings?: Array<{
1027
+ internalId?: string;
1028
+ externalId?: string;
1029
+ title?: string;
1030
+ error?: {
1031
+ code?: string;
1032
+ message?: string;
1033
+ details?: Record<string, unknown>;
1034
+ };
1035
+ timestamp?: string;
1036
+ }>;
619
1037
  /** Non-listing-specific errors encountered */
620
- errors?: Array<Record<string, string | number | boolean>>;
1038
+ errors?: Array<{
1039
+ type?: string;
1040
+ message?: string;
1041
+ timestamp?: string;
1042
+ details?: Record<string, unknown>;
1043
+ }>;
621
1044
  /** When sync operation completed */
622
1045
  completedAt?: string;
623
1046
  /** When next sync is recommended */
@@ -640,11 +1063,17 @@ export interface MarketplaceListingSyncRequestMessage {
640
1063
  /** Scope of listings to sync */
641
1064
  syncScope?: string;
642
1065
  /** Specific listing IDs to sync (if syncScope=specific) */
643
- listingIds?: Array<Record<string, string | number | boolean>>;
1066
+ listingIds?: string[];
644
1067
  /** External marketplace listing IDs to sync */
645
- externalListingIds?: Array<Record<string, string | number | boolean>>;
1068
+ externalListingIds?: string[];
646
1069
  /** Sync configuration options */
647
- options?: Record<string, string | number | boolean>;
1070
+ options?: {
1071
+ includeInactive?: boolean;
1072
+ includeImages?: boolean;
1073
+ includeVariations?: boolean;
1074
+ includeAnalytics?: boolean;
1075
+ batchSize?: number;
1076
+ };
648
1077
  /** Processing priority */
649
1078
  priority?: string;
650
1079
  /** Unique request identifier */
@@ -652,7 +1081,11 @@ export interface MarketplaceListingSyncRequestMessage {
652
1081
  /** Webhook URL for completion notification */
653
1082
  webhookUrl?: string;
654
1083
  /** Additional request context */
655
- metadata?: Record<string, string | number | boolean>;
1084
+ metadata?: {
1085
+ source?: string;
1086
+ scheduledSync?: boolean;
1087
+ retryCount?: number;
1088
+ };
656
1089
  }
657
1090
  /**
658
1091
  * Notifies backend that marketplace tags generation completed. Contains generated tags optimized for discoverability with metadata tracking.
@@ -663,9 +1096,14 @@ export interface MarketplaceListingTagsGenerationCompletedMessage {
663
1096
  /** Type of entity processed */
664
1097
  entityType: string;
665
1098
  /** Generated searchability tags (style, technical, usage keywords) */
666
- tags: Array<Record<string, string | number | boolean>>;
1099
+ tags: string[];
667
1100
  /** Content generation metadata for tracking */
668
- metadata: Record<string, string | number | boolean>;
1101
+ metadata: {
1102
+ source: string;
1103
+ generatedAt: string;
1104
+ aiModel: string;
1105
+ confidence: number;
1106
+ };
669
1107
  /** Error message if generation failed */
670
1108
  error?: string;
671
1109
  }
@@ -686,11 +1124,17 @@ export interface MarketplaceListingTagsGenerationRequestMessage {
686
1124
  /** Callback URL for completion notification */
687
1125
  webhookUrl?: string;
688
1126
  /** Technical analysis data for tag generation */
689
- technicalMetadata?: Record<string, string | number | boolean>;
1127
+ technicalMetadata?: {
1128
+ vertices?: number;
1129
+ faces?: number;
1130
+ volumeMm3?: number;
1131
+ dimensionsMm?: number[];
1132
+ isWatertight?: boolean;
1133
+ };
690
1134
  /** URLs to 360-degree thumbnail views for visual analysis */
691
- thumbnailUrls?: Array<Record<string, string | number | boolean>>;
1135
+ thumbnailUrls?: string[];
692
1136
  /** Currently assigned tags to supplement or replace */
693
- existingTags?: Array<Record<string, string | number | boolean>>;
1137
+ existingTags?: string[];
694
1138
  /** Current classification for category-based tags */
695
1139
  existingCategory?: string;
696
1140
  /** Maximum number of tags for marketplace (e.g., 13 for Etsy) */
@@ -700,7 +1144,7 @@ export interface MarketplaceListingTagsGenerationRequestMessage {
700
1144
  /** Artistic style of the model (e.g., 'realistic', 'low-poly') */
701
1145
  style?: string;
702
1146
  /** Intended uses for the model */
703
- useCases?: Array<Record<string, string | number | boolean>>;
1147
+ useCases?: string[];
704
1148
  }
705
1149
  /**
706
1150
  * Notifies backend that marketplace title generation completed. Contains generated title with metadata tracking.
@@ -713,7 +1157,12 @@ export interface MarketplaceListingTitleGenerationCompletedMessage {
713
1157
  /** Marketplace-optimized title */
714
1158
  title: string;
715
1159
  /** Content generation metadata for tracking */
716
- metadata: Record<string, string | number | boolean>;
1160
+ metadata: {
1161
+ source: string;
1162
+ generatedAt: string;
1163
+ aiModel: string;
1164
+ confidence: number;
1165
+ };
717
1166
  /** Error message if generation failed */
718
1167
  error?: string;
719
1168
  }
@@ -734,9 +1183,13 @@ export interface MarketplaceListingTitleGenerationRequestMessage {
734
1183
  /** Callback URL for completion notification */
735
1184
  webhookUrl?: string;
736
1185
  /** Technical analysis data for context */
737
- technicalMetadata?: Record<string, string | number | boolean>;
1186
+ technicalMetadata?: {
1187
+ vertices?: number;
1188
+ faces?: number;
1189
+ dimensionsMm?: number[];
1190
+ };
738
1191
  /** Currently assigned tags for SEO keywords */
739
- existingTags?: Array<Record<string, string | number | boolean>>;
1192
+ existingTags?: string[];
740
1193
  /** Current classification for categorization */
741
1194
  existingCategory?: string;
742
1195
  /** Maximum character count for marketplace (e.g., 140 for Etsy) */
@@ -746,7 +1199,7 @@ export interface MarketplaceListingTitleGenerationRequestMessage {
746
1199
  /** Target geographic market (e.g., 'US', 'EU') */
747
1200
  targetMarket?: string;
748
1201
  /** Specific keywords to include */
749
- keywords?: Array<Record<string, string | number | boolean>>;
1202
+ keywords?: string[];
750
1203
  }
751
1204
  /**
752
1205
  * Result of a listing update operation
@@ -759,7 +1212,7 @@ export interface MarketplaceListingUpdateCompletedMessage {
759
1212
  /** Status of the update (success, failed) */
760
1213
  status?: string;
761
1214
  /** Result details from the marketplace API */
762
- result?: Record<string, string | number | boolean>;
1215
+ result?: Record<string, unknown>;
763
1216
  /** Error message if failed */
764
1217
  error?: string;
765
1218
  }
@@ -772,65 +1225,21 @@ export interface MarketplaceListingUpdateRequestMessage {
772
1225
  /** External ID of the listing to update */
773
1226
  listingId?: string;
774
1227
  /** Fields to update */
775
- updates?: Record<string, string | number | boolean>;
1228
+ updates?: {
1229
+ price?: number;
1230
+ quantity?: number;
1231
+ title?: string;
1232
+ description?: string;
1233
+ tags?: string[];
1234
+ };
776
1235
  /** User credentials for the marketplace */
777
- credentials?: Record<string, string | number | boolean>;
778
- }
779
- /**
780
- * Indicates completion of marketplace listing publication. Contains external listing ID and URL, or error details if failed. Works with any marketplace provider (etsy, ebay, etc.).
781
- */
782
- export interface MarketplacePublishListingCompletedMessage {
783
- /** BullMQ job ID from original request */
784
- originalJobId?: string;
785
- /** Internal marketplace_items UUID */
786
- listingId?: string;
787
- /** UUID of the metamodel that was published */
788
- metamodelId?: string;
789
- /** Marketplace provider type (etsy, ebay, etc.) */
790
- marketplaceProvider?: string;
791
- /** Material variant name */
792
- materialName?: string;
793
- /** Publication result (SUCCESS or FAILED) */
794
- status?: string;
795
- /** External marketplace listing ID (only if status=SUCCESS) */
796
- externalListingId?: string;
797
- /** URL to view listing on marketplace (only if status=SUCCESS) */
798
- externalListingUrl?: string;
799
- /** External marketplace file ID (only if status=SUCCESS) */
800
- externalFileId?: string;
801
- /** Error details (only if status=FAILED) */
802
- error?: Record<string, string | number | boolean>;
803
- /** When the listing was created (ISO 8601, only if status=SUCCESS) */
804
- publishedAt?: string;
805
- /** Processing time in milliseconds */
806
- processingDuration?: string | number | boolean;
807
- }
808
- /**
809
- * Publishes a single metamodel listing to a marketplace for a specific material variant. Creates listing, uploads digital file, and returns external listing ID. This message is enqueued for EACH material variant when publishing a metamodel. The marketplace type (etsy, ebay, etc.) is determined by the marketplaceProvider field.
810
- */
811
- export interface MarketplacePublishListingRequestMessage {
812
- /** Internal marketplace_items table UUID */
813
- listingId?: string;
814
- /** UUID of the metamodel being published */
815
- metamodelId?: string;
816
- /** UUID of the user who owns the metamodel */
817
- ownerId?: string;
818
- /** Marketplace provider type (etsy, ebay, leboncoin, etc.) */
819
- marketplaceProvider?: string;
820
- /** UUID of the marketplace connection configuration */
821
- marketplaceConnectionId?: string;
822
- /** Material-specific listing configuration */
823
- materialVariant?: Record<string, string | number | boolean>;
824
- /** Common listing information shared across variants */
825
- baseListingData?: Record<string, string | number | boolean>;
826
- /** Publishing configuration (marketplace-specific options) */
827
- publishOptions?: Record<string, string | number | boolean>;
828
- /** Encrypted marketplace credentials (retrieved from marketplaceConnectionId) */
829
- marketplaceCredentials?: Record<string, string | number | boolean>;
830
- /** Digital file to upload */
831
- fileMetadata?: Record<string, string | number | boolean>;
832
- /** Callback URL for completion notification */
833
- webhookUrl?: string;
1236
+ credentials?: {
1237
+ access_token?: string;
1238
+ refresh_token?: string;
1239
+ expires_at?: number;
1240
+ api_key?: string;
1241
+ api_secret?: string;
1242
+ };
834
1243
  }
835
1244
  /**
836
1245
  * Notifies that a batch media download has been completed.
@@ -841,13 +1250,36 @@ export interface MediaBatchDownloadCompletedMessage {
841
1250
  /** The final status of the batch download operation. */
842
1251
  status: string;
843
1252
  /** List of successfully processed files. */
844
- processedFiles?: Array<Record<string, string | number | boolean>>;
1253
+ processedFiles?: Array<{
1254
+ originalPath: string;
1255
+ originalName?: string;
1256
+ s3Location: {
1257
+ bucket?: string;
1258
+ key?: string;
1259
+ url?: string;
1260
+ };
1261
+ processedType?: string;
1262
+ originalSize?: number;
1263
+ processedSize?: number;
1264
+ compressionRatio?: number;
1265
+ }>;
845
1266
  /** List of files that failed to process. */
846
- failedFiles?: Array<Record<string, string | number | boolean>>;
1267
+ failedFiles?: Array<{
1268
+ path?: string;
1269
+ error?: string;
1270
+ }>;
847
1271
  /** Timestamp when the batch processing completed. */
848
1272
  processedAt: string;
849
1273
  /** Statistics about the batch processing. */
850
- statistics?: Record<string, string | number | boolean>;
1274
+ statistics?: {
1275
+ totalFiles?: number;
1276
+ successfulFiles?: number;
1277
+ failedFiles?: number;
1278
+ totalOriginalSize?: number;
1279
+ totalProcessedSize?: number;
1280
+ averageCompressionRatio?: number;
1281
+ processingDuration?: number;
1282
+ };
851
1283
  }
852
1284
  /**
853
1285
  * Request to download and process a batch of media files from a storage provider. Images are compressed and resized to specified dimensions, converted to WebP format. Text files and documents are processed and stored with metadata. All processed files are uploaded to MinIO S3 storage under the media/{batchId}/ prefix.
@@ -871,13 +1303,28 @@ export interface MediaBatchDownloadRequestMessage {
871
1303
  storageConnectionId?: string;
872
1304
  /** Decrypted credentials for the storage provider (Fat Payload pattern). Required when downloadStrategy is 'storage_provider'.
873
1305
  */
874
- credentials?: Record<string, string | number | boolean>;
1306
+ credentials?: {
1307
+ provider?: string;
1308
+ accessToken?: string;
1309
+ refreshToken?: string;
1310
+ clientId?: string;
1311
+ clientSecret?: string;
1312
+ host?: string;
1313
+ username?: string;
1314
+ password?: string;
1315
+ port?: number;
1316
+ };
875
1317
  /** Array of media files to download and process. Must contain at least one file. Each file includes metadata for identification and processing.
876
1318
  */
877
- mediaFiles?: Array<Record<string, string | number | boolean>>;
1319
+ mediaFiles?: Array<unknown>;
878
1320
  /** Optional compression settings that override deployment environment defaults. If not provided, uses values from MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT, IMAGE_QUALITY, and OUTPUT_FORMAT environment variables.
879
1321
  */
880
- compressionSettings?: Record<string, string | number | boolean>;
1322
+ compressionSettings?: {
1323
+ maxWidth?: number;
1324
+ maxHeight?: number;
1325
+ imageQuality?: number;
1326
+ outputFormat?: string;
1327
+ };
881
1328
  }
882
1329
  /**
883
1330
  * Handles metamodel metadata generation completion. Contains AI-generated metadata and aggregated technical analysis.
@@ -886,9 +1333,99 @@ export interface MetamodelMetadataGenerationCompletedMessage {
886
1333
  /** The unique identifier for the metamodel */
887
1334
  metamodelId: string;
888
1335
  /** AI-generated metadata for the metamodel */
889
- metadata: Record<string, string | number | boolean>;
1336
+ metadata: {
1337
+ classification: {
1338
+ primary_category?: string;
1339
+ sub_category?: string;
1340
+ confidence?: number;
1341
+ reasoning?: string[];
1342
+ };
1343
+ printTechnology: {
1344
+ recommended?: string;
1345
+ confidence?: number;
1346
+ reasoning?: string[];
1347
+ constituentsAnalysis?: {
1348
+ fdmCompatible?: number;
1349
+ resinRequired?: number;
1350
+ totalParts?: number;
1351
+ };
1352
+ };
1353
+ franchise: {
1354
+ name?: string;
1355
+ universe?: string;
1356
+ confidence?: number;
1357
+ licensingInfo?: string;
1358
+ };
1359
+ tagDataJson: {
1360
+ style?: string[];
1361
+ technical?: string[];
1362
+ source?: string[];
1363
+ quality?: string[];
1364
+ scale?: string[];
1365
+ usage?: string[];
1366
+ custom?: string[];
1367
+ };
1368
+ assemblyMetadata: {
1369
+ totalParts?: number;
1370
+ complexity?: string;
1371
+ estimatedAssemblyTime?: number;
1372
+ requiresGlue?: boolean;
1373
+ requiresPainting?: boolean;
1374
+ requiresSupports?: boolean;
1375
+ instructions?: {
1376
+ url?: string;
1377
+ embedded?: string;
1378
+ };
1379
+ };
1380
+ aiGenerationMetadata: {
1381
+ workerVersion?: string;
1382
+ ollamaModels?: string[];
1383
+ totalResponses?: number;
1384
+ processingTimeSeconds?: number;
1385
+ promptTokens?: number;
1386
+ completionTokens?: number;
1387
+ generatedAt?: string;
1388
+ };
1389
+ generatedDescription: string;
1390
+ pricing: Record<string, unknown>;
1391
+ marketplaceListingsJson: Record<string, unknown>;
1392
+ };
890
1393
  /** Aggregated technical analysis from constituent models */
891
- technicalMetadata: Record<string, string | number | boolean>;
1394
+ technicalMetadata: {
1395
+ totalVertices: number;
1396
+ totalFaces: number;
1397
+ totalEdges: number;
1398
+ averageDetailLevel: string;
1399
+ assembledBoundingBox: {
1400
+ width?: number;
1401
+ height?: number;
1402
+ depth?: number;
1403
+ originalUnit?: string;
1404
+ };
1405
+ totalVolumeCubicMm: number;
1406
+ totalSurfaceAreaSqMm: number;
1407
+ allPartsManifold: boolean;
1408
+ lowestQualityScore: number;
1409
+ lowestPrintabilityScore: number;
1410
+ partsRequiringRepair: number;
1411
+ partsWithThinWalls: number;
1412
+ constituentModels: Array<{
1413
+ modelId?: string;
1414
+ name?: string;
1415
+ orderIndex?: number;
1416
+ purpose?: string;
1417
+ isOptional?: boolean;
1418
+ }>;
1419
+ validationStatus: {
1420
+ allPartsPresent?: boolean;
1421
+ allPartsAnalyzed?: boolean;
1422
+ assemblyInstructionsComplete?: boolean;
1423
+ minimumQualityMet?: boolean;
1424
+ readyForMarketplace?: boolean;
1425
+ };
1426
+ analyzedAt: string;
1427
+ analysisVersion: string;
1428
+ };
892
1429
  }
893
1430
  /**
894
1431
  * Handles metamodel metadata generation requests via Ollama. Aggregates data from constituent models and generates AI-enhanced metadata.
@@ -897,7 +1434,7 @@ export interface MetamodelMetadataGenerationRequestMessage {
897
1434
  /** The unique identifier for the metamodel */
898
1435
  metamodelId?: string;
899
1436
  /** Array of model IDs that compose this metamodel */
900
- constituentModelIds?: Array<Record<string, string | number | boolean>>;
1437
+ constituentModelIds?: string[];
901
1438
  /** The name of the metamodel */
902
1439
  name?: string;
903
1440
  /** The owner's user ID */
@@ -905,7 +1442,19 @@ export interface MetamodelMetadataGenerationRequestMessage {
905
1442
  /** The library containing this metamodel */
906
1443
  libraryId?: string;
907
1444
  /** Enriched metadata for constituent models (includes storage items) */
908
- constituentModels?: Array<Record<string, string | number | boolean>>;
1445
+ constituentModels?: Array<{
1446
+ modelId?: string;
1447
+ name?: string;
1448
+ storageConnectionId?: string;
1449
+ storageItems?: Array<{
1450
+ path?: string;
1451
+ mimeType?: string;
1452
+ size?: number;
1453
+ s3Key?: string;
1454
+ bucket?: string;
1455
+ isImage?: boolean;
1456
+ }>;
1457
+ }>;
909
1458
  /** Optional webhook URL for async completion notification */
910
1459
  webhookUrl?: string;
911
1460
  }
@@ -927,7 +1476,7 @@ export interface ModelAnalyticsCollectionRequestMessage {
927
1476
  /** Sub-category for more specific targeting */
928
1477
  subCategory?: string;
929
1478
  /** Relevant tags from metamodel metadata (max 10) */
930
- tags?: Array<Record<string, string | number | boolean>>;
1479
+ tags?: string[];
931
1480
  /** Franchise name if detected (e.g., "Dungeons & Dragons") */
932
1481
  franchise?: string;
933
1482
  /** Classification confidence score */
@@ -948,13 +1497,29 @@ export interface ModelDiscoveryFolderProcessedEventMessage {
948
1497
  /** The path to the processed folder. */
949
1498
  folderPath?: string;
950
1499
  /** A list of files discovered in the folder. */
951
- discoveredFiles?: Array<Record<string, string | number | boolean>>;
1500
+ discoveredFiles?: Array<{
1501
+ path: string;
1502
+ name: string;
1503
+ size: number;
1504
+ modifiedAt: string;
1505
+ }>;
952
1506
  /** A signature representing the state of the folder. */
953
- folderSignature?: Record<string, string | number | boolean>;
1507
+ folderSignature?: {
1508
+ hash: string;
1509
+ calculatedAt: string;
1510
+ };
954
1511
  /** The timestamp when the folder was processed. */
955
1512
  processedAt?: string;
956
1513
  /** Statistics about the processed folder. */
957
- statistics?: Record<string, string | number | boolean>;
1514
+ statistics?: {
1515
+ totalFiles: number;
1516
+ modelFiles: number;
1517
+ mediaFiles: number;
1518
+ accessoryFiles: number;
1519
+ totalFolders: number;
1520
+ totalSize: number;
1521
+ processingDuration: number;
1522
+ };
958
1523
  }
959
1524
  /**
960
1525
  * Handles model discovery scan found events.
@@ -969,22 +1534,34 @@ export interface ModelDiscoveryScanFoundEventMessage {
969
1534
  /** A description of the model. */
970
1535
  description?: string;
971
1536
  /** An array of file types associated with the model. */
972
- fileTypes?: Array<Record<string, string | number | boolean>>;
1537
+ fileTypes?: string[];
973
1538
  /** The size of the model file in bytes. */
974
1539
  size?: number;
975
1540
  /** The storage location of the model. */
976
- storageLocation?: Record<string, string | number | boolean>;
1541
+ storageLocation?: {
1542
+ storageConnectionId: string;
1543
+ path: string;
1544
+ libraryId: string;
1545
+ ownerId: string;
1546
+ };
977
1547
  /** The type of the storage provider. */
978
1548
  providerType?: string;
979
1549
  /** A flexible object for additional metadata. */
980
- metadata?: Record<string, string | number | boolean>;
1550
+ metadata?: Record<string, unknown>;
981
1551
  }
982
1552
  /**
983
1553
  * Handles model discovery scan progress events.
984
1554
  */
985
1555
  export interface ModelDiscoveryScanProgressEventMessage {
986
1556
  /** Contains the discovery scan progress details. */
987
- payload?: Record<string, string | number | boolean>;
1557
+ payload?: {
1558
+ jobId: string;
1559
+ storageConnectionId: string;
1560
+ status: string;
1561
+ message: string;
1562
+ progress: number;
1563
+ error?: string;
1564
+ };
988
1565
  }
989
1566
  /**
990
1567
  * Handles model discovery scan requests events.
@@ -999,30 +1576,34 @@ export interface ModelDiscoveryScanRequestMessage {
999
1576
  /** The specific path within the storage connection to scan for this library. */
1000
1577
  path?: string;
1001
1578
  /** Decrypted credentials for the storage provider. */
1002
- credentials?: Record<string, string | number | boolean>;
1579
+ credentials?: Record<string, unknown>;
1003
1580
  /** Configuration for the storage connection (e.g. scanRootPath). */
1004
- configuration?: Record<string, string | number | boolean>;
1581
+ configuration?: Record<string, unknown>;
1005
1582
  }
1006
1583
  /**
1007
- * Request to index a 3D model for similarity search.
1584
+ * DEPRECATED (2026-02-18) FR-023 retired. Merge 3D rendering into worker-file-vectorize.
1008
1585
  */
1009
1586
  export interface ModelFinderIndexRequestMessage {
1010
1587
  /** */
1011
1588
  modelId?: string;
1012
1589
  /** */
1013
- storageItem?: string | number | boolean;
1590
+ storageItem?: unknown;
1014
1591
  }
1015
1592
  /**
1016
- * Response containing search results from the model finder.
1593
+ * DEPRECATED (2026-02-18) FR-023 retired. Merge 3D rendering into worker-file-vectorize.
1017
1594
  */
1018
1595
  export interface ModelFinderResponseMessage {
1019
1596
  /** */
1020
1597
  requestId?: string;
1021
1598
  /** */
1022
- results?: Array<Record<string, string | number | boolean>>;
1599
+ results?: Array<{
1600
+ modelId?: string;
1601
+ similarity?: number;
1602
+ metamodelIds?: string[];
1603
+ }>;
1023
1604
  }
1024
1605
  /**
1025
- * Request to search for similar 3D models.
1606
+ * DEPRECATED (2026-02-18) FR-023 retired. Merge 3D rendering into worker-file-vectorize.
1026
1607
  */
1027
1608
  export interface ModelFinderSearchRequestMessage {
1028
1609
  /** Optional: Search using an existing model as reference */
@@ -1030,7 +1611,7 @@ export interface ModelFinderSearchRequestMessage {
1030
1611
  /** Optional: Search using an uploaded image */
1031
1612
  referenceImageId?: string;
1032
1613
  /** */
1033
- limit?: string | number | boolean;
1614
+ limit?: number;
1034
1615
  }
1035
1616
  /**
1036
1617
  * Notifies backend that enriched marketplace metadata generation completed. Backend updates Model entity with generated description, tags, classification, etc.
@@ -1039,7 +1620,12 @@ export interface ModelMetadataGenerationCompletedMessage {
1039
1620
  /** UUID of the model that was processed. */
1040
1621
  modelId: string;
1041
1622
  /** Enriched marketplace metadata generated by LLM. */
1042
- metadata: Record<string, string | number | boolean>;
1623
+ metadata: {
1624
+ description: string;
1625
+ tags: string[];
1626
+ primaryCategory: string;
1627
+ subCategory: string;
1628
+ };
1043
1629
  }
1044
1630
  /**
1045
1631
  * Generates enriched marketplace metadata (SEO descriptions, tags, categories) for 3D models using LLM vision analysis. Worker receives all necessary data in the payload (Model, TechnicalMetadata, Thumbnails) and does NOT query the database. Prerequisites: file download, technical metadata, and thumbnail generation must be complete before this message is sent.
@@ -1048,20 +1634,89 @@ export interface ModelMetadataGenerationRequestMessage {
1048
1634
  /** UUID of the model (reference only) */
1049
1635
  modelId?: string;
1050
1636
  /** Core model entity data */
1051
- model?: Record<string, string | number | boolean>;
1637
+ model?: {
1638
+ name?: string;
1639
+ fileName?: string;
1640
+ fileSize?: number;
1641
+ ownerId?: string;
1642
+ };
1052
1643
  /** Geometric and technical analysis results */
1053
- technicalMetadata?: Record<string, string | number | boolean>;
1644
+ technicalMetadata?: {
1645
+ vertices?: number;
1646
+ faces?: number;
1647
+ volumeMm3?: number;
1648
+ dimensionsMm?: number[];
1649
+ isWatertight?: boolean;
1650
+ boundingBox?: Record<string, unknown>;
1651
+ };
1054
1652
  /** List of 360 degree thumbnail views (URLs or paths) */
1055
- thumbnails?: Array<Record<string, string | number | boolean>>;
1653
+ thumbnails?: Array<{
1654
+ id?: string;
1655
+ url?: string;
1656
+ angle?: number;
1657
+ }>;
1056
1658
  }
1057
1659
  /**
1058
1660
  * Handles model metamodel detection found with hierarchical relationships.
1059
1661
  */
1060
1662
  export interface ModelMetamodelDetectionFoundMessage {
1061
1663
  /** List of metamodel nodes in hierarchical structure (roots and children). */
1062
- metamodels: Array<Record<string, string | number | boolean>>;
1664
+ metamodels: Array<{
1665
+ internalId: string;
1666
+ name: string;
1667
+ storageItemIds?: string[];
1668
+ childMetamodelIds?: string[];
1669
+ parentMetamodelId?: string;
1670
+ confidenceScore: number;
1671
+ libraryId: string;
1672
+ mediaBatchId?: string;
1673
+ metaModelType?: string;
1674
+ metadata?: {
1675
+ level?: number;
1676
+ sku?: string;
1677
+ scale?: string;
1678
+ creator?: string;
1679
+ isVariant?: boolean;
1680
+ partType?: string;
1681
+ source?: string;
1682
+ thingId?: string;
1683
+ url?: string;
1684
+ thumbnail?: string;
1685
+ mediaUrls?: Array<{
1686
+ url: string;
1687
+ name?: string;
1688
+ type?: string;
1689
+ metadata?: {
1690
+ mediaType?: string;
1691
+ isPrimary?: boolean;
1692
+ width?: number;
1693
+ height?: number;
1694
+ thingId?: string;
1695
+ fileId?: string;
1696
+ };
1697
+ }>;
1698
+ };
1699
+ }>;
1063
1700
  /** EKG edges derived from Louvain clustering (OPTIONAL - new field) */
1064
- ekgEdges?: Array<Record<string, string | number | boolean>>;
1701
+ ekgEdges?: Array<{
1702
+ sourceMetamodelId: string;
1703
+ targetId?: string;
1704
+ targetType?: string;
1705
+ massFunction: {
1706
+ related?: number;
1707
+ unrelated?: number;
1708
+ uncertainty?: number;
1709
+ };
1710
+ heuristicContributions?: Array<{
1711
+ name?: string;
1712
+ belief?: number;
1713
+ }>;
1714
+ louvainMetadata?: {
1715
+ communityId?: string;
1716
+ modularity?: number;
1717
+ edgeWeight?: number;
1718
+ };
1719
+ }>;
1065
1720
  }
1066
1721
  /**
1067
1722
  * Handles model metamodel detection requests.
@@ -1072,15 +1727,91 @@ export interface ModelMetamodelDetectionRequestMessage {
1072
1727
  /** The path to the folder that was processed. */
1073
1728
  folderPath: string;
1074
1729
  /** A list of files discovered in the folder. Worker should check this first, then manifestUrl. */
1075
- discoveredFiles?: Array<Record<string, string | number | boolean>>;
1730
+ discoveredFiles?: Array<{
1731
+ path: string;
1732
+ name: string;
1733
+ size: number;
1734
+ modifiedAt: string;
1735
+ }>;
1076
1736
  /** URL to a JSON file containing the list of discovered files (for large folders) */
1077
1737
  manifestUrl?: string;
1078
1738
  /** A signature representing the state of the folder. */
1079
- folderSignature: Record<string, string | number | boolean>;
1739
+ folderSignature: {
1740
+ hash: string;
1741
+ calculatedAt: string;
1742
+ };
1080
1743
  /** The timestamp when the folder was processed. */
1081
1744
  processedAt: string;
1082
1745
  /** Statistics about the processed folder. */
1083
- statistics: Record<string, string | number | boolean>;
1746
+ statistics: {
1747
+ totalFiles: number;
1748
+ modelFiles: number;
1749
+ mediaFiles: number;
1750
+ accessoryFiles: number;
1751
+ totalFolders: number;
1752
+ totalSize: number;
1753
+ processingDuration: number;
1754
+ };
1755
+ }
1756
+ /**
1757
+ * Reports completion of 3D print analysis — contains estimation, printability, and cost breakdown per FR-022
1758
+ */
1759
+ export interface ModelPrintAnalysisCompletedMessage {
1760
+ /** ID of the original analysis request job */
1761
+ originalJobId?: string;
1762
+ /** UUID of the analysed model */
1763
+ modelId?: string;
1764
+ /** Analysis result status */
1765
+ status?: string;
1766
+ /** Error description when status is FAILED */
1767
+ errorMessage?: string;
1768
+ /** Material type used for estimation */
1769
+ material?: string;
1770
+ /** Quality preset used */
1771
+ quality?: string;
1772
+ /** Estimated total print time in minutes */
1773
+ printTimeMinutes?: number;
1774
+ /** Estimated material consumption in grams (body only) */
1775
+ materialGrams?: number;
1776
+ /** Whether the model requires support structures */
1777
+ needsSupport?: boolean;
1778
+ /** Estimated support material in grams */
1779
+ supportMaterialGrams?: number;
1780
+ /** Percentage of surface area with overhangs > 45° */
1781
+ overhangPercentage?: number;
1782
+ /** Thinnest detected wall in millimeters */
1783
+ minWallThicknessMm?: number;
1784
+ /** Solid volume of the mesh in cm³ */
1785
+ solidVolumeCm3?: number;
1786
+ /** Total surface area in cm² */
1787
+ surfaceAreaCm2?: number;
1788
+ /** Bounding box in millimeters */
1789
+ boundingBox?: {
1790
+ x?: number;
1791
+ y?: number;
1792
+ z?: number;
1793
+ };
1794
+ /** Total estimated production cost in EUR */
1795
+ estimatedCostEUR?: number;
1796
+ /** Granular cost breakdown per WF-009 MaterialCostCalculatorService */
1797
+ costBreakdown?: Record<string, unknown>;
1798
+ }
1799
+ /**
1800
+ * Triggers 3D print analysis for a model — estimates print time, material usage, support needs, and cost breakdown per FR-022
1801
+ */
1802
+ export interface ModelPrintAnalysisRequestMessage {
1803
+ /** UUID of the model to analyse */
1804
+ modelId?: string;
1805
+ /** UUID of the user who owns the model */
1806
+ ownerId?: string;
1807
+ /** Material type enum value (e.g. PLA, PETG, RESIN_STANDARD) */
1808
+ material?: string;
1809
+ /** Print quality preset */
1810
+ quality?: string;
1811
+ /** URL called when analysis completes or fails */
1812
+ webhookUrl?: string;
1813
+ /** Path to model in MinIO storage for geometry analysis (e.g. 'raw_models/{modelId}/original.glb') */
1814
+ minioPath?: string;
1084
1815
  }
1085
1816
  /**
1086
1817
  * Contains sellability analysis results including Etsy-specific recommendations, material pricing, and marketplace compatibility scores
@@ -1093,21 +1824,67 @@ export interface ModelSellabilityAnalysisCompletedMessage {
1093
1824
  /** Overall sellability score (0-100) */
1094
1825
  sellabilityScore?: number;
1095
1826
  /** Pricing analysis and recommendations with material-specific pricing (v2.0.0) */
1096
- pricingRecommendations?: Record<string, string | number | boolean>;
1827
+ pricingRecommendations?: {
1828
+ suggestedPrice?: number;
1829
+ priceRange?: {
1830
+ min?: number;
1831
+ max?: number;
1832
+ median?: number;
1833
+ };
1834
+ competitorAverage?: number;
1835
+ materialPricing?: Record<string, unknown>;
1836
+ factors?: Array<{
1837
+ factor?: string;
1838
+ impact?: string;
1839
+ description?: string;
1840
+ }>;
1841
+ };
1097
1842
  /** Recommended marketplaces with Etsy-specific scoring (v2.0.0) */
1098
- marketplaceRecommendations?: Array<Record<string, string | number | boolean>>;
1843
+ marketplaceRecommendations?: Array<{
1844
+ marketplace?: string;
1845
+ compatibilityScore?: number;
1846
+ reasoning?: string;
1847
+ estimatedReach?: number;
1848
+ platformFee?: number;
1849
+ etsySpecificData?: {
1850
+ categoryFitScore?: number;
1851
+ recommendedMaterials?: string[];
1852
+ estimatedTimeToFirstSale?: string;
1853
+ };
1854
+ }>;
1099
1855
  /** Market demand insights */
1100
- demandAnalysis?: Record<string, string | number | boolean>;
1856
+ demandAnalysis?: {
1857
+ categoryDemand?: string;
1858
+ trendingScore?: number;
1859
+ searchVolume?: number;
1860
+ competitionLevel?: string;
1861
+ trendDirection?: string;
1862
+ };
1101
1863
  /** Quality-related factors affecting sellability */
1102
- qualityFactors?: Record<string, string | number | boolean>;
1864
+ qualityFactors?: {
1865
+ technicalQuality?: number;
1866
+ printability?: number;
1867
+ uniqueness?: number;
1868
+ marketFit?: number;
1869
+ };
1103
1870
  /** Actionable recommendations to improve sellability */
1104
- recommendations?: Array<Record<string, string | number | boolean>>;
1871
+ recommendations?: Array<{
1872
+ category?: string;
1873
+ priority?: string;
1874
+ title?: string;
1875
+ description?: string;
1876
+ expectedImpact?: string;
1877
+ }>;
1105
1878
  /** Analysis completion timestamp (ISO 8601) */
1106
1879
  analyzedAt?: string;
1107
1880
  /** Analysis algorithm version */
1108
1881
  analysisVersion?: string;
1109
1882
  /** Error information if analysis failed */
1110
- error?: Record<string, string | number | boolean>;
1883
+ error?: {
1884
+ code?: string;
1885
+ message?: string;
1886
+ details?: Record<string, unknown>;
1887
+ };
1111
1888
  }
1112
1889
  /**
1113
1890
  * Analyzes a metamodel to determine sellability score, pricing recommendations, and optimal marketplace selection. Enhanced with Etsy-specific analysis including competitor pricing, category demand trends, and material suitability.
@@ -1118,11 +1895,21 @@ export interface ModelSellabilityAnalysisRequestMessage {
1118
1895
  /** UUID of the user who owns the metamodel */
1119
1896
  ownerId?: string;
1120
1897
  /** Full metamodel data including technical metadata, enriched metadata, and child models. Injected by backend to avoid DB access. */
1121
- metamodelData?: Record<string, string | number | boolean>;
1898
+ metamodelData?: Record<string, unknown>;
1122
1899
  /** URL to a JSON manifest containing the metamodel data if it is too large for the message payload. */
1123
1900
  manifestUrl?: string;
1124
1901
  /** Optional analysis configuration */
1125
- analysisOptions?: Record<string, string | number | boolean>;
1902
+ analysisOptions?: {
1903
+ targetMarketplaces?: string[];
1904
+ competitorAnalysis?: boolean;
1905
+ demandAnalysis?: boolean;
1906
+ includeChildModels?: boolean;
1907
+ etsyAnalysisOptions?: {
1908
+ analyzeMaterialSuitability?: boolean;
1909
+ fetchEtsyTrends?: boolean;
1910
+ competitorCount?: number;
1911
+ };
1912
+ };
1126
1913
  }
1127
1914
  /**
1128
1915
  * Handles completion of 3D model semantic analysis with generated tags and similarity results.
@@ -1135,15 +1922,61 @@ export interface ModelSemanticAnalysisCompletedMessage {
1135
1922
  /** Final processing status. */
1136
1923
  processingStatus?: string;
1137
1924
  /** Generated semantic metadata and analysis results. */
1138
- semanticMetadata?: Record<string, string | number | boolean>;
1925
+ semanticMetadata?: {
1926
+ semanticTags?: Array<{
1927
+ tagName?: string;
1928
+ confidence?: number;
1929
+ category?: string;
1930
+ }>;
1931
+ embedding?: number[];
1932
+ similarModels?: Array<{
1933
+ modelId?: string;
1934
+ similarity?: number;
1935
+ metadata?: Record<string, unknown>;
1936
+ }>;
1937
+ geometricFeatures?: {
1938
+ vertexCount?: number;
1939
+ faceCount?: number;
1940
+ volume?: number;
1941
+ surfaceArea?: number;
1942
+ boundingBox?: {
1943
+ width?: number;
1944
+ height?: number;
1945
+ depth?: number;
1946
+ };
1947
+ isWatertight?: boolean;
1948
+ hasTextureCoords?: boolean;
1949
+ complexity?: string;
1950
+ };
1951
+ };
1139
1952
  /** Processing performance metrics. */
1140
- processingTime?: Record<string, string | number | boolean>;
1953
+ processingTime?: {
1954
+ totalTimeMs?: number;
1955
+ geometryTimeMs?: number;
1956
+ neuralTimeMs?: number;
1957
+ searchTimeMs?: number;
1958
+ };
1141
1959
  /** Processing quality and confidence metrics. */
1142
- qualityMetrics?: Record<string, string | number | boolean>;
1960
+ qualityMetrics?: {
1961
+ overallConfidence?: number;
1962
+ tagCount?: number;
1963
+ duplicateDetected?: boolean;
1964
+ knowledgeBaseUpdated?: boolean;
1965
+ };
1143
1966
  /** Error information if processing failed. */
1144
- error?: Record<string, string | number | boolean>;
1967
+ error?: {
1968
+ message?: string;
1969
+ category?: string;
1970
+ retryable?: boolean;
1971
+ technicalDetails?: string;
1972
+ };
1145
1973
  /** Additional debug information for troubleshooting. */
1146
- debugInfo?: Record<string, string | number | boolean>;
1974
+ debugInfo?: {
1975
+ workerVersion?: string;
1976
+ processingNode?: string;
1977
+ gpuUsed?: boolean;
1978
+ memoryUsageMb?: number;
1979
+ };
1147
1980
  }
1148
1981
  /**
1149
1982
  * Handles 3D model semantic analysis requests using ULIP-2 neural networks and FAISS vector similarity search.
@@ -1164,7 +1997,13 @@ export interface ModelSemanticAnalysisRequestMessage {
1164
1997
  /** The type of the storage provider (S3, GoogleDrive, SFTP, etc). */
1165
1998
  storageProviderType?: string;
1166
1999
  /** Configuration options for semantic analysis. */
1167
- processingOptions?: Record<string, string | number | boolean>;
2000
+ processingOptions?: {
2001
+ pointCloudSize?: number;
2002
+ similarityThreshold?: number;
2003
+ similarityK?: number;
2004
+ enableDuplicateDetection?: boolean;
2005
+ generateThumbnail?: boolean;
2006
+ };
1168
2007
  /** Processing priority (1=highest, 10=lowest). */
1169
2008
  priority?: number;
1170
2009
  /** Optional webhook URL for completion notification. */
@@ -1183,15 +2022,20 @@ export interface ModelTechnicalMetadataCompletedMessage {
1183
2022
  /** Analysis completion status */
1184
2023
  status?: string;
1185
2024
  /** Number of vertices in the mesh */
1186
- vertices?: string | number | boolean;
2025
+ vertices?: number;
1187
2026
  /** Number of faces/polygons in the mesh */
1188
- faces?: string | number | boolean;
2027
+ faces?: number;
1189
2028
  /** Number of edges in the mesh */
1190
- edges?: string | number | boolean;
2029
+ edges?: number;
1191
2030
  /** Visual detail level based on polygon density */
1192
2031
  detailLevel?: string;
1193
2032
  /** 3D bounding box dimensions in millimeters */
1194
- boundingBox?: Record<string, string | number | boolean>;
2033
+ boundingBox?: {
2034
+ width?: number;
2035
+ height?: number;
2036
+ depth?: number;
2037
+ originalUnit?: string;
2038
+ };
1195
2039
  /** Model volume in cubic millimeters (for material calculation) */
1196
2040
  volumeCubicMm?: number;
1197
2041
  /** Total surface area in square millimeters */
@@ -1203,13 +2047,13 @@ export interface ModelTechnicalMetadataCompletedMessage {
1203
2047
  /** Is the mesh watertight/manifold? Critical for 3D printing (true = printable) */
1204
2048
  manifold?: boolean;
1205
2049
  /** Number of non-manifold edges (repair needed if > 0) */
1206
- nonManifoldEdges?: string | number | boolean;
2050
+ nonManifoldEdges?: number;
1207
2051
  /** Number of holes/boundary loops in the mesh (0 = closed mesh) */
1208
- holes?: string | number | boolean;
2052
+ holes?: number;
1209
2053
  /** Number of faces with inverted normals (causes rendering/slicing issues) */
1210
- flippedNormals?: string | number | boolean;
2054
+ flippedNormals?: number;
1211
2055
  /** Number of self-intersecting faces (0 = clean geometry) */
1212
- selfIntersections?: string | number | boolean;
2056
+ selfIntersections?: number;
1213
2057
  /** Overall quality score 0-100 (100 = perfect for printing, <60 needs repair) */
1214
2058
  qualityScore?: number;
1215
2059
  /** Printability score 0-100 (considers supports, orientation, size constraints) */
@@ -1217,17 +2061,47 @@ export interface ModelTechnicalMetadataCompletedMessage {
1217
2061
  /** Does this model require support structures for 3D printing? */
1218
2062
  requiresSupports?: boolean;
1219
2063
  /** Detected overhang areas requiring support structures */
1220
- overhangs?: Array<Record<string, string | number | boolean>>;
2064
+ overhangs?: Array<{
2065
+ angle?: number;
2066
+ area?: number;
2067
+ location?: string;
2068
+ }>;
1221
2069
  /** Estimated print time in minutes using normal quality settings (0.2mm layers, 20% infill) */
1222
- estimatedPrintTimeMinutes?: string | number | boolean;
2070
+ estimatedPrintTimeMinutes?: number;
1223
2071
  /** Print time estimates for different quality presets */
1224
- printTimeEstimates?: Record<string, string | number | boolean>;
2072
+ printTimeEstimates?: {
2073
+ draft?: number;
2074
+ normal?: number;
2075
+ highQuality?: number;
2076
+ };
1225
2077
  /** Estimated material usage in grams using 20% infill (assumes PLA density 1.24g/cm³) */
1226
2078
  estimatedMaterialGrams?: number;
1227
2079
  /** Material usage estimates for different infill percentages */
1228
- materialEstimates?: Record<string, string | number | boolean>;
2080
+ materialEstimates?: {
2081
+ infill10?: number;
2082
+ infill20?: number;
2083
+ infill50?: number;
2084
+ infill100?: number;
2085
+ };
1229
2086
  /** Recommended print orientation for minimal support material and best results */
1230
- recommendedOrientation?: Record<string, string | number | boolean>;
2087
+ recommendedOrientation?: {
2088
+ rotationX?: number;
2089
+ rotationY?: number;
2090
+ rotationZ?: number;
2091
+ reasoning?: string;
2092
+ };
2093
+ /** Slicer-derived recommended print settings based on model analysis (feeds into print job creation as defaults) */
2094
+ slicerRecommendations?: {
2095
+ layerHeightMm?: number;
2096
+ infillPercentage?: number;
2097
+ nozzleSizeMm?: number;
2098
+ printSpeedMmS?: number;
2099
+ temperatureC?: number;
2100
+ bedTemperatureC?: number;
2101
+ supportEnabled?: boolean;
2102
+ materialType?: string;
2103
+ estimatedLayerCount?: number;
2104
+ };
1231
2105
  /** Original file format unit detected from metadata or inferred from scale */
1232
2106
  originalUnit?: string;
1233
2107
  /** File format version (e.g., 'STL Binary', 'OBJ v4', 'PLY 1.0') */
@@ -1245,7 +2119,11 @@ export interface ModelTechnicalMetadataCompletedMessage {
1245
2119
  /** Confidence level of analysis results (0.0 = uncertain, 1.0 = highly confident) */
1246
2120
  analysisConfidence?: number;
1247
2121
  /** Warnings or issues detected during analysis (structured for programmatic handling) */
1248
- analysisWarnings?: Array<Record<string, string | number | boolean>>;
2122
+ analysisWarnings?: Array<{
2123
+ code?: string;
2124
+ message?: string;
2125
+ severity?: string;
2126
+ }>;
1249
2127
  /** ISO 8601 timestamp when analysis was performed (e.g., '2025-11-19T14:35:22Z') */
1250
2128
  analyzedAt?: string;
1251
2129
  /** Detailed error message if status is FAILED */
@@ -1262,13 +2140,217 @@ export interface ModelTechnicalMetadataRequestMessage {
1262
2140
  /** User ID who owns the model */
1263
2141
  ownerId?: string;
1264
2142
  /** Location of the 3D model file (legacy - used for direct download if minioPath not provided) */
1265
- storageLocation?: Record<string, string | number | boolean>;
2143
+ storageLocation?: {
2144
+ storageConnectionId: string;
2145
+ path: string;
2146
+ };
1266
2147
  /** Path to model in MinIO (e.g., 'raw_models/{modelId}/original.glb'). If provided, file will be read from MinIO instead of downloading from storage provider. */
1267
2148
  minioPath?: string;
1268
2149
  /** ID of parent file-download job (for BullMQ dependency tracking). */
1269
2150
  parentJobId?: string;
1270
2151
  /** Optional analysis configuration parameters */
1271
- analysisOptions?: Record<string, string | number | boolean>;
2152
+ analysisOptions?: {
2153
+ detailedAnalysis?: boolean;
2154
+ estimatePrintMetrics?: boolean;
2155
+ skipCache?: boolean;
2156
+ };
2157
+ }
2158
+ /**
2159
+ * Request FDM slicing simulation via OrcaSlicer (preferred) or heuristic fallback. Accepts OrcaSlicer-compatible printer/process/filament JSON profiles.
2160
+ */
2161
+ export interface SlicingFdmRequestMessage {
2162
+ /** UUID of the model */
2163
+ modelId?: string;
2164
+ /** UUID or path of the storage item to download the STL/3MF */
2165
+ storageItemId?: string;
2166
+ /** UUID of the user's slicer profile from the database */
2167
+ profileId?: string;
2168
+ /** Human-readable profile name (e.g. 'My Bambu X1C - PLA Fine') */
2169
+ profileName?: string;
2170
+ /** OrcaSlicer printer profile JSON: nozzle_diameter, bed_shape, max speeds, acceleration, retraction */
2171
+ printerProfile?: Record<string, unknown>;
2172
+ /** OrcaSlicer process profile JSON: layer_height, sparse_infill_density, wall_loops, speeds, support settings */
2173
+ processProfile?: Record<string, unknown>;
2174
+ /** OrcaSlicer filament profile JSON: filament_type, filament_density, temperature, flow_ratio, retraction */
2175
+ filamentProfile?: Record<string, unknown>;
2176
+ /** Override: layer height in mm (takes precedence over processProfile) */
2177
+ layerHeight?: number;
2178
+ /** Override: infill percentage (0-100) */
2179
+ infillPercentage?: number;
2180
+ /** Override: nozzle diameter in mm */
2181
+ nozzleDiameter?: number;
2182
+ /** Override: outer wall print speed in mm/s */
2183
+ printSpeed?: number;
2184
+ /** Override: number of wall loops / perimeters */
2185
+ wallCount?: number;
2186
+ /** Override: generate support structures */
2187
+ supportEnabled?: boolean;
2188
+ /** Override: filament density in g/cm³ (default: 1.24 PLA) */
2189
+ materialDensity?: number;
2190
+ /** URL to POST the slicing result back to */
2191
+ webhookUrl?: string;
2192
+ }
2193
+ /**
2194
+ * Result of FDM slicing simulation from OrcaSlicer (toolpath) or heuristic fallback. Contains exact physical metrics for cost calculation.
2195
+ */
2196
+ export interface SlicingFdmResultMessage {
2197
+ /** UUID of the model */
2198
+ modelId?: string;
2199
+ /** Status of the simulation */
2200
+ status?: string;
2201
+ /** Exact print time in hours (from toolpath analysis) */
2202
+ printTimeHours?: number;
2203
+ /** Total filament weight in grams (including supports) */
2204
+ materialWeightGrams?: number;
2205
+ /** Extruded material volume in cm³ */
2206
+ materialVolumeCm3?: number;
2207
+ /** Maximum Z height in mm */
2208
+ maxZHeightMM?: number;
2209
+ /** Support structure filament weight in grams */
2210
+ supportMaterialWeightGrams?: number;
2211
+ /** Total number of layers */
2212
+ layerCount?: number;
2213
+ /** Total filament extrusion length in mm */
2214
+ totalExtrusionLengthMm?: number;
2215
+ /** Engine that produced the result */
2216
+ slicingMethod?: string;
2217
+ /** Version of the slicer engine used */
2218
+ slicerVersion?: string;
2219
+ /** Name or ID of the slicer profile used */
2220
+ profileUsed?: string;
2221
+ /** Error code if simulation failed */
2222
+ errorCode?: string;
2223
+ /** Error message if simulation failed */
2224
+ errorMessage?: string;
2225
+ }
2226
+ /**
2227
+ * Request SLA/MSLA slicing simulation via PySLM cross-sectional analysis. Accepts resin printer profile with exposure, lift, and layer parameters.
2228
+ */
2229
+ export interface SlicingSlaRequestMessage {
2230
+ /** UUID of the model */
2231
+ modelId?: string;
2232
+ /** UUID or path of the storage item to download the STL/3MF */
2233
+ storageItemId?: string;
2234
+ /** SLA or MSLA */
2235
+ technology?: string;
2236
+ /** UUID of the user's slicer profile from the database */
2237
+ profileId?: string;
2238
+ /** Human-readable profile name (e.g. 'Elegoo Mars 3 - Standard Grey') */
2239
+ profileName?: string;
2240
+ /** Layer height in mm (default: 0.05) */
2241
+ layerHeight?: number;
2242
+ /** Normal layer UV exposure time in seconds (default: 2.5) */
2243
+ exposureTime?: number;
2244
+ /** Bottom/burn-in layer exposure time in seconds (default: 30) */
2245
+ bottomExposureTime?: number;
2246
+ /** Number of bottom/burn-in layers (default: 5) */
2247
+ bottomLayers?: number;
2248
+ /** Platform lift height in mm between layers (default: 5.0) */
2249
+ liftHeight?: number;
2250
+ /** Platform lift speed in mm/min (default: 60) */
2251
+ liftSpeed?: number;
2252
+ /** Platform retract speed in mm/min (default: 150) */
2253
+ retractSpeed?: number;
2254
+ /** Resin density in g/cm³ (default: 1.1) */
2255
+ resinDensity?: number;
2256
+ /** Generate support structures (default: true for SLA) */
2257
+ supportEnabled?: boolean;
2258
+ /** URL to POST the slicing result back to */
2259
+ webhookUrl?: string;
2260
+ }
2261
+ /**
2262
+ * Result of SLA/MSLA slicing simulation from PySLM cross-sectional analysis. Contains exact resin usage and print time metrics.
2263
+ */
2264
+ export interface SlicingSlaResultMessage {
2265
+ /** UUID of the model */
2266
+ modelId?: string;
2267
+ /** Status of the simulation */
2268
+ status?: string;
2269
+ /** Exact print time in hours (from cross-sectional analysis) */
2270
+ printTimeHours?: number;
2271
+ /** Total resin weight in grams (including supports) */
2272
+ materialWeightGrams?: number;
2273
+ /** Cured resin volume in cm³ (from cross-sectional area integration) */
2274
+ materialVolumeCm3?: number;
2275
+ /** Maximum Z height in mm */
2276
+ maxZHeightMM?: number;
2277
+ /** Support structure resin weight in grams */
2278
+ supportMaterialWeightGrams?: number;
2279
+ /** Total number of layers */
2280
+ layerCount?: number;
2281
+ /** Maximum cross-sectional area in mm² (affects MSLA peel force) */
2282
+ maxCrossSectionAreaMm2?: number;
2283
+ /** Engine that produced the result */
2284
+ slicingMethod?: string;
2285
+ /** Version of PySLM / trimesh used */
2286
+ slicerVersion?: string;
2287
+ /** Name or ID of the slicer profile used */
2288
+ profileUsed?: string;
2289
+ /** Error code if simulation failed */
2290
+ errorCode?: string;
2291
+ /** Error message if simulation failed */
2292
+ errorMessage?: string;
2293
+ }
2294
+ /**
2295
+ * Emitted when AI texture generation completes (success or failure). Contains artifact S3 URLs on success, or error details on failure. The credit reservation should be confirmed (success) or released (failure) based on the status.
2296
+ */
2297
+ export interface TextureGenerationCompletedMessage {
2298
+ /** The unique job identifier matching the original request. */
2299
+ jobId?: string;
2300
+ /** The ID of the model that was textured. */
2301
+ modelId?: string;
2302
+ /** The tenant who owns the model. */
2303
+ tenantId?: string;
2304
+ /** The result status of the texture generation. */
2305
+ status?: string;
2306
+ /** S3 URLs of generated texture artifacts. Present only when status is 'completed'. */
2307
+ artifacts?: {
2308
+ texturedGlb?: string;
2309
+ albedoMap?: string;
2310
+ normalMap?: string;
2311
+ roughnessMap?: string;
2312
+ };
2313
+ /** Error details. Present only when status is 'failed'. */
2314
+ error?: {
2315
+ code?: string;
2316
+ message?: string;
2317
+ stage?: string;
2318
+ retryable?: boolean;
2319
+ };
2320
+ /** Pipeline performance metrics. */
2321
+ metrics?: {
2322
+ totalDurationMs?: number;
2323
+ uvUnwrapMs?: number;
2324
+ depthExtractionMs?: number;
2325
+ diffusionMs?: number;
2326
+ pbrDecompMs?: number;
2327
+ glbExportMs?: number;
2328
+ gpuType?: string;
2329
+ vramPeakMb?: number;
2330
+ };
2331
+ /** Credit reservation ID to confirm (on success) or release (on failure). */
2332
+ creditReservationId?: string;
2333
+ }
2334
+ /**
2335
+ * Request AI-powered texture generation for a 3D model. Requires a mesh file URL and a text prompt describing the desired texture. Credits are reserved before dispatch.
2336
+ */
2337
+ export interface TextureGenerationRequestMessage {
2338
+ /** Unique job identifier for tracking. */
2339
+ jobId?: string;
2340
+ /** The unique identifier for the model to texture. */
2341
+ modelId?: string;
2342
+ /** The identifier of the tenant requesting the generation. */
2343
+ tenantId?: string;
2344
+ /** S3 URL to the source mesh file (GLB, OBJ, or STL). */
2345
+ meshUrl?: string;
2346
+ /** Text description of the desired texture (1-500 characters). Example: 'weathered bronze with green patina'. */
2347
+ prompt?: string;
2348
+ /** Style preset to guide the texture generation aesthetic. */
2349
+ stylePreset?: string;
2350
+ /** Output texture resolution (width = height in pixels). */
2351
+ resolution?: number;
2352
+ /** Credit reservation ID from the credit ledger. Must be confirmed on completion or released on failure. */
2353
+ creditReservationId?: string;
1272
2354
  }
1273
2355
  /**
1274
2356
  * Handles thumbnail generation completed.
@@ -1283,13 +2365,23 @@ export interface ThumbnailGenerationCompletedMessage {
1283
2365
  /** The path to the generated thumbnail. */
1284
2366
  thumbnailPath?: string;
1285
2367
  /** Array of 360° thumbnail view paths (16 angles) for vision-based analysis. */
1286
- thumbnail360Views?: Array<Record<string, string | number | boolean>>;
2368
+ thumbnail360Views?: Array<{
2369
+ angle_index?: number;
2370
+ index?: number;
2371
+ storage_path?: string;
2372
+ url?: string;
2373
+ }>;
1287
2374
  /** The path to the generated GLTF/GLB 3D preview file. */
1288
2375
  gltfPreviewPath?: string;
2376
+ /** The path to the generated animated MP4 preview file. */
2377
+ animatedPreviewPath?: string;
1289
2378
  /** An error message if the thumbnail generation failed. */
1290
2379
  errorMessage?: string;
1291
2380
  /** The storage location of the model. */
1292
- storageLocation?: Record<string, string | number | boolean>;
2381
+ storageLocation?: {
2382
+ storageConnectionId: string;
2383
+ path: string;
2384
+ };
1293
2385
  }
1294
2386
  /**
1295
2387
  * Handles thumbnail generation requests with customization options. Supports both storage provider downloads and MinIO-cached files.
@@ -1300,7 +2392,10 @@ export interface ThumbnailGenerationRequestMessage {
1300
2392
  /** The identifier of the user who owns the entity. */
1301
2393
  ownerId?: string;
1302
2394
  /** The storage location of the model (legacy - used for direct download if minioPath not provided). */
1303
- storageLocation?: Record<string, string | number | boolean>;
2395
+ storageLocation?: {
2396
+ storageConnectionId: string;
2397
+ path: string;
2398
+ };
1304
2399
  /** Path to model in MinIO (e.g., 'raw_models/{modelId}/original.glb'). If provided, file will be read from MinIO instead of downloading from storage provider. */
1305
2400
  minioPath?: string;
1306
2401
  /** The type of preview to generate, e.g., 'default', 'static', 'glb'. */
@@ -1310,7 +2405,24 @@ export interface ThumbnailGenerationRequestMessage {
1310
2405
  /** ID of parent file-download job (for BullMQ dependency tracking). */
1311
2406
  parentJobId?: string;
1312
2407
  /** User-defined customizations for the thumbnail. */
1313
- customization?: Record<string, string | number | boolean>;
2408
+ customization?: {
2409
+ texture?: {
2410
+ storageConnectionId?: string;
2411
+ path?: string;
2412
+ };
2413
+ background?: {
2414
+ storageConnectionId?: string;
2415
+ path?: string;
2416
+ color?: string;
2417
+ };
2418
+ watermark?: {
2419
+ storageConnectionId?: string;
2420
+ path?: string;
2421
+ text?: string;
2422
+ position?: string;
2423
+ opacity?: number;
2424
+ };
2425
+ };
1314
2426
  }
1315
2427
  /**
1316
2428
  * User engagement and onboarding tracking events for analytics and behavioral insights.
@@ -1332,6 +2444,8 @@ Used for:
1332
2444
 
1333
2445
  */
1334
2446
  export interface UserEngagementEventMessage {
2447
+ /** Schema version for forward-compatible evolution */
2448
+ eventVersion: string;
1335
2449
  /** Category of user engagement event */
1336
2450
  eventType: string;
1337
2451
  /** Specific user action performed */
@@ -1340,7 +2454,7 @@ export interface UserEngagementEventMessage {
1340
2454
  timestamp: string;
1341
2455
  /** Unique identifier of the user */
1342
2456
  userId: string;
1343
- /** User's email (hashed for privacy in analytics) */
2457
+ /** User's email — MUST be SHA-256 hashed at the producer side before publishing (GDPR/CNIL compliance). Never send raw email. */
1344
2458
  userEmail?: string;
1345
2459
  /** When the user account was created (for cohort analysis) */
1346
2460
  userCreatedAt?: string;
@@ -1348,10 +2462,26 @@ export interface UserEngagementEventMessage {
1348
2462
  userPlanTier?: string;
1349
2463
  /** User session identifier for grouping actions */
1350
2464
  sessionId?: string;
1351
- /** Request ID for correlation with logs */
2465
+ /** Request ID for correlation with backend logs */
1352
2466
  requestId?: string;
2467
+ /** Correlation ID to link engagement events across frontend and backend boundaries, and to pipeline traces */
2468
+ correlationId?: string;
1353
2469
  /** Additional context about the action */
1354
- actionDetails?: Record<string, string | number | boolean>;
2470
+ actionDetails?: {
2471
+ onboardingStep?: string;
2472
+ modelId?: string;
2473
+ modelStatus?: string;
2474
+ modelCount?: number;
2475
+ marketplace?: string;
2476
+ marketplaceListingId?: string;
2477
+ marketplaceAction?: string;
2478
+ previousPlanTier?: string;
2479
+ newPlanTier?: string;
2480
+ featureName?: string;
2481
+ featureCategory?: string;
2482
+ storageProvider?: string;
2483
+ settingChanged?: string;
2484
+ };
1355
2485
  /** Where the action originated */
1356
2486
  source?: string;
1357
2487
  /** HTTP method used */
@@ -1359,7 +2489,7 @@ export interface UserEngagementEventMessage {
1359
2489
  /** API endpoint path */
1360
2490
  httpUrl?: string;
1361
2491
  /** HTTP response status code */
1362
- httpStatusCode?: string | number | boolean;
2492
+ httpStatusCode?: number;
1363
2493
  /** Action duration in milliseconds */
1364
2494
  durationMs?: number;
1365
2495
  /** A/B test or experiment ID */
@@ -1369,7 +2499,12 @@ export interface UserEngagementEventMessage {
1369
2499
  /** Deployment environment */
1370
2500
  environment?: string;
1371
2501
  /** Client/browser information (anonymized) */
1372
- clientInfo?: Record<string, string | number | boolean>;
2502
+ clientInfo?: {
2503
+ userAgent?: string;
2504
+ platform?: string;
2505
+ browser?: string;
2506
+ browserVersion?: string;
2507
+ };
1373
2508
  }
1374
2509
  /**
1375
2510
  * Analytics event emitted by workers for tracking processing metrics, user behavior,
@@ -1403,9 +2538,13 @@ export interface WorkerAnalyticsEventMessage {
1403
2538
  /** Error message if status is failure */
1404
2539
  errorMessage?: string;
1405
2540
  /** Processing time metrics in milliseconds */
1406
- timing?: Record<string, string | number | boolean>;
2541
+ timing?: {
2542
+ queueWaitMs?: number;
2543
+ processingMs?: number;
2544
+ stages?: Record<string, number>;
2545
+ };
1407
2546
  /** Worker-specific metrics. Structure varies by eventType. */
1408
- metrics?: Record<string, string | number | boolean>;
2547
+ metrics?: Record<string, unknown>;
1409
2548
  }
1410
2549
  /**
1411
2550
  * Enriched metrics event for detailed worker monitoring, cost tracking,
@@ -1446,15 +2585,62 @@ export interface WorkerMetricsEnrichedEventMessage {
1446
2585
  /** Storage item ID (for file operations) */
1447
2586
  storageItemId?: string;
1448
2587
  /** Comprehensive timing breakdown */
1449
- timing?: Record<string, string | number | boolean>;
2588
+ timing?: {
2589
+ queueWaitMs?: number;
2590
+ processingMs?: number;
2591
+ stages?: Record<string, number>;
2592
+ };
1450
2593
  /** LLM token usage and cost breakdown */
1451
- llmUsage?: Record<string, string | number | boolean>;
2594
+ llmUsage?: {
2595
+ provider?: string;
2596
+ model?: string;
2597
+ tokensPrompt?: number;
2598
+ tokensCompletion?: number;
2599
+ tokensTotal?: number;
2600
+ costPerPromptToken?: number;
2601
+ costPerCompletionToken?: number;
2602
+ totalCostUsd?: number;
2603
+ cacheHit?: boolean;
2604
+ retries?: number;
2605
+ fallbackUsed?: boolean;
2606
+ modelLatencyMs?: number;
2607
+ };
1452
2608
  /** System resource consumption during job */
1453
- resources?: Record<string, string | number | boolean>;
2609
+ resources?: {
2610
+ cpu?: {
2611
+ peakPercent?: number;
2612
+ avgPercent?: number;
2613
+ systemTimeMs?: number;
2614
+ userTimeMs?: number;
2615
+ };
2616
+ memory?: {
2617
+ peakMb?: number;
2618
+ avgMb?: number;
2619
+ startMb?: number;
2620
+ endMb?: number;
2621
+ leakDetected?: boolean;
2622
+ };
2623
+ disk?: {
2624
+ bytesRead?: number;
2625
+ bytesWritten?: number;
2626
+ opsRead?: number;
2627
+ opsWrite?: number;
2628
+ };
2629
+ network?: {
2630
+ bytesReceived?: number;
2631
+ bytesSent?: number;
2632
+ apiCallsCount?: number;
2633
+ avgLatencyMs?: number;
2634
+ };
2635
+ };
1454
2636
  /** Worker-specific metrics (varies by worker type) */
1455
- workerMetrics?: Record<string, string | number | boolean>;
2637
+ workerMetrics?: Record<string, unknown>;
1456
2638
  /** Error details if status is failure */
1457
- error?: Record<string, string | number | boolean>;
2639
+ error?: {
2640
+ code?: string;
2641
+ message?: string;
2642
+ category?: string;
2643
+ };
1458
2644
  /** Deployment environment */
1459
2645
  environment?: string;
1460
2646
  /** Cloud region/datacenter */