@mesh-sync/worker-backend-client 4.0.19 → 4.0.24-pr.51.20260312132340

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
@@ -2,9 +2,8 @@
2
2
  * Message type constants
3
3
  */
4
4
  export declare const MessageTypes: {
5
+ readonly ANALYTICS_COLLECTION_REQUEST: "analytics-collection-request";
5
6
  readonly BACKEND_LOGGING_EVENT: "backend-logging-event";
6
- readonly EKG_EDGE_BATCH_CREATE_COMPLETED: "ekg-edge-batch-create-completed";
7
- readonly EKG_EDGE_BATCH_CREATE_REQUEST: "ekg-edge-batch-create-request";
8
7
  readonly ETSY_ANALYTICS_SYNC_COMPLETED: "etsy-analytics-sync-completed";
9
8
  readonly ETSY_ANALYTICS_SYNC_REQUEST: "etsy-analytics-sync-request";
10
9
  readonly ETSY_PUBLISH_LISTING_COMPLETED: "etsy-publish-listing-completed";
@@ -13,13 +12,15 @@ export declare const MessageTypes: {
13
12
  readonly FILE_DOWNLOAD_REQUEST: "file-download-request";
14
13
  readonly FILE_VECTORIZE_COMPLETED: "file-vectorize-completed";
15
14
  readonly FILE_VECTORIZE_REQUEST: "file-vectorize-request";
16
- readonly MARKETPLACE_ANALYTICS_SYNC_COMPLETED: "marketplace-analytics-sync-completed";
17
- 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";
18
17
  readonly MARKETPLACE_CONNECTION_SYNC_COMPLETED: "marketplace-connection-sync-completed";
19
18
  readonly MARKETPLACE_CONNECTION_SYNC_REQUEST: "marketplace-connection-sync-request";
20
19
  readonly MARKETPLACE_CREDENTIAL_ROTATION_COMPLETED: "marketplace-credential-rotation-completed";
21
20
  readonly MARKETPLACE_CREDENTIAL_ROTATION_REQUEST: "marketplace-credential-rotation-request";
21
+ readonly MARKETPLACE_INTELLIGENCE_COMPLETED: "marketplace-intelligence-completed";
22
22
  readonly MARKETPLACE_INTELLIGENCE_EVENT: "marketplace-intelligence-event";
23
+ readonly MARKETPLACE_INTELLIGENCE_REQUEST: "marketplace-intelligence-request";
23
24
  readonly MARKETPLACE_LISTING_DESCRIPTION_GENERATION_COMPLETED: "marketplace-listing-description-generation-completed";
24
25
  readonly MARKETPLACE_LISTING_DESCRIPTION_GENERATION_REQUEST: "marketplace-listing-description-generation-request";
25
26
  readonly MARKETPLACE_LISTING_SYNC_COMPLETED: "marketplace-listing-sync-completed";
@@ -30,8 +31,6 @@ export declare const MessageTypes: {
30
31
  readonly MARKETPLACE_LISTING_TITLE_GENERATION_REQUEST: "marketplace-listing-title-generation-request";
31
32
  readonly MARKETPLACE_LISTING_UPDATE_COMPLETED: "marketplace-listing-update-completed";
32
33
  readonly MARKETPLACE_LISTING_UPDATE_REQUEST: "marketplace-listing-update-request";
33
- readonly MARKETPLACE_PUBLISH_LISTING_COMPLETED: "marketplace-publish-listing-completed";
34
- readonly MARKETPLACE_PUBLISH_LISTING_REQUEST: "marketplace-publish-listing-request";
35
34
  readonly MEDIA_BATCH_DOWNLOAD_COMPLETED: "media-batch-download-completed";
36
35
  readonly MEDIA_BATCH_DOWNLOAD_REQUEST: "media-batch-download-request";
37
36
  readonly METAMODEL_METADATA_GENERATION_COMPLETED: "metamodel-metadata-generation-completed";
@@ -48,12 +47,20 @@ export declare const MessageTypes: {
48
47
  readonly MODEL_METADATA_GENERATION_REQUEST: "model-metadata-generation-request";
49
48
  readonly MODEL_METAMODEL_DETECTION_FOUND: "model-metamodel-detection-found";
50
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";
51
52
  readonly MODEL_SELLABILITY_ANALYSIS_COMPLETED: "model-sellability-analysis-completed";
52
53
  readonly MODEL_SELLABILITY_ANALYSIS_REQUEST: "model-sellability-analysis-request";
53
54
  readonly MODEL_SEMANTIC_ANALYSIS_COMPLETED: "model-semantic-analysis-completed";
54
55
  readonly MODEL_SEMANTIC_ANALYSIS_REQUEST: "model-semantic-analysis-request";
55
56
  readonly MODEL_TECHNICAL_METADATA_COMPLETED: "model-technical-metadata-completed";
56
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";
57
64
  readonly THUMBNAIL_GENERATION_COMPLETED: "thumbnail-generation-completed";
58
65
  readonly THUMBNAIL_GENERATION_REQUEST: "thumbnail-generation-request";
59
66
  readonly USER_ENGAGEMENT_EVENT: "user-engagement-event";
@@ -61,6 +68,21 @@ export declare const MessageTypes: {
61
68
  readonly WORKER_METRICS_ENRICHED_EVENT: "worker-metrics-enriched-event";
62
69
  };
63
70
  export type MessageType = typeof MessageTypes[keyof typeof MessageTypes];
71
+ /**
72
+ * Request to trigger a manual market data collection job.
73
+ Used for ad-hoc scraping of specific queries on marketplaces.
74
+
75
+ */
76
+ export interface AnalyticsCollectionRequestMessage {
77
+ /** The marketplace to scrape (etsy, ebay, etc.) */
78
+ marketplace?: string;
79
+ /** The search query to use */
80
+ query: string;
81
+ /** Collection options (pages, filters, etc.) */
82
+ options?: {
83
+ pages?: number;
84
+ };
85
+ }
64
86
  /**
65
87
  * Centralized logging event for capturing all warn/error/failure logs from meshsync-backend.
66
88
  This event is sent to ELK for centralized monitoring, alerting, and debugging.
@@ -99,7 +121,7 @@ export interface BackendLoggingEventMessage {
99
121
  /** Request URL path (without query params for privacy) */
100
122
  httpUrl?: string;
101
123
  /** HTTP response status code */
102
- httpStatusCode?: string | number | boolean;
124
+ httpStatusCode?: number;
103
125
  /** Error class/type name */
104
126
  errorType?: string;
105
127
  /** Stack trace (sanitized, no sensitive data) */
@@ -107,7 +129,14 @@ export interface BackendLoggingEventMessage {
107
129
  /** Application-specific error code for categorization */
108
130
  errorCode?: string;
109
131
  /** Additional structured context (sanitized, no PII) */
110
- 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
+ };
111
140
  /** Deployment environment */
112
141
  environment?: string;
113
142
  /** Backend service version */
@@ -117,38 +146,6 @@ export interface BackendLoggingEventMessage {
117
146
  /** Operation duration in milliseconds (if applicable) */
118
147
  durationMs?: number;
119
148
  }
120
- /**
121
- * Completion event for EKG edge batch creation with propagation results.
122
- */
123
- export interface EkgEdgeBatchCreateCompletedMessage {
124
- /** Original request ID from ekg-edge-batch-create-request */
125
- requestId: string;
126
- /** Whether the batch operation succeeded */
127
- success: boolean;
128
- /** Batch operation statistics */
129
- statistics: Record<string, string | number | boolean>;
130
- /** List of high-conflict edges requiring review */
131
- conflicts?: Array<Record<string, string | number | boolean>>;
132
- /** Errors encountered during processing */
133
- errors?: Array<Record<string, string | number | boolean>>;
134
- /** Overall graph state after this batch */
135
- graphMetrics?: Record<string, string | number | boolean>;
136
- }
137
- /**
138
- * Create multiple EKG edges with Dempster-Shafer mass functions. Triggered by metamodel detection completion.
139
- */
140
- export interface EkgEdgeBatchCreateRequestMessage {
141
- /** Unique request ID for tracking (e.g., metamodel detection job ID) */
142
- requestId: string;
143
- /** Source of the edges: metamodel-heuristic, manual, taxonomy-import, etc. */
144
- source: string;
145
- /** Batch of edges to create/update in the EKG */
146
- edges: Array<Record<string, string | number | boolean>>;
147
- /** Options for evidential edge propagation after edge creation */
148
- propagationOptions?: Record<string, string | number | boolean>;
149
- /** Optional webhook URL for async completion notification */
150
- webhookUrl?: string;
151
- }
152
149
  /**
153
150
  * Contains synced analytics data for Etsy listings. Backend stores this in etsy_analytics_snapshots table and indexes to ELK.
154
151
 
@@ -159,15 +156,42 @@ export interface EtsyAnalyticsSyncCompletedMessage {
159
156
  /** */
160
157
  status?: string;
161
158
  /** Number of listings successfully synced */
162
- syncedCount?: string | number | boolean;
159
+ syncedCount?: number;
163
160
  /** Number of listings that failed */
164
- errorCount?: string | number | boolean;
161
+ errorCount?: number;
165
162
  /** Analytics for each synced listing */
166
- 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
+ }>;
167
184
  /** New credentials if token was refreshed during operation */
168
- credentialUpdate?: Record<string, string | number | boolean>;
185
+ credentialUpdate?: {
186
+ newAccessToken?: string;
187
+ newRefreshToken?: string;
188
+ expiresIn?: number;
189
+ };
169
190
  /** Errors for failed listings */
170
- errors?: Array<Record<string, string | number | boolean>>;
191
+ errors?: Array<{
192
+ listingId?: string;
193
+ error?: string;
194
+ }>;
171
195
  /** */
172
196
  syncedAt?: string;
173
197
  /** When next automatic sync should occur */
@@ -180,19 +204,34 @@ Can sync: - Specific listings (provide listingIds) - All user listings (provide
180
204
  */
181
205
  export interface EtsyAnalyticsSyncRequestMessage {
182
206
  /** Internal listing IDs to sync. Empty = sync all for user. */
183
- listingIds?: Array<Record<string, string | number | boolean>>;
207
+ listingIds?: string[];
184
208
  /** User whose listings to sync (if listingIds empty) */
185
209
  userId?: string;
186
210
  /** Etsy shop ID for shop-level analytics */
187
211
  shopId?: string;
188
212
  /** Etsy OAuth credentials */
189
- credentials?: Record<string, string | number | boolean>;
213
+ credentials?: {
214
+ apiKey?: string;
215
+ shopId?: string;
216
+ accessToken?: string;
217
+ refreshToken?: string;
218
+ };
190
219
  /** Date range for historical analytics */
191
- timeRange?: Record<string, string | number | boolean>;
220
+ timeRange?: {
221
+ startDate: string;
222
+ endDate: string;
223
+ };
192
224
  /** */
193
- syncOptions?: Record<string, string | number | boolean>;
225
+ syncOptions?: {
226
+ includeDetailedMetrics?: boolean;
227
+ includeTrafficSources?: boolean;
228
+ includeSearchTerms?: boolean;
229
+ };
194
230
  /** Encrypted Etsy OAuth credentials */
195
- etsyCredentials?: Record<string, string | number | boolean>;
231
+ etsyCredentials?: {
232
+ accessToken: string;
233
+ shopId: string;
234
+ };
196
235
  /** */
197
236
  webhookUrl?: string;
198
237
  }
@@ -216,15 +255,24 @@ export interface EtsyPublishListingCompletedMessage {
216
255
  /** URL to view listing on Etsy (only if status=SUCCESS) */
217
256
  etsyListingUrl?: string;
218
257
  /** New credentials if token was refreshed during operation */
219
- credentialUpdate?: Record<string, string | number | boolean>;
258
+ credentialUpdate?: {
259
+ newAccessToken?: string;
260
+ newRefreshToken?: string;
261
+ expiresIn?: number;
262
+ };
220
263
  /** Etsy digital file ID (only if status=SUCCESS) */
221
264
  etsyFileId?: string;
222
265
  /** Error details (only if status=FAILED) */
223
- error?: Record<string, string | number | boolean>;
266
+ error?: {
267
+ code?: string;
268
+ message?: string;
269
+ details?: Record<string, unknown>;
270
+ retryable?: boolean;
271
+ };
224
272
  /** When the listing was created (only if status=SUCCESS) */
225
273
  publishedAt?: string;
226
274
  /** Processing time in milliseconds */
227
- processingDuration?: string | number | boolean;
275
+ processingDuration?: number;
228
276
  }
229
277
  /**
230
278
  * Publishes a single metamodel listing to Etsy for a specific material variant. Creates Etsy listing, uploads digital file, and returns external listing ID.
@@ -240,17 +288,48 @@ export interface EtsyPublishListingRequestMessage {
240
288
  /** User ID who owns the metamodel */
241
289
  ownerId?: string;
242
290
  /** Etsy OAuth credentials */
243
- credentials?: Record<string, string | number | boolean>;
291
+ credentials?: {
292
+ apiKey?: string;
293
+ shopId?: string;
294
+ accessToken?: string;
295
+ refreshToken?: string;
296
+ };
244
297
  /** Material-specific listing configuration */
245
- materialVariant?: Record<string, string | number | boolean>;
298
+ materialVariant?: {
299
+ materialName: string;
300
+ price: number;
301
+ sku?: string;
302
+ currency?: string;
303
+ };
246
304
  /** Common listing information */
247
- 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
+ };
248
315
  /** */
249
- publishOptions?: Record<string, string | number | boolean>;
316
+ publishOptions?: {
317
+ autoActivate?: boolean;
318
+ shippingProfileId?: number;
319
+ };
250
320
  /** Encrypted Etsy OAuth credentials */
251
- etsyCredentials?: Record<string, string | number | boolean>;
321
+ etsyCredentials?: {
322
+ accessToken: string;
323
+ shopId: string;
324
+ expiresAt?: string;
325
+ };
252
326
  /** Digital file to upload */
253
- fileMetadata?: Record<string, string | number | boolean>;
327
+ fileMetadata?: {
328
+ storageItemId: string;
329
+ fileName: string;
330
+ fileSize?: number;
331
+ mimeType?: string;
332
+ };
254
333
  /** Callback URL for completion notification */
255
334
  webhookUrl?: string;
256
335
  }
@@ -265,7 +344,11 @@ export interface FileDownloadCompletedMessage {
265
344
  /** The final status of the download operation. */
266
345
  status?: string;
267
346
  /** Details of the file's location in Minio S3 (present on success). */
268
- s3Location?: Record<string, string | number | boolean>;
347
+ s3Location?: {
348
+ bucket: string;
349
+ key: string;
350
+ versionId?: string;
351
+ };
269
352
  /** Contains error details if the status is FAILED. */
270
353
  errorMessage?: string;
271
354
  /** The timestamp when the download was completed or failed. */
@@ -288,13 +371,31 @@ export interface FileDownloadRequestMessage {
288
371
  /** The identifier of the user who owns the model. Optional - if not provided, will be retrieved from StorageConnection. */
289
372
  ownerId?: string;
290
373
  /** The storage location of the model. */
291
- storageLocation?: Record<string, string | number | boolean>;
374
+ storageLocation?: {
375
+ storageConnectionId: string;
376
+ path: string;
377
+ };
292
378
  /** Optional metadata from discovery. For Thingiverse, contains downloadUrl for direct file access. */
293
- metadata?: Record<string, string | number | boolean>;
379
+ metadata?: {
380
+ downloadUrl?: string;
381
+ };
294
382
  /** Decrypted credentials required for this specific download operation. Injected by the backend. */
295
- 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
+ };
296
394
  /** Destination in MinIO where file will be uploaded after download. */
297
- minioDestination?: Record<string, string | number | boolean>;
395
+ minioDestination?: {
396
+ bucket?: string;
397
+ path: string;
398
+ };
298
399
  /** Automatically enqueue thumbnail generation, technical metadata analysis, and metadata generation jobs after download completes. */
299
400
  autoEnqueueChildren?: boolean;
300
401
  /** Preview type for thumbnail generation (passed to child job). */
@@ -311,11 +412,11 @@ export interface FileVectorizeCompletedMessage {
311
412
  /** */
312
413
  fileId?: string;
313
414
  /** The computed embedding vector */
314
- vector?: Array<Record<string, string | number | boolean>>;
415
+ vector?: number[];
315
416
  /** */
316
417
  modelName?: string;
317
418
  /** Length of the vector (e.g., 512) */
318
- dimension?: string | number | boolean;
419
+ dimension?: number;
319
420
  }
320
421
  /**
321
422
  * Request to generate a vector embedding for an image file using CLIP.
@@ -324,55 +425,108 @@ export interface FileVectorizeRequestMessage {
324
425
  /** The ID of the file in the database */
325
426
  fileId?: string;
326
427
  /** Location of the image file */
327
- storageItem?: string | number | boolean;
428
+ storageItem?: unknown;
328
429
  /** Optional: Specific model version to use */
329
430
  modelName?: string;
330
431
  }
331
432
  /**
332
- * 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
333
434
  */
334
- export interface MarketplaceAnalyticsSyncCompletedMessage {
335
- /** BullMQ job ID from original request */
336
- originalJobId?: string;
337
- /** Marketplace provider type (etsy, ebay, etc.) */
338
- marketplaceProvider?: string;
339
- /** 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' */
340
443
  status?: string;
341
- /** Number of listings successfully synced */
342
- syncedCount?: string | number | boolean;
343
- /** Number of listings that failed */
344
- errorCount?: string | number | boolean;
345
- /** Analytics for each synced listing */
346
- results?: Array<Record<string, string | number | boolean>>;
347
- /** Errors for failed listings */
348
- errors?: Array<Record<string, string | number | boolean>>;
349
- /** When sync completed (ISO 8601) */
350
- syncedAt?: string;
351
- /** When next automatic sync should occur (ISO 8601) */
352
- 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;
353
501
  }
354
502
  /**
355
- * 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.
356
504
  */
357
- export interface MarketplaceAnalyticsSyncRequestMessage {
358
- /** Marketplace provider type (etsy, ebay, etc.) */
359
- marketplaceProvider?: string;
360
- /** UUID of the marketplace connection configuration */
361
- marketplaceConnectionId?: string;
362
- /** Internal listing UUIDs to sync. Empty array = sync all for user. */
363
- listingIds?: Array<Record<string, string | number | boolean>>;
364
- /** UUID of user whose listings to sync (if listingIds empty) */
365
- userId?: string;
366
- /** External marketplace shop ID for shop-level analytics */
367
- externalShopId?: string;
368
- /** Date range for historical analytics */
369
- timeRange?: Record<string, string | number | boolean>;
370
- /** Optional sync configuration */
371
- syncOptions?: Record<string, string | number | boolean>;
372
- /** Encrypted marketplace credentials (retrieved from marketplaceConnectionId) */
373
- marketplaceCredentials?: Record<string, string | number | boolean>;
374
- /** Callback URL for completion notification */
375
- 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
+ };
376
530
  }
377
531
  /**
378
532
  * Notification that marketplace connection sync has completed. Contains updated connection metadata, profile information, and sync statistics.
@@ -392,15 +546,42 @@ export interface MarketplaceConnectionSyncCompletedMessage {
392
546
  /** Type of sync that was performed */
393
547
  syncType?: string;
394
548
  /** Updated connection information */
395
- 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
+ };
396
560
  /** Available marketplace categories */
397
- categories?: Array<Record<string, string | number | boolean>>;
561
+ categories?: Array<{
562
+ id?: string;
563
+ name?: string;
564
+ path?: string;
565
+ level?: number;
566
+ }>;
398
567
  /** Sync operation statistics */
399
- 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
+ };
400
577
  /** When sync completed */
401
578
  completedAt?: string;
402
579
  /** Error details if sync failed */
403
- error?: Record<string, string | number | boolean>;
580
+ error?: {
581
+ code?: string;
582
+ message?: string;
583
+ details?: Record<string, unknown>;
584
+ };
404
585
  }
405
586
  /**
406
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
@@ -423,7 +604,10 @@ export interface MarketplaceConnectionSyncRequestMessage {
423
604
  /** Webhook URL to call when sync completes */
424
605
  webhookUrl?: string;
425
606
  /** Additional context data */
426
- metadata?: Record<string, string | number | boolean>;
607
+ metadata?: {
608
+ source?: string;
609
+ retryCount?: number;
610
+ };
427
611
  }
428
612
  /**
429
613
  * Notification that marketplace credential rotation has completed. Contains the rotation results, new credential metadata, and any issues encountered.
@@ -445,19 +629,62 @@ export interface MarketplaceCredentialRotationCompletedMessage {
445
629
  /** Original reason for rotation */
446
630
  reason?: string;
447
631
  /** Metadata about new credentials */
448
- 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
+ };
449
644
  /** Status of previous credentials */
450
- oldCredentials?: Record<string, string | number | boolean>;
645
+ oldCredentials?: {
646
+ revoked?: boolean;
647
+ revokedAt?: string;
648
+ preservedUntil?: string;
649
+ };
451
650
  /** Details of the rotation operation */
452
- operationDetails?: Record<string, string | number | boolean>;
651
+ operationDetails?: {
652
+ duration?: number;
653
+ attempts?: number;
654
+ method?: string;
655
+ completedAt?: string;
656
+ };
453
657
  /** Connection status after credential rotation */
454
- 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
+ };
455
667
  /** Information about next scheduled rotation */
456
- nextRotation?: Record<string, string | number | boolean>;
668
+ nextRotation?: {
669
+ scheduledAt?: string;
670
+ reason?: string;
671
+ reminderAt?: string;
672
+ };
457
673
  /** Error details if rotation failed */
458
- 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
+ };
459
681
  /** Notifications sent as part of rotation */
460
- notifications?: Array<Record<string, string | number | boolean>>;
682
+ notifications?: Array<{
683
+ type?: string;
684
+ recipient?: string;
685
+ status?: string;
686
+ sentAt?: string;
687
+ }>;
461
688
  }
462
689
  /**
463
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
@@ -477,9 +704,20 @@ export interface MarketplaceCredentialRotationRequestMessage {
477
704
  /** How urgently the rotation is needed */
478
705
  urgency?: string;
479
706
  /** Current credential metadata (no actual secrets) */
480
- currentCredentials?: Record<string, string | number | boolean>;
707
+ currentCredentials?: {
708
+ tokenType?: string;
709
+ expiresAt?: string;
710
+ lastUsedAt?: string;
711
+ errorsSinceLastRotation?: number;
712
+ };
481
713
  /** Rotation configuration options */
482
- options?: Record<string, string | number | boolean>;
714
+ options?: {
715
+ preserveOldToken?: boolean;
716
+ testNewCredentials?: boolean;
717
+ notifyUser?: boolean;
718
+ retryOnFailure?: boolean;
719
+ maxRetries?: number;
720
+ };
483
721
  /** Unique request identifier */
484
722
  requestId?: string;
485
723
  /** Webhook URL for completion notification */
@@ -487,7 +725,70 @@ export interface MarketplaceCredentialRotationRequestMessage {
487
725
  /** When this rotation was scheduled (if scheduled) */
488
726
  scheduledAt?: string;
489
727
  /** Additional request context */
490
- 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;
491
792
  }
492
793
  /**
493
794
  * Public marketplace intelligence data scraped from external marketplaces.
@@ -513,13 +814,48 @@ export interface MarketplaceIntelligenceEventMessage {
513
814
  /** Marketplace-native listing ID */
514
815
  externalId: string;
515
816
  /** Core listing information */
516
- listing: Record<string, string | number | boolean>;
817
+ listing: {
818
+ title: string;
819
+ price: number;
820
+ currency: string;
821
+ url: string;
822
+ thumbnailUrl: string;
823
+ };
517
824
  /** Public engagement and sales metrics */
518
- 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
+ };
519
834
  /** Additional listing context and categorization */
520
- 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
+ };
521
852
  /** Search context that found this listing */
522
- queryContext?: Record<string, string | number | boolean>;
853
+ queryContext?: {
854
+ searchQuery?: string;
855
+ pageNumber?: number;
856
+ position?: number;
857
+ filters?: Record<string, unknown>;
858
+ };
523
859
  /** ISO 8601 timestamp when data was scraped */
524
860
  collectedAt: string;
525
861
  /** Version of collector that scraped this data */
@@ -527,6 +863,48 @@ export interface MarketplaceIntelligenceEventMessage {
527
863
  /** Method used for scraping */
528
864
  scrapingMethod?: string;
529
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
+ }
530
908
  /**
531
909
  * Notifies backend that marketplace description generation completed. Contains generated description with metadata tracking (AI model, confidence, generation timestamp) and suggested price.
532
910
  */
@@ -540,9 +918,21 @@ export interface MarketplaceListingDescriptionGenerationCompletedMessage {
540
918
  /** SEO-optimized marketplace description (3-5 sentences) */
541
919
  description: string;
542
920
  /** Content generation metadata for tracking */
543
- metadata: Record<string, string | number | boolean>;
921
+ metadata: {
922
+ source: string;
923
+ generatedAt: string;
924
+ aiModel: string;
925
+ confidence: number;
926
+ };
544
927
  /** Volume-based price calculation for 3D printed item */
545
- 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
+ };
546
936
  /** Error message if generation failed */
547
937
  error?: string;
548
938
  }
@@ -563,11 +953,17 @@ export interface MarketplaceListingDescriptionGenerationRequestMessage {
563
953
  /** Callback URL for completion notification */
564
954
  webhookUrl?: string;
565
955
  /** Technical analysis data for context */
566
- technicalMetadata?: Record<string, string | number | boolean>;
956
+ technicalMetadata?: {
957
+ vertices?: number;
958
+ faces?: number;
959
+ volumeMm3?: number;
960
+ dimensionsMm?: number[];
961
+ isWatertight?: boolean;
962
+ };
567
963
  /** URLs to 360-degree thumbnail views */
568
- thumbnailUrls?: Array<Record<string, string | number | boolean>>;
964
+ thumbnailUrls?: string[];
569
965
  /** Currently assigned tags for context */
570
- existingTags?: Array<Record<string, string | number | boolean>>;
966
+ existingTags?: string[];
571
967
  /** Current classification for context */
572
968
  existingCategory?: string;
573
969
  /** Desired tone/voice for the listing (e.g., 'professional', 'playful') */
@@ -575,7 +971,7 @@ export interface MarketplaceListingDescriptionGenerationRequestMessage {
575
971
  /** Target geographic market (e.g., 'US', 'EU') */
576
972
  targetMarket?: string;
577
973
  /** Specific keywords to include */
578
- keywords?: Array<Record<string, string | number | boolean>>;
974
+ keywords?: string[];
579
975
  }
580
976
  /**
581
977
  * Notification that marketplace listing sync operation has completed. Contains detailed results of the sync including created/updated listings, errors encountered, and performance statistics.
@@ -595,15 +991,56 @@ export interface MarketplaceListingSyncCompletedMessage {
595
991
  /** Direction of sync that was performed */
596
992
  syncDirection?: string;
597
993
  /** Detailed sync operation statistics */
598
- 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
+ };
599
1004
  /** Detailed sync results by operation */
600
- 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
+ };
601
1017
  /** Details of successfully processed listings */
602
- 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
+ }>;
603
1025
  /** Details of listings that failed to sync */
604
- 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
+ }>;
605
1037
  /** Non-listing-specific errors encountered */
606
- 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
+ }>;
607
1044
  /** When sync operation completed */
608
1045
  completedAt?: string;
609
1046
  /** When next sync is recommended */
@@ -626,11 +1063,17 @@ export interface MarketplaceListingSyncRequestMessage {
626
1063
  /** Scope of listings to sync */
627
1064
  syncScope?: string;
628
1065
  /** Specific listing IDs to sync (if syncScope=specific) */
629
- listingIds?: Array<Record<string, string | number | boolean>>;
1066
+ listingIds?: string[];
630
1067
  /** External marketplace listing IDs to sync */
631
- externalListingIds?: Array<Record<string, string | number | boolean>>;
1068
+ externalListingIds?: string[];
632
1069
  /** Sync configuration options */
633
- options?: Record<string, string | number | boolean>;
1070
+ options?: {
1071
+ includeInactive?: boolean;
1072
+ includeImages?: boolean;
1073
+ includeVariations?: boolean;
1074
+ includeAnalytics?: boolean;
1075
+ batchSize?: number;
1076
+ };
634
1077
  /** Processing priority */
635
1078
  priority?: string;
636
1079
  /** Unique request identifier */
@@ -638,7 +1081,11 @@ export interface MarketplaceListingSyncRequestMessage {
638
1081
  /** Webhook URL for completion notification */
639
1082
  webhookUrl?: string;
640
1083
  /** Additional request context */
641
- metadata?: Record<string, string | number | boolean>;
1084
+ metadata?: {
1085
+ source?: string;
1086
+ scheduledSync?: boolean;
1087
+ retryCount?: number;
1088
+ };
642
1089
  }
643
1090
  /**
644
1091
  * Notifies backend that marketplace tags generation completed. Contains generated tags optimized for discoverability with metadata tracking.
@@ -649,9 +1096,14 @@ export interface MarketplaceListingTagsGenerationCompletedMessage {
649
1096
  /** Type of entity processed */
650
1097
  entityType: string;
651
1098
  /** Generated searchability tags (style, technical, usage keywords) */
652
- tags: Array<Record<string, string | number | boolean>>;
1099
+ tags: string[];
653
1100
  /** Content generation metadata for tracking */
654
- metadata: Record<string, string | number | boolean>;
1101
+ metadata: {
1102
+ source: string;
1103
+ generatedAt: string;
1104
+ aiModel: string;
1105
+ confidence: number;
1106
+ };
655
1107
  /** Error message if generation failed */
656
1108
  error?: string;
657
1109
  }
@@ -672,11 +1124,17 @@ export interface MarketplaceListingTagsGenerationRequestMessage {
672
1124
  /** Callback URL for completion notification */
673
1125
  webhookUrl?: string;
674
1126
  /** Technical analysis data for tag generation */
675
- technicalMetadata?: Record<string, string | number | boolean>;
1127
+ technicalMetadata?: {
1128
+ vertices?: number;
1129
+ faces?: number;
1130
+ volumeMm3?: number;
1131
+ dimensionsMm?: number[];
1132
+ isWatertight?: boolean;
1133
+ };
676
1134
  /** URLs to 360-degree thumbnail views for visual analysis */
677
- thumbnailUrls?: Array<Record<string, string | number | boolean>>;
1135
+ thumbnailUrls?: string[];
678
1136
  /** Currently assigned tags to supplement or replace */
679
- existingTags?: Array<Record<string, string | number | boolean>>;
1137
+ existingTags?: string[];
680
1138
  /** Current classification for category-based tags */
681
1139
  existingCategory?: string;
682
1140
  /** Maximum number of tags for marketplace (e.g., 13 for Etsy) */
@@ -686,7 +1144,7 @@ export interface MarketplaceListingTagsGenerationRequestMessage {
686
1144
  /** Artistic style of the model (e.g., 'realistic', 'low-poly') */
687
1145
  style?: string;
688
1146
  /** Intended uses for the model */
689
- useCases?: Array<Record<string, string | number | boolean>>;
1147
+ useCases?: string[];
690
1148
  }
691
1149
  /**
692
1150
  * Notifies backend that marketplace title generation completed. Contains generated title with metadata tracking.
@@ -699,7 +1157,12 @@ export interface MarketplaceListingTitleGenerationCompletedMessage {
699
1157
  /** Marketplace-optimized title */
700
1158
  title: string;
701
1159
  /** Content generation metadata for tracking */
702
- metadata: Record<string, string | number | boolean>;
1160
+ metadata: {
1161
+ source: string;
1162
+ generatedAt: string;
1163
+ aiModel: string;
1164
+ confidence: number;
1165
+ };
703
1166
  /** Error message if generation failed */
704
1167
  error?: string;
705
1168
  }
@@ -720,9 +1183,13 @@ export interface MarketplaceListingTitleGenerationRequestMessage {
720
1183
  /** Callback URL for completion notification */
721
1184
  webhookUrl?: string;
722
1185
  /** Technical analysis data for context */
723
- technicalMetadata?: Record<string, string | number | boolean>;
1186
+ technicalMetadata?: {
1187
+ vertices?: number;
1188
+ faces?: number;
1189
+ dimensionsMm?: number[];
1190
+ };
724
1191
  /** Currently assigned tags for SEO keywords */
725
- existingTags?: Array<Record<string, string | number | boolean>>;
1192
+ existingTags?: string[];
726
1193
  /** Current classification for categorization */
727
1194
  existingCategory?: string;
728
1195
  /** Maximum character count for marketplace (e.g., 140 for Etsy) */
@@ -732,7 +1199,7 @@ export interface MarketplaceListingTitleGenerationRequestMessage {
732
1199
  /** Target geographic market (e.g., 'US', 'EU') */
733
1200
  targetMarket?: string;
734
1201
  /** Specific keywords to include */
735
- keywords?: Array<Record<string, string | number | boolean>>;
1202
+ keywords?: string[];
736
1203
  }
737
1204
  /**
738
1205
  * Result of a listing update operation
@@ -745,7 +1212,7 @@ export interface MarketplaceListingUpdateCompletedMessage {
745
1212
  /** Status of the update (success, failed) */
746
1213
  status?: string;
747
1214
  /** Result details from the marketplace API */
748
- result?: Record<string, string | number | boolean>;
1215
+ result?: Record<string, unknown>;
749
1216
  /** Error message if failed */
750
1217
  error?: string;
751
1218
  }
@@ -758,65 +1225,21 @@ export interface MarketplaceListingUpdateRequestMessage {
758
1225
  /** External ID of the listing to update */
759
1226
  listingId?: string;
760
1227
  /** Fields to update */
761
- updates?: Record<string, string | number | boolean>;
1228
+ updates?: {
1229
+ price?: number;
1230
+ quantity?: number;
1231
+ title?: string;
1232
+ description?: string;
1233
+ tags?: string[];
1234
+ };
762
1235
  /** User credentials for the marketplace */
763
- credentials?: Record<string, string | number | boolean>;
764
- }
765
- /**
766
- * 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.).
767
- */
768
- export interface MarketplacePublishListingCompletedMessage {
769
- /** BullMQ job ID from original request */
770
- originalJobId?: string;
771
- /** Internal marketplace_items UUID */
772
- listingId?: string;
773
- /** UUID of the metamodel that was published */
774
- metamodelId?: string;
775
- /** Marketplace provider type (etsy, ebay, etc.) */
776
- marketplaceProvider?: string;
777
- /** Material variant name */
778
- materialName?: string;
779
- /** Publication result (SUCCESS or FAILED) */
780
- status?: string;
781
- /** External marketplace listing ID (only if status=SUCCESS) */
782
- externalListingId?: string;
783
- /** URL to view listing on marketplace (only if status=SUCCESS) */
784
- externalListingUrl?: string;
785
- /** External marketplace file ID (only if status=SUCCESS) */
786
- externalFileId?: string;
787
- /** Error details (only if status=FAILED) */
788
- error?: Record<string, string | number | boolean>;
789
- /** When the listing was created (ISO 8601, only if status=SUCCESS) */
790
- publishedAt?: string;
791
- /** Processing time in milliseconds */
792
- processingDuration?: string | number | boolean;
793
- }
794
- /**
795
- * 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.
796
- */
797
- export interface MarketplacePublishListingRequestMessage {
798
- /** Internal marketplace_items table UUID */
799
- listingId?: string;
800
- /** UUID of the metamodel being published */
801
- metamodelId?: string;
802
- /** UUID of the user who owns the metamodel */
803
- ownerId?: string;
804
- /** Marketplace provider type (etsy, ebay, leboncoin, etc.) */
805
- marketplaceProvider?: string;
806
- /** UUID of the marketplace connection configuration */
807
- marketplaceConnectionId?: string;
808
- /** Material-specific listing configuration */
809
- materialVariant?: Record<string, string | number | boolean>;
810
- /** Common listing information shared across variants */
811
- baseListingData?: Record<string, string | number | boolean>;
812
- /** Publishing configuration (marketplace-specific options) */
813
- publishOptions?: Record<string, string | number | boolean>;
814
- /** Encrypted marketplace credentials (retrieved from marketplaceConnectionId) */
815
- marketplaceCredentials?: Record<string, string | number | boolean>;
816
- /** Digital file to upload */
817
- fileMetadata?: Record<string, string | number | boolean>;
818
- /** Callback URL for completion notification */
819
- 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
+ };
820
1243
  }
821
1244
  /**
822
1245
  * Notifies that a batch media download has been completed.
@@ -827,13 +1250,36 @@ export interface MediaBatchDownloadCompletedMessage {
827
1250
  /** The final status of the batch download operation. */
828
1251
  status: string;
829
1252
  /** List of successfully processed files. */
830
- 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
+ }>;
831
1266
  /** List of files that failed to process. */
832
- failedFiles?: Array<Record<string, string | number | boolean>>;
1267
+ failedFiles?: Array<{
1268
+ path?: string;
1269
+ error?: string;
1270
+ }>;
833
1271
  /** Timestamp when the batch processing completed. */
834
1272
  processedAt: string;
835
1273
  /** Statistics about the batch processing. */
836
- 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
+ };
837
1283
  }
838
1284
  /**
839
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.
@@ -857,13 +1303,28 @@ export interface MediaBatchDownloadRequestMessage {
857
1303
  storageConnectionId?: string;
858
1304
  /** Decrypted credentials for the storage provider (Fat Payload pattern). Required when downloadStrategy is 'storage_provider'.
859
1305
  */
860
- 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
+ };
861
1317
  /** Array of media files to download and process. Must contain at least one file. Each file includes metadata for identification and processing.
862
1318
  */
863
- mediaFiles?: Array<Record<string, string | number | boolean>>;
1319
+ mediaFiles?: Array<unknown>;
864
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.
865
1321
  */
866
- compressionSettings?: Record<string, string | number | boolean>;
1322
+ compressionSettings?: {
1323
+ maxWidth?: number;
1324
+ maxHeight?: number;
1325
+ imageQuality?: number;
1326
+ outputFormat?: string;
1327
+ };
867
1328
  }
868
1329
  /**
869
1330
  * Handles metamodel metadata generation completion. Contains AI-generated metadata and aggregated technical analysis.
@@ -872,9 +1333,99 @@ export interface MetamodelMetadataGenerationCompletedMessage {
872
1333
  /** The unique identifier for the metamodel */
873
1334
  metamodelId: string;
874
1335
  /** AI-generated metadata for the metamodel */
875
- 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
+ };
876
1393
  /** Aggregated technical analysis from constituent models */
877
- 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
+ };
878
1429
  }
879
1430
  /**
880
1431
  * Handles metamodel metadata generation requests via Ollama. Aggregates data from constituent models and generates AI-enhanced metadata.
@@ -883,7 +1434,7 @@ export interface MetamodelMetadataGenerationRequestMessage {
883
1434
  /** The unique identifier for the metamodel */
884
1435
  metamodelId?: string;
885
1436
  /** Array of model IDs that compose this metamodel */
886
- constituentModelIds?: Array<Record<string, string | number | boolean>>;
1437
+ constituentModelIds?: string[];
887
1438
  /** The name of the metamodel */
888
1439
  name?: string;
889
1440
  /** The owner's user ID */
@@ -891,7 +1442,19 @@ export interface MetamodelMetadataGenerationRequestMessage {
891
1442
  /** The library containing this metamodel */
892
1443
  libraryId?: string;
893
1444
  /** Enriched metadata for constituent models (includes storage items) */
894
- 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
+ }>;
895
1458
  /** Optional webhook URL for async completion notification */
896
1459
  webhookUrl?: string;
897
1460
  }
@@ -913,7 +1476,7 @@ export interface ModelAnalyticsCollectionRequestMessage {
913
1476
  /** Sub-category for more specific targeting */
914
1477
  subCategory?: string;
915
1478
  /** Relevant tags from metamodel metadata (max 10) */
916
- tags?: Array<Record<string, string | number | boolean>>;
1479
+ tags?: string[];
917
1480
  /** Franchise name if detected (e.g., "Dungeons & Dragons") */
918
1481
  franchise?: string;
919
1482
  /** Classification confidence score */
@@ -934,13 +1497,29 @@ export interface ModelDiscoveryFolderProcessedEventMessage {
934
1497
  /** The path to the processed folder. */
935
1498
  folderPath?: string;
936
1499
  /** A list of files discovered in the folder. */
937
- discoveredFiles?: Array<Record<string, string | number | boolean>>;
1500
+ discoveredFiles?: Array<{
1501
+ path: string;
1502
+ name: string;
1503
+ size: number;
1504
+ modifiedAt: string;
1505
+ }>;
938
1506
  /** A signature representing the state of the folder. */
939
- folderSignature?: Record<string, string | number | boolean>;
1507
+ folderSignature?: {
1508
+ hash: string;
1509
+ calculatedAt: string;
1510
+ };
940
1511
  /** The timestamp when the folder was processed. */
941
1512
  processedAt?: string;
942
1513
  /** Statistics about the processed folder. */
943
- 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
+ };
944
1523
  }
945
1524
  /**
946
1525
  * Handles model discovery scan found events.
@@ -955,22 +1534,34 @@ export interface ModelDiscoveryScanFoundEventMessage {
955
1534
  /** A description of the model. */
956
1535
  description?: string;
957
1536
  /** An array of file types associated with the model. */
958
- fileTypes?: Array<Record<string, string | number | boolean>>;
1537
+ fileTypes?: string[];
959
1538
  /** The size of the model file in bytes. */
960
1539
  size?: number;
961
1540
  /** The storage location of the model. */
962
- storageLocation?: Record<string, string | number | boolean>;
1541
+ storageLocation?: {
1542
+ storageConnectionId: string;
1543
+ path: string;
1544
+ libraryId: string;
1545
+ ownerId: string;
1546
+ };
963
1547
  /** The type of the storage provider. */
964
1548
  providerType?: string;
965
1549
  /** A flexible object for additional metadata. */
966
- metadata?: Record<string, string | number | boolean>;
1550
+ metadata?: Record<string, unknown>;
967
1551
  }
968
1552
  /**
969
1553
  * Handles model discovery scan progress events.
970
1554
  */
971
1555
  export interface ModelDiscoveryScanProgressEventMessage {
972
1556
  /** Contains the discovery scan progress details. */
973
- 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
+ };
974
1565
  }
975
1566
  /**
976
1567
  * Handles model discovery scan requests events.
@@ -985,30 +1576,34 @@ export interface ModelDiscoveryScanRequestMessage {
985
1576
  /** The specific path within the storage connection to scan for this library. */
986
1577
  path?: string;
987
1578
  /** Decrypted credentials for the storage provider. */
988
- credentials?: Record<string, string | number | boolean>;
1579
+ credentials?: Record<string, unknown>;
989
1580
  /** Configuration for the storage connection (e.g. scanRootPath). */
990
- configuration?: Record<string, string | number | boolean>;
1581
+ configuration?: Record<string, unknown>;
991
1582
  }
992
1583
  /**
993
- * Request to index a 3D model for similarity search.
1584
+ * DEPRECATED (2026-02-18) FR-023 retired. Merge 3D rendering into worker-file-vectorize.
994
1585
  */
995
1586
  export interface ModelFinderIndexRequestMessage {
996
1587
  /** */
997
1588
  modelId?: string;
998
1589
  /** */
999
- storageItem?: string | number | boolean;
1590
+ storageItem?: unknown;
1000
1591
  }
1001
1592
  /**
1002
- * Response containing search results from the model finder.
1593
+ * DEPRECATED (2026-02-18) FR-023 retired. Merge 3D rendering into worker-file-vectorize.
1003
1594
  */
1004
1595
  export interface ModelFinderResponseMessage {
1005
1596
  /** */
1006
1597
  requestId?: string;
1007
1598
  /** */
1008
- results?: Array<Record<string, string | number | boolean>>;
1599
+ results?: Array<{
1600
+ modelId?: string;
1601
+ similarity?: number;
1602
+ metamodelIds?: string[];
1603
+ }>;
1009
1604
  }
1010
1605
  /**
1011
- * Request to search for similar 3D models.
1606
+ * DEPRECATED (2026-02-18) FR-023 retired. Merge 3D rendering into worker-file-vectorize.
1012
1607
  */
1013
1608
  export interface ModelFinderSearchRequestMessage {
1014
1609
  /** Optional: Search using an existing model as reference */
@@ -1016,7 +1611,7 @@ export interface ModelFinderSearchRequestMessage {
1016
1611
  /** Optional: Search using an uploaded image */
1017
1612
  referenceImageId?: string;
1018
1613
  /** */
1019
- limit?: string | number | boolean;
1614
+ limit?: number;
1020
1615
  }
1021
1616
  /**
1022
1617
  * Notifies backend that enriched marketplace metadata generation completed. Backend updates Model entity with generated description, tags, classification, etc.
@@ -1025,7 +1620,12 @@ export interface ModelMetadataGenerationCompletedMessage {
1025
1620
  /** UUID of the model that was processed. */
1026
1621
  modelId: string;
1027
1622
  /** Enriched marketplace metadata generated by LLM. */
1028
- metadata: Record<string, string | number | boolean>;
1623
+ metadata: {
1624
+ description: string;
1625
+ tags: string[];
1626
+ primaryCategory: string;
1627
+ subCategory: string;
1628
+ };
1029
1629
  }
1030
1630
  /**
1031
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.
@@ -1034,20 +1634,89 @@ export interface ModelMetadataGenerationRequestMessage {
1034
1634
  /** UUID of the model (reference only) */
1035
1635
  modelId?: string;
1036
1636
  /** Core model entity data */
1037
- model?: Record<string, string | number | boolean>;
1637
+ model?: {
1638
+ name?: string;
1639
+ fileName?: string;
1640
+ fileSize?: number;
1641
+ ownerId?: string;
1642
+ };
1038
1643
  /** Geometric and technical analysis results */
1039
- 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
+ };
1040
1652
  /** List of 360 degree thumbnail views (URLs or paths) */
1041
- thumbnails?: Array<Record<string, string | number | boolean>>;
1653
+ thumbnails?: Array<{
1654
+ id?: string;
1655
+ url?: string;
1656
+ angle?: number;
1657
+ }>;
1042
1658
  }
1043
1659
  /**
1044
1660
  * Handles model metamodel detection found with hierarchical relationships.
1045
1661
  */
1046
1662
  export interface ModelMetamodelDetectionFoundMessage {
1047
1663
  /** List of metamodel nodes in hierarchical structure (roots and children). */
1048
- 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
+ }>;
1049
1700
  /** EKG edges derived from Louvain clustering (OPTIONAL - new field) */
1050
- 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
+ }>;
1051
1720
  }
1052
1721
  /**
1053
1722
  * Handles model metamodel detection requests.
@@ -1058,15 +1727,91 @@ export interface ModelMetamodelDetectionRequestMessage {
1058
1727
  /** The path to the folder that was processed. */
1059
1728
  folderPath: string;
1060
1729
  /** A list of files discovered in the folder. Worker should check this first, then manifestUrl. */
1061
- discoveredFiles?: Array<Record<string, string | number | boolean>>;
1730
+ discoveredFiles?: Array<{
1731
+ path: string;
1732
+ name: string;
1733
+ size: number;
1734
+ modifiedAt: string;
1735
+ }>;
1062
1736
  /** URL to a JSON file containing the list of discovered files (for large folders) */
1063
1737
  manifestUrl?: string;
1064
1738
  /** A signature representing the state of the folder. */
1065
- folderSignature: Record<string, string | number | boolean>;
1739
+ folderSignature: {
1740
+ hash: string;
1741
+ calculatedAt: string;
1742
+ };
1066
1743
  /** The timestamp when the folder was processed. */
1067
1744
  processedAt: string;
1068
1745
  /** Statistics about the processed folder. */
1069
- 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;
1070
1815
  }
1071
1816
  /**
1072
1817
  * Contains sellability analysis results including Etsy-specific recommendations, material pricing, and marketplace compatibility scores
@@ -1079,21 +1824,67 @@ export interface ModelSellabilityAnalysisCompletedMessage {
1079
1824
  /** Overall sellability score (0-100) */
1080
1825
  sellabilityScore?: number;
1081
1826
  /** Pricing analysis and recommendations with material-specific pricing (v2.0.0) */
1082
- 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
+ };
1083
1842
  /** Recommended marketplaces with Etsy-specific scoring (v2.0.0) */
1084
- 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
+ }>;
1085
1855
  /** Market demand insights */
1086
- demandAnalysis?: Record<string, string | number | boolean>;
1856
+ demandAnalysis?: {
1857
+ categoryDemand?: string;
1858
+ trendingScore?: number;
1859
+ searchVolume?: number;
1860
+ competitionLevel?: string;
1861
+ trendDirection?: string;
1862
+ };
1087
1863
  /** Quality-related factors affecting sellability */
1088
- qualityFactors?: Record<string, string | number | boolean>;
1864
+ qualityFactors?: {
1865
+ technicalQuality?: number;
1866
+ printability?: number;
1867
+ uniqueness?: number;
1868
+ marketFit?: number;
1869
+ };
1089
1870
  /** Actionable recommendations to improve sellability */
1090
- 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
+ }>;
1091
1878
  /** Analysis completion timestamp (ISO 8601) */
1092
1879
  analyzedAt?: string;
1093
1880
  /** Analysis algorithm version */
1094
1881
  analysisVersion?: string;
1095
1882
  /** Error information if analysis failed */
1096
- error?: Record<string, string | number | boolean>;
1883
+ error?: {
1884
+ code?: string;
1885
+ message?: string;
1886
+ details?: Record<string, unknown>;
1887
+ };
1097
1888
  }
1098
1889
  /**
1099
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.
@@ -1104,11 +1895,21 @@ export interface ModelSellabilityAnalysisRequestMessage {
1104
1895
  /** UUID of the user who owns the metamodel */
1105
1896
  ownerId?: string;
1106
1897
  /** Full metamodel data including technical metadata, enriched metadata, and child models. Injected by backend to avoid DB access. */
1107
- metamodelData?: Record<string, string | number | boolean>;
1898
+ metamodelData?: Record<string, unknown>;
1108
1899
  /** URL to a JSON manifest containing the metamodel data if it is too large for the message payload. */
1109
1900
  manifestUrl?: string;
1110
1901
  /** Optional analysis configuration */
1111
- 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
+ };
1112
1913
  }
1113
1914
  /**
1114
1915
  * Handles completion of 3D model semantic analysis with generated tags and similarity results.
@@ -1121,15 +1922,61 @@ export interface ModelSemanticAnalysisCompletedMessage {
1121
1922
  /** Final processing status. */
1122
1923
  processingStatus?: string;
1123
1924
  /** Generated semantic metadata and analysis results. */
1124
- 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
+ };
1125
1952
  /** Processing performance metrics. */
1126
- processingTime?: Record<string, string | number | boolean>;
1953
+ processingTime?: {
1954
+ totalTimeMs?: number;
1955
+ geometryTimeMs?: number;
1956
+ neuralTimeMs?: number;
1957
+ searchTimeMs?: number;
1958
+ };
1127
1959
  /** Processing quality and confidence metrics. */
1128
- qualityMetrics?: Record<string, string | number | boolean>;
1960
+ qualityMetrics?: {
1961
+ overallConfidence?: number;
1962
+ tagCount?: number;
1963
+ duplicateDetected?: boolean;
1964
+ knowledgeBaseUpdated?: boolean;
1965
+ };
1129
1966
  /** Error information if processing failed. */
1130
- error?: Record<string, string | number | boolean>;
1967
+ error?: {
1968
+ message?: string;
1969
+ category?: string;
1970
+ retryable?: boolean;
1971
+ technicalDetails?: string;
1972
+ };
1131
1973
  /** Additional debug information for troubleshooting. */
1132
- debugInfo?: Record<string, string | number | boolean>;
1974
+ debugInfo?: {
1975
+ workerVersion?: string;
1976
+ processingNode?: string;
1977
+ gpuUsed?: boolean;
1978
+ memoryUsageMb?: number;
1979
+ };
1133
1980
  }
1134
1981
  /**
1135
1982
  * Handles 3D model semantic analysis requests using ULIP-2 neural networks and FAISS vector similarity search.
@@ -1150,7 +1997,13 @@ export interface ModelSemanticAnalysisRequestMessage {
1150
1997
  /** The type of the storage provider (S3, GoogleDrive, SFTP, etc). */
1151
1998
  storageProviderType?: string;
1152
1999
  /** Configuration options for semantic analysis. */
1153
- processingOptions?: Record<string, string | number | boolean>;
2000
+ processingOptions?: {
2001
+ pointCloudSize?: number;
2002
+ similarityThreshold?: number;
2003
+ similarityK?: number;
2004
+ enableDuplicateDetection?: boolean;
2005
+ generateThumbnail?: boolean;
2006
+ };
1154
2007
  /** Processing priority (1=highest, 10=lowest). */
1155
2008
  priority?: number;
1156
2009
  /** Optional webhook URL for completion notification. */
@@ -1169,15 +2022,20 @@ export interface ModelTechnicalMetadataCompletedMessage {
1169
2022
  /** Analysis completion status */
1170
2023
  status?: string;
1171
2024
  /** Number of vertices in the mesh */
1172
- vertices?: string | number | boolean;
2025
+ vertices?: number;
1173
2026
  /** Number of faces/polygons in the mesh */
1174
- faces?: string | number | boolean;
2027
+ faces?: number;
1175
2028
  /** Number of edges in the mesh */
1176
- edges?: string | number | boolean;
2029
+ edges?: number;
1177
2030
  /** Visual detail level based on polygon density */
1178
2031
  detailLevel?: string;
1179
2032
  /** 3D bounding box dimensions in millimeters */
1180
- boundingBox?: Record<string, string | number | boolean>;
2033
+ boundingBox?: {
2034
+ width?: number;
2035
+ height?: number;
2036
+ depth?: number;
2037
+ originalUnit?: string;
2038
+ };
1181
2039
  /** Model volume in cubic millimeters (for material calculation) */
1182
2040
  volumeCubicMm?: number;
1183
2041
  /** Total surface area in square millimeters */
@@ -1189,13 +2047,13 @@ export interface ModelTechnicalMetadataCompletedMessage {
1189
2047
  /** Is the mesh watertight/manifold? Critical for 3D printing (true = printable) */
1190
2048
  manifold?: boolean;
1191
2049
  /** Number of non-manifold edges (repair needed if > 0) */
1192
- nonManifoldEdges?: string | number | boolean;
2050
+ nonManifoldEdges?: number;
1193
2051
  /** Number of holes/boundary loops in the mesh (0 = closed mesh) */
1194
- holes?: string | number | boolean;
2052
+ holes?: number;
1195
2053
  /** Number of faces with inverted normals (causes rendering/slicing issues) */
1196
- flippedNormals?: string | number | boolean;
2054
+ flippedNormals?: number;
1197
2055
  /** Number of self-intersecting faces (0 = clean geometry) */
1198
- selfIntersections?: string | number | boolean;
2056
+ selfIntersections?: number;
1199
2057
  /** Overall quality score 0-100 (100 = perfect for printing, <60 needs repair) */
1200
2058
  qualityScore?: number;
1201
2059
  /** Printability score 0-100 (considers supports, orientation, size constraints) */
@@ -1203,17 +2061,47 @@ export interface ModelTechnicalMetadataCompletedMessage {
1203
2061
  /** Does this model require support structures for 3D printing? */
1204
2062
  requiresSupports?: boolean;
1205
2063
  /** Detected overhang areas requiring support structures */
1206
- overhangs?: Array<Record<string, string | number | boolean>>;
2064
+ overhangs?: Array<{
2065
+ angle?: number;
2066
+ area?: number;
2067
+ location?: string;
2068
+ }>;
1207
2069
  /** Estimated print time in minutes using normal quality settings (0.2mm layers, 20% infill) */
1208
- estimatedPrintTimeMinutes?: string | number | boolean;
2070
+ estimatedPrintTimeMinutes?: number;
1209
2071
  /** Print time estimates for different quality presets */
1210
- printTimeEstimates?: Record<string, string | number | boolean>;
2072
+ printTimeEstimates?: {
2073
+ draft?: number;
2074
+ normal?: number;
2075
+ highQuality?: number;
2076
+ };
1211
2077
  /** Estimated material usage in grams using 20% infill (assumes PLA density 1.24g/cm³) */
1212
2078
  estimatedMaterialGrams?: number;
1213
2079
  /** Material usage estimates for different infill percentages */
1214
- materialEstimates?: Record<string, string | number | boolean>;
2080
+ materialEstimates?: {
2081
+ infill10?: number;
2082
+ infill20?: number;
2083
+ infill50?: number;
2084
+ infill100?: number;
2085
+ };
1215
2086
  /** Recommended print orientation for minimal support material and best results */
1216
- 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
+ };
1217
2105
  /** Original file format unit detected from metadata or inferred from scale */
1218
2106
  originalUnit?: string;
1219
2107
  /** File format version (e.g., 'STL Binary', 'OBJ v4', 'PLY 1.0') */
@@ -1231,7 +2119,11 @@ export interface ModelTechnicalMetadataCompletedMessage {
1231
2119
  /** Confidence level of analysis results (0.0 = uncertain, 1.0 = highly confident) */
1232
2120
  analysisConfidence?: number;
1233
2121
  /** Warnings or issues detected during analysis (structured for programmatic handling) */
1234
- analysisWarnings?: Array<Record<string, string | number | boolean>>;
2122
+ analysisWarnings?: Array<{
2123
+ code?: string;
2124
+ message?: string;
2125
+ severity?: string;
2126
+ }>;
1235
2127
  /** ISO 8601 timestamp when analysis was performed (e.g., '2025-11-19T14:35:22Z') */
1236
2128
  analyzedAt?: string;
1237
2129
  /** Detailed error message if status is FAILED */
@@ -1248,13 +2140,217 @@ export interface ModelTechnicalMetadataRequestMessage {
1248
2140
  /** User ID who owns the model */
1249
2141
  ownerId?: string;
1250
2142
  /** Location of the 3D model file (legacy - used for direct download if minioPath not provided) */
1251
- storageLocation?: Record<string, string | number | boolean>;
2143
+ storageLocation?: {
2144
+ storageConnectionId: string;
2145
+ path: string;
2146
+ };
1252
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. */
1253
2148
  minioPath?: string;
1254
2149
  /** ID of parent file-download job (for BullMQ dependency tracking). */
1255
2150
  parentJobId?: string;
1256
2151
  /** Optional analysis configuration parameters */
1257
- 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;
1258
2354
  }
1259
2355
  /**
1260
2356
  * Handles thumbnail generation completed.
@@ -1269,13 +2365,23 @@ export interface ThumbnailGenerationCompletedMessage {
1269
2365
  /** The path to the generated thumbnail. */
1270
2366
  thumbnailPath?: string;
1271
2367
  /** Array of 360° thumbnail view paths (16 angles) for vision-based analysis. */
1272
- 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
+ }>;
1273
2374
  /** The path to the generated GLTF/GLB 3D preview file. */
1274
2375
  gltfPreviewPath?: string;
2376
+ /** The path to the generated animated MP4 preview file. */
2377
+ animatedPreviewPath?: string;
1275
2378
  /** An error message if the thumbnail generation failed. */
1276
2379
  errorMessage?: string;
1277
2380
  /** The storage location of the model. */
1278
- storageLocation?: Record<string, string | number | boolean>;
2381
+ storageLocation?: {
2382
+ storageConnectionId: string;
2383
+ path: string;
2384
+ };
1279
2385
  }
1280
2386
  /**
1281
2387
  * Handles thumbnail generation requests with customization options. Supports both storage provider downloads and MinIO-cached files.
@@ -1286,7 +2392,10 @@ export interface ThumbnailGenerationRequestMessage {
1286
2392
  /** The identifier of the user who owns the entity. */
1287
2393
  ownerId?: string;
1288
2394
  /** The storage location of the model (legacy - used for direct download if minioPath not provided). */
1289
- storageLocation?: Record<string, string | number | boolean>;
2395
+ storageLocation?: {
2396
+ storageConnectionId: string;
2397
+ path: string;
2398
+ };
1290
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. */
1291
2400
  minioPath?: string;
1292
2401
  /** The type of preview to generate, e.g., 'default', 'static', 'glb'. */
@@ -1296,7 +2405,24 @@ export interface ThumbnailGenerationRequestMessage {
1296
2405
  /** ID of parent file-download job (for BullMQ dependency tracking). */
1297
2406
  parentJobId?: string;
1298
2407
  /** User-defined customizations for the thumbnail. */
1299
- 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
+ };
1300
2426
  }
1301
2427
  /**
1302
2428
  * User engagement and onboarding tracking events for analytics and behavioral insights.
@@ -1318,6 +2444,8 @@ Used for:
1318
2444
 
1319
2445
  */
1320
2446
  export interface UserEngagementEventMessage {
2447
+ /** Schema version for forward-compatible evolution */
2448
+ eventVersion: string;
1321
2449
  /** Category of user engagement event */
1322
2450
  eventType: string;
1323
2451
  /** Specific user action performed */
@@ -1326,7 +2454,7 @@ export interface UserEngagementEventMessage {
1326
2454
  timestamp: string;
1327
2455
  /** Unique identifier of the user */
1328
2456
  userId: string;
1329
- /** 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. */
1330
2458
  userEmail?: string;
1331
2459
  /** When the user account was created (for cohort analysis) */
1332
2460
  userCreatedAt?: string;
@@ -1334,10 +2462,26 @@ export interface UserEngagementEventMessage {
1334
2462
  userPlanTier?: string;
1335
2463
  /** User session identifier for grouping actions */
1336
2464
  sessionId?: string;
1337
- /** Request ID for correlation with logs */
2465
+ /** Request ID for correlation with backend logs */
1338
2466
  requestId?: string;
2467
+ /** Correlation ID to link engagement events across frontend and backend boundaries, and to pipeline traces */
2468
+ correlationId?: string;
1339
2469
  /** Additional context about the action */
1340
- 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
+ };
1341
2485
  /** Where the action originated */
1342
2486
  source?: string;
1343
2487
  /** HTTP method used */
@@ -1345,7 +2489,7 @@ export interface UserEngagementEventMessage {
1345
2489
  /** API endpoint path */
1346
2490
  httpUrl?: string;
1347
2491
  /** HTTP response status code */
1348
- httpStatusCode?: string | number | boolean;
2492
+ httpStatusCode?: number;
1349
2493
  /** Action duration in milliseconds */
1350
2494
  durationMs?: number;
1351
2495
  /** A/B test or experiment ID */
@@ -1355,7 +2499,12 @@ export interface UserEngagementEventMessage {
1355
2499
  /** Deployment environment */
1356
2500
  environment?: string;
1357
2501
  /** Client/browser information (anonymized) */
1358
- clientInfo?: Record<string, string | number | boolean>;
2502
+ clientInfo?: {
2503
+ userAgent?: string;
2504
+ platform?: string;
2505
+ browser?: string;
2506
+ browserVersion?: string;
2507
+ };
1359
2508
  }
1360
2509
  /**
1361
2510
  * Analytics event emitted by workers for tracking processing metrics, user behavior,
@@ -1389,9 +2538,13 @@ export interface WorkerAnalyticsEventMessage {
1389
2538
  /** Error message if status is failure */
1390
2539
  errorMessage?: string;
1391
2540
  /** Processing time metrics in milliseconds */
1392
- timing?: Record<string, string | number | boolean>;
2541
+ timing?: {
2542
+ queueWaitMs?: number;
2543
+ processingMs?: number;
2544
+ stages?: Record<string, number>;
2545
+ };
1393
2546
  /** Worker-specific metrics. Structure varies by eventType. */
1394
- metrics?: Record<string, string | number | boolean>;
2547
+ metrics?: Record<string, unknown>;
1395
2548
  }
1396
2549
  /**
1397
2550
  * Enriched metrics event for detailed worker monitoring, cost tracking,
@@ -1432,15 +2585,62 @@ export interface WorkerMetricsEnrichedEventMessage {
1432
2585
  /** Storage item ID (for file operations) */
1433
2586
  storageItemId?: string;
1434
2587
  /** Comprehensive timing breakdown */
1435
- timing?: Record<string, string | number | boolean>;
2588
+ timing?: {
2589
+ queueWaitMs?: number;
2590
+ processingMs?: number;
2591
+ stages?: Record<string, number>;
2592
+ };
1436
2593
  /** LLM token usage and cost breakdown */
1437
- 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
+ };
1438
2608
  /** System resource consumption during job */
1439
- 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
+ };
1440
2636
  /** Worker-specific metrics (varies by worker type) */
1441
- workerMetrics?: Record<string, string | number | boolean>;
2637
+ workerMetrics?: Record<string, unknown>;
1442
2638
  /** Error details if status is failure */
1443
- error?: Record<string, string | number | boolean>;
2639
+ error?: {
2640
+ code?: string;
2641
+ message?: string;
2642
+ category?: string;
2643
+ };
1444
2644
  /** Deployment environment */
1445
2645
  environment?: string;
1446
2646
  /** Cloud region/datacenter */