@ductape/sdk 0.1.108 → 0.1.113

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.
Files changed (46) hide show
  1. package/dist/api/services/processorApi.service.js +23 -9
  2. package/dist/api/services/processorApi.service.js.map +1 -1
  3. package/dist/features/feature-executor.d.ts +9 -0
  4. package/dist/features/feature-executor.js +246 -74
  5. package/dist/features/feature-executor.js.map +1 -1
  6. package/dist/features/features.service.d.ts +5 -0
  7. package/dist/features/features.service.js +49 -7
  8. package/dist/features/features.service.js.map +1 -1
  9. package/dist/features/index.d.ts +2 -1
  10. package/dist/features/index.js +3 -1
  11. package/dist/features/index.js.map +1 -1
  12. package/dist/features/types/features.types.d.ts +9 -0
  13. package/dist/features/types/features.types.js.map +1 -1
  14. package/dist/functions/functions.runtime.d.ts +25 -0
  15. package/dist/functions/functions.runtime.js +254 -0
  16. package/dist/functions/functions.runtime.js.map +1 -0
  17. package/dist/functions/http-handler.d.ts +17 -0
  18. package/dist/functions/http-handler.js +51 -0
  19. package/dist/functions/http-handler.js.map +1 -0
  20. package/dist/functions/index.d.ts +3 -0
  21. package/dist/functions/index.js +20 -0
  22. package/dist/functions/index.js.map +1 -0
  23. package/dist/functions/types.d.ts +94 -0
  24. package/dist/functions/types.js +15 -0
  25. package/dist/functions/types.js.map +1 -0
  26. package/dist/graph/graphs.service.d.ts +1 -1
  27. package/dist/graph/graphs.service.js +73 -43
  28. package/dist/graph/graphs.service.js.map +1 -1
  29. package/dist/graph/types/traversal.interface.d.ts +2 -0
  30. package/dist/index.d.ts +16 -1
  31. package/dist/index.js +23 -3
  32. package/dist/index.js.map +1 -1
  33. package/dist/processor/services/processor.service.d.ts +6 -0
  34. package/dist/processor/services/processor.service.js +8 -13
  35. package/dist/processor/services/processor.service.js.map +1 -1
  36. package/dist/sessions/sessions.service.d.ts +2 -0
  37. package/dist/sessions/sessions.service.js +15 -5
  38. package/dist/sessions/sessions.service.js.map +1 -1
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/dist/types/productsBuilder.types.d.ts +3 -0
  41. package/dist/types/productsBuilder.types.js +2 -0
  42. package/dist/types/productsBuilder.types.js.map +1 -1
  43. package/dist/vector/vector-database.service.d.ts +2 -0
  44. package/dist/vector/vector-database.service.js +21 -12
  45. package/dist/vector/vector-database.service.js.map +1 -1
  46. package/package.json +1 -1
@@ -32,6 +32,7 @@ const inputs_types_1 = require("../types/inputs.types");
32
32
  const processor_utils_1 = require("../processor/utils/processor.utils");
33
33
  const productsBuilder_types_1 = require("../types/productsBuilder.types");
34
34
  const date_fns_1 = require("date-fns");
35
+ const functions_1 = require("../functions");
35
36
  /** Only log when DUCTAPE_DEBUG is set to avoid sync I/O and serialization cost in hot path */
36
37
  const debugLog = typeof process !== 'undefined' && (((_a = process.env) === null || _a === void 0 ? void 0 : _a.DUCTAPE_DEBUG) === 'true' || ((_b = process.env) === null || _b === void 0 ? void 0 : _b.DUCTAPE_DEBUG) === '1')
37
38
  ? (...args) => console.log(...args)
@@ -47,6 +48,56 @@ const stepLog = typeof process !== 'undefined'
47
48
  }
48
49
  }
49
50
  : () => { };
51
+ const SENSITIVE_LOG_KEY = /(?:authorization|cookie|password|passwd|secret|token|api[_-]?key|access[_-]?key|private[_-]?key|client[_-]?secret|session)/i;
52
+ const MAX_LOG_STRING_LENGTH = 2000;
53
+ /** Produce useful payload traces without leaking credentials or exploding logs. */
54
+ const sanitizeForLog = (value, key = '', seen = new WeakSet()) => {
55
+ if (key !== 'has_session' && SENSITIVE_LOG_KEY.test(key))
56
+ return '[REDACTED]';
57
+ if (value == null || typeof value === 'number' || typeof value === 'boolean')
58
+ return value;
59
+ if (typeof value === 'bigint')
60
+ return value.toString();
61
+ if (typeof value === 'string') {
62
+ return value.length > MAX_LOG_STRING_LENGTH
63
+ ? `${value.slice(0, MAX_LOG_STRING_LENGTH)}...[truncated ${value.length - MAX_LOG_STRING_LENGTH} chars]`
64
+ : value;
65
+ }
66
+ if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
67
+ return `[Buffer ${value.length} bytes]`;
68
+ }
69
+ if (value instanceof Error)
70
+ return { name: value.name, message: value.message, stack: value.stack };
71
+ if (Array.isArray(value))
72
+ return value.map((item) => sanitizeForLog(item, key, seen));
73
+ if (typeof value === 'object') {
74
+ if (seen.has(value))
75
+ return '[Circular]';
76
+ seen.add(value);
77
+ return Object.fromEntries(Object.entries(value).map(([nestedKey, nestedValue]) => [
78
+ nestedKey,
79
+ sanitizeForLog(nestedValue, nestedKey, seen),
80
+ ]));
81
+ }
82
+ return String(value);
83
+ };
84
+ /** Observability must not disappear because a successful result contains BigInt or cycles. */
85
+ const stringifyProcessorValue = (value) => {
86
+ const seen = new WeakSet();
87
+ return JSON.stringify(value, (_key, nested) => {
88
+ if (typeof nested === 'bigint')
89
+ return nested.toString();
90
+ if (nested instanceof Error) {
91
+ return { name: nested.name, message: nested.message, stack: nested.stack };
92
+ }
93
+ if (nested && typeof nested === 'object') {
94
+ if (seen.has(nested))
95
+ return '[Circular]';
96
+ seen.add(nested);
97
+ }
98
+ return nested;
99
+ });
100
+ };
50
101
  /** Normalize error to a string and extract HTTP details when present (e.g. Axios) */
51
102
  function formatErrorDetails(error) {
52
103
  var _a, _b, _c, _d;
@@ -98,6 +149,7 @@ class FeatureExecutor {
98
149
  this.graphConnectionUsed = false;
99
150
  /** Pre-fetched bootstrap data per step tag (feature batch prefetch). */
100
151
  this.stepBootstrapCache = new Map();
152
+ this.functionInvocations = new Map();
101
153
  debugLog('[FeatureExecutor] constructor ENTRY', {
102
154
  feature_tag: feature.tag,
103
155
  product: options.product,
@@ -106,6 +158,7 @@ class FeatureExecutor {
106
158
  });
107
159
  this.config = config;
108
160
  this.feature = feature;
161
+ this.inheritedSession = options.session;
109
162
  this.sessionLogFields = sessionLogFields || {};
110
163
  this._privateKey = private_key || '';
111
164
  this.preInitializedProduct = Boolean(preInitializedBuilder);
@@ -141,8 +194,26 @@ class FeatureExecutor {
141
194
  feature_id: this.state.feature_id,
142
195
  feature_tag: this.state.feature_tag,
143
196
  steps_count: (_b = (_a = feature.steps) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
197
+ has_session: Boolean(this.inheritedSession),
198
+ input: sanitizeForLog(options.input),
144
199
  });
145
200
  }
201
+ /** Debug-only structured execution trace. Payloads are recursively redacted. */
202
+ trace(stage, payload = {}) {
203
+ debugLog('[FeatureExecutor][trace]', sanitizeForLog(Object.assign({ stage, feature_id: this.state.feature_id, feature_tag: this.state.feature_tag, product: this.state.product, env: this.state.env, has_session: Boolean(this.inheritedSession) }, payload)));
204
+ }
205
+ /** Brokers expose the same session as separate tag/token fields. */
206
+ inheritedBrokerSession() {
207
+ if (!this.inheritedSession)
208
+ return undefined;
209
+ const separator = this.inheritedSession.indexOf(':');
210
+ if (separator < 1)
211
+ return undefined;
212
+ return {
213
+ tag: this.inheritedSession.slice(0, separator),
214
+ token: this.inheritedSession.slice(separator + 1),
215
+ };
216
+ }
146
217
  /**
147
218
  * Get auth payload for API calls
148
219
  */
@@ -152,6 +223,7 @@ class FeatureExecutor {
152
223
  workspace_id: this.config.workspace_id,
153
224
  public_key: this.config.public_key,
154
225
  token: this.config.token,
226
+ access_key: this.config.access_key,
155
227
  };
156
228
  }
157
229
  /** Product private key for processor result encryption; must always match backend decryption key. No fallback to workspace key. */
@@ -172,6 +244,10 @@ class FeatureExecutor {
172
244
  access_key: this.config.access_key,
173
245
  preInitializedProductBuilder: this.productBuilder,
174
246
  });
247
+ this._processorService.setFeatureExecutionContext({
248
+ feature_id: this.state.feature_id,
249
+ feature_tag: this.state.feature_tag,
250
+ });
175
251
  }
176
252
  return this._processorService;
177
253
  }
@@ -301,8 +377,8 @@ class FeatureExecutor {
301
377
  error,
302
378
  };
303
379
  const inputPayload = { product: this.state.product, env: this.state.env, event: this.state.feature_tag, input: this.state.input };
304
- const resultStr = JSON.stringify(resultData);
305
- const inputStr = JSON.stringify(inputPayload);
380
+ const resultStr = stringifyProcessorValue(resultData);
381
+ const inputStr = stringifyProcessorValue(inputPayload);
306
382
  const encKey = this.getProcessorResultEncryptionKey();
307
383
  const processorResult = {
308
384
  process_id: this.state.feature_id,
@@ -320,7 +396,9 @@ class FeatureExecutor {
320
396
  product_tag: this.state.product,
321
397
  workspace_id: this.config.workspace_id,
322
398
  };
399
+ this.trace('execution.persistence.sent', { status, payload: resultData });
323
400
  await this.processorApiService.saveResult(processorResult, this.getAuthPayload());
401
+ this.trace('execution.persistence.acknowledged', { status, process_id: this.state.feature_id });
324
402
  debugLog('[FeatureExecutor] persistExecutionResult SUCCESS', { feature_id: this.state.feature_id, status });
325
403
  }
326
404
  catch (err) {
@@ -356,6 +434,7 @@ class FeatureExecutor {
356
434
  * Processor results for steps always have component: 'feature_step' and step_type set to the step kind.
357
435
  */
358
436
  async persistStepResult(step, status, output, error, duration, input) {
437
+ var _a;
359
438
  const resolvedInput = input !== null && input !== void 0 ? input : step.input;
360
439
  const stepType = this.getStepTypeForResult(step);
361
440
  debugLog('[FeatureExecutor] persistStepResult ENTRY', {
@@ -373,30 +452,20 @@ class FeatureExecutor {
373
452
  ? output
374
453
  : {}
375
454
  : { error: error !== null && error !== void 0 ? error : 'Step failed' };
376
- const resultStr = JSON.stringify(value);
377
- const inputStr = JSON.stringify(resolvedInput);
455
+ const resultStr = stringifyProcessorValue(value);
456
+ const inputStr = stringifyProcessorValue(resolvedInput);
378
457
  const encKey = this.getProcessorResultEncryptionKey();
379
- const stepResult = {
380
- process_id: stepProcessId,
381
- product_id: this.productId || null,
382
- env: this.state.env,
383
- component: types_1.LogEventTypes.FEATURE_STEP, // step results always feature_step
384
- status,
385
- start: Date.now() - (duration || 0),
386
- end: Date.now(),
387
- retryable: true,
388
- result: encKey ? (0, processor_utils_1.encrypt)(resultStr, encKey) : resultStr,
389
- input: encKey ? (0, processor_utils_1.encrypt)(inputStr, encKey) : inputStr,
390
- feature_id: this.state.feature_id,
391
- feature_tag: this.state.feature_tag,
392
- product_tag: this.state.product,
393
- workspace_id: this.config.workspace_id,
458
+ const stepResult = Object.assign({ process_id: stepProcessId, product_id: this.productId || null, env: this.state.env, component: types_1.LogEventTypes.FEATURE_STEP, // step results always feature_step
459
+ status, start: Date.now() - (duration || 0), end: Date.now(), retryable: true, result: encKey ? (0, processor_utils_1.encrypt)(resultStr, encKey) : resultStr, input: encKey ? (0, processor_utils_1.encrypt)(inputStr, encKey) : inputStr, feature_id: this.state.feature_id, feature_tag: this.state.feature_tag, product_tag: this.state.product, workspace_id: this.config.workspace_id, step_tag: step.tag, step_type: stepType, step_error: error, step_duration_ms: duration }, ((_a = this.functionInvocations.get(step.tag)) !== null && _a !== void 0 ? _a : {}));
460
+ this.trace('step.persistence.sent', {
394
461
  step_tag: step.tag,
395
- step_type: stepType, // action | notification | storage | produce | database_action | graph | vector | quota | fallback | child_feature | sleep | wait_for_signal | checkpoint
396
- step_error: error,
397
- step_duration_ms: duration,
398
- };
462
+ step_type: stepType,
463
+ status,
464
+ input: resolvedInput,
465
+ output: value,
466
+ });
399
467
  await this.processorApiService.saveResult(stepResult, this.getAuthPayload());
468
+ this.trace('step.persistence.acknowledged', { step_tag: step.tag, status, process_id: stepProcessId });
400
469
  debugLog('[FeatureExecutor] persistStepResult SUCCESS', { feature_id: this.state.feature_id, step_tag: step.tag });
401
470
  }
402
471
  catch (err) {
@@ -449,7 +518,7 @@ class FeatureExecutor {
449
518
  * Execute the feature
450
519
  */
451
520
  async execute() {
452
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
521
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
453
522
  const startTime = Date.now();
454
523
  debugLog('[FeatureExecutor] execute ENTRY', {
455
524
  feature_id: this.state.feature_id,
@@ -457,6 +526,10 @@ class FeatureExecutor {
457
526
  product: this.state.product,
458
527
  env: this.state.env,
459
528
  });
529
+ this.trace('execution.started', {
530
+ input: this.state.input,
531
+ configured_steps: (_a = this.feature.steps) === null || _a === void 0 ? void 0 : _a.map((step) => ({ tag: step.tag, type: step.type, input: step.input })),
532
+ });
460
533
  try {
461
534
  // Track phase so failures before first step are reported as (initialization)
462
535
  this.state.current_step = '(initialization)';
@@ -469,6 +542,7 @@ class FeatureExecutor {
469
542
  this.productId = this.productBuilder.fetchProductId();
470
543
  }
471
544
  debugLog('[FeatureExecutor] execute product initialized', { feature_id: this.state.feature_id, product_id: this.productId });
545
+ this.trace('product.fetched', { product_id: this.productId, preinitialized: this.preInitializedProduct });
472
546
  // Initialize logging after we have product ID
473
547
  this.initializeLogging();
474
548
  this.state.status = types_1.FeatureStatus.RUNNING;
@@ -489,14 +563,17 @@ class FeatureExecutor {
489
563
  }
490
564
  catch (prefetchErr) {
491
565
  stepLog('Bootstrap prefetch failed (continuing without prefetch)', {
492
- error: (_a = prefetchErr === null || prefetchErr === void 0 ? void 0 : prefetchErr.message) !== null && _a !== void 0 ? _a : String(prefetchErr),
566
+ error: (_b = prefetchErr === null || prefetchErr === void 0 ? void 0 : prefetchErr.message) !== null && _b !== void 0 ? _b : String(prefetchErr),
493
567
  });
494
568
  this.stepBootstrapCache.clear();
495
569
  }
496
570
  // Execute each step
497
571
  for (const step of orderedSteps) {
498
572
  // Check step condition if present
499
- if (step.condition && !(await this.evaluateCondition(step.condition))) {
573
+ const conditionMet = step.condition ? await this.evaluateCondition(step.condition) : true;
574
+ if (step.condition)
575
+ this.trace('step.condition.evaluated', { step_tag: step.tag, condition: step.condition, result: conditionMet });
576
+ if (!conditionMet) {
500
577
  debugLog('[FeatureExecutor] execute step SKIPPED (condition)', { feature_id: this.state.feature_id, step_tag: step.tag });
501
578
  this.logStepEvent(step, `Step ${step.tag} - skipped (condition not met)`, logs_types_1.LogEventStatus.SUCCESS, { skipped: true });
502
579
  continue; // Skip step if condition not met
@@ -517,8 +594,8 @@ class FeatureExecutor {
517
594
  success: result.success,
518
595
  durationMs: result.duration,
519
596
  hasError: !!result.error,
520
- input: result.input,
521
- output: result.output,
597
+ input: sanitizeForLog(result.input),
598
+ output: sanitizeForLog(result.output),
522
599
  });
523
600
  // Log step completion
524
601
  this.logStepEvent(step, result.success ? `Step ${step.tag} - completed` : `Step ${step.tag} - failed`, result.success ? logs_types_1.LogEventStatus.SUCCESS : logs_types_1.LogEventStatus.FAIL, { duration: result.duration, error: result.error });
@@ -530,7 +607,7 @@ class FeatureExecutor {
530
607
  try {
531
608
  stepReturnValue = await this.resolveInput(outputSchema, result.output);
532
609
  }
533
- catch (_p) {
610
+ catch (_q) {
534
611
  stepReturnValue = result.output;
535
612
  }
536
613
  }
@@ -547,22 +624,22 @@ class FeatureExecutor {
547
624
  });
548
625
  if (!result.success) {
549
626
  this.state.failed_step = step.tag;
550
- stepLog('Step failed', { tag: step.tag, error: result.error, allow_fail: (_b = step.options) === null || _b === void 0 ? void 0 : _b.allow_fail, optional: (_c = step.options) === null || _c === void 0 ? void 0 : _c.optional });
627
+ stepLog('Step failed', { tag: step.tag, error: result.error, allow_fail: (_c = step.options) === null || _c === void 0 ? void 0 : _c.allow_fail, optional: (_d = step.options) === null || _d === void 0 ? void 0 : _d.optional });
551
628
  debugLog('[FeatureExecutor] execute step FAILED', {
552
629
  feature_id: this.state.feature_id,
553
630
  step_tag: step.tag,
554
631
  error: result.error,
555
- allow_fail: (_d = step.options) === null || _d === void 0 ? void 0 : _d.allow_fail,
556
- optional: (_e = step.options) === null || _e === void 0 ? void 0 : _e.optional,
632
+ allow_fail: (_e = step.options) === null || _e === void 0 ? void 0 : _e.allow_fail,
633
+ optional: (_f = step.options) === null || _f === void 0 ? void 0 : _f.optional,
557
634
  });
558
635
  // Check if step allows failure
559
- if ((_f = step.options) === null || _f === void 0 ? void 0 : _f.allow_fail) {
636
+ if ((_g = step.options) === null || _g === void 0 ? void 0 : _g.allow_fail) {
560
637
  // Store error but continue
561
638
  this.state.steps[step.tag] = { error: result.error };
562
639
  continue;
563
640
  }
564
641
  // Check if step is optional
565
- if ((_g = step.options) === null || _g === void 0 ? void 0 : _g.optional) {
642
+ if ((_h = step.options) === null || _h === void 0 ? void 0 : _h.optional) {
566
643
  // Don't trigger rollback, just continue
567
644
  continue;
568
645
  }
@@ -574,7 +651,7 @@ class FeatureExecutor {
574
651
  feature_id: this.state.feature_id,
575
652
  success: rollbackResult.success,
576
653
  rolled_back_steps: rollbackResult.rolled_back_steps,
577
- failed_rollbacks: (_j = (_h = rollbackResult.failed_steps) === null || _h === void 0 ? void 0 : _h.length) !== null && _j !== void 0 ? _j : 0,
654
+ failed_rollbacks: (_k = (_j = rollbackResult.failed_steps) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : 0,
578
655
  });
579
656
  // Persist failed feature result
580
657
  await this.persistExecutionResult(types_1.LogEventStatus.FAIL, undefined, result.error);
@@ -585,7 +662,7 @@ class FeatureExecutor {
585
662
  completed_steps: this.state.completed_steps,
586
663
  step_timings: this.state.step_timings,
587
664
  });
588
- await ((_k = this.logService) === null || _k === void 0 ? void 0 : _k.publish());
665
+ await ((_l = this.logService) === null || _l === void 0 ? void 0 : _l.publish());
589
666
  if (this.graphConnectionUsed) {
590
667
  await this.getGraphService().disconnect().catch(() => { });
591
668
  await this.getProcessorService().disconnectBrokerConnections().catch(() => { });
@@ -619,6 +696,7 @@ class FeatureExecutor {
619
696
  this.state.ended_at = Date.now();
620
697
  // Determine output - use last step output or aggregate (resolves $ operators)
621
698
  const output = await this.determineWorkflowOutput();
699
+ this.trace('execution.output.resolved', { output, completed_steps: this.state.completed_steps });
622
700
  stepLog('Run finished (completed)', {
623
701
  status: types_1.FeatureStatus.COMPLETED,
624
702
  completed_steps: this.state.completed_steps,
@@ -634,7 +712,7 @@ class FeatureExecutor {
634
712
  // Persist successful feature result
635
713
  await this.persistExecutionResult(types_1.LogEventStatus.SUCCESS, output);
636
714
  // Fire-and-forget log publish on success so we don't block on log upload
637
- (_l = this.logService) === null || _l === void 0 ? void 0 : _l.publish().catch(() => { });
715
+ (_m = this.logService) === null || _m === void 0 ? void 0 : _m.publish().catch(() => { });
638
716
  if (this.graphConnectionUsed) {
639
717
  await this.getGraphService().disconnect().catch(() => { });
640
718
  await this.getProcessorService().disconnectBrokerConnections().catch(() => { });
@@ -657,8 +735,9 @@ class FeatureExecutor {
657
735
  this.state.status = types_1.FeatureStatus.FAILED;
658
736
  this.state.ended_at = Date.now();
659
737
  const details = formatErrorDetails(error);
660
- const failedAt = (_m = this.state.current_step) !== null && _m !== void 0 ? _m : '(unknown)';
661
- debugLog('[FeatureExecutor] execute FAILED (exception)', Object.assign(Object.assign({ feature_id: this.state.feature_id, feature_tag: this.state.feature_tag, failed_at: failedAt, completed_steps: this.state.completed_steps, error: details.message }, (details.status != null && { http_status: details.status })), (details.responseBody != null && { response_body: details.responseBody })));
738
+ const failedAt = (_o = this.state.current_step) !== null && _o !== void 0 ? _o : '(unknown)';
739
+ debugLog('[FeatureExecutor] execute FAILED (exception)', Object.assign(Object.assign({ feature_id: this.state.feature_id, feature_tag: this.state.feature_tag, failed_at: failedAt, completed_steps: this.state.completed_steps, error: details.message }, (details.status != null && { http_status: details.status })), (details.responseBody != null && { response_body: sanitizeForLog(details.responseBody) })));
740
+ this.trace('execution.failed', { failed_at: failedAt, error: details, completed_steps: this.state.completed_steps });
662
741
  if (details.stack) {
663
742
  debugLog('[FeatureExecutor] execute FAILED stack', details.stack);
664
743
  }
@@ -668,7 +747,7 @@ class FeatureExecutor {
668
747
  : `Failed at ${failedAt}: ${details.message}`;
669
748
  stepLog('Run finished (failed - exception)', Object.assign({ status: types_1.FeatureStatus.FAILED, failed_step: failedAt, error: errorSummary, completed_steps: this.state.completed_steps, step_timings: this.state.step_timings }, (details.reason && { reason: details.reason })));
670
749
  await this.persistExecutionResult(types_1.LogEventStatus.FAIL, undefined, errorSummary);
671
- await ((_o = this.logService) === null || _o === void 0 ? void 0 : _o.publish());
750
+ await ((_p = this.logService) === null || _p === void 0 ? void 0 : _p.publish());
672
751
  if (this.graphConnectionUsed) {
673
752
  await this.getGraphService().disconnect().catch(() => { });
674
753
  await this.getProcessorService().disconnectBrokerConnections().catch(() => { });
@@ -701,12 +780,14 @@ class FeatureExecutor {
701
780
  });
702
781
  let resolvedInput = {};
703
782
  try {
783
+ this.trace('step.input.supplied', { step_tag: step.tag, step_type: step.type, payload: step.input || {} });
704
784
  // Resolve input with data references and all $ operators
705
785
  resolvedInput = (await this.resolveInput(step.input || {}));
786
+ this.trace('step.input.resolved', { step_tag: step.tag, step_type: step.type, payload: resolvedInput });
706
787
  debugLog('[FeatureExecutor] executeStep input', {
707
788
  feature_id: this.state.feature_id,
708
789
  step_tag: step.tag,
709
- input: resolvedInput,
790
+ input: sanitizeForLog(resolvedInput),
710
791
  });
711
792
  let output;
712
793
  // Route steps to dedicated services; only action and notification use ProcessorService.
@@ -733,6 +814,9 @@ class FeatureExecutor {
733
814
  case types_1.FeatureStepType.VECTOR:
734
815
  output = await this.executeVectorStep(step, resolvedInput);
735
816
  break;
817
+ case types_1.FeatureStepType.FUNCTION:
818
+ output = await this.executeFunctionStep(step, resolvedInput);
819
+ break;
736
820
  case types_1.FeatureStepType.QUOTA:
737
821
  output = await this.executeQuotaStep(step, resolvedInput);
738
822
  break;
@@ -774,15 +858,16 @@ class FeatureExecutor {
774
858
  }
775
859
  }
776
860
  const duration = Date.now() - startTime;
861
+ this.trace('step.response.received', { step_tag: step.tag, step_type: step.type, payload: output, duration_ms: duration });
777
862
  debugLog('[FeatureExecutor] executeStep output', {
778
863
  feature_id: this.state.feature_id,
779
864
  step_tag: step.tag,
780
- output,
865
+ output: sanitizeForLog(output),
781
866
  durationMs: duration,
782
867
  });
783
868
  return {
784
869
  success: true,
785
- input: resolvedInput,
870
+ input: sanitizeForLog(resolvedInput),
786
871
  output,
787
872
  duration,
788
873
  };
@@ -794,7 +879,14 @@ class FeatureExecutor {
794
879
  const stepErrorMsg = details.reason != null
795
880
  ? (details.status != null ? `${details.reason} (HTTP ${details.status})` : details.reason)
796
881
  : (details.status != null ? `${details.message} (HTTP ${details.status})` : details.message);
797
- debugLog('[FeatureExecutor] executeStep FAILED', Object.assign(Object.assign({ feature_id: this.state.feature_id, step_tag: step.tag, step_type: step.type, durationMs: duration, input: resolvedInput, error: stepErrorMsg }, (details.status != null && { http_status: details.status })), (details.responseBody != null && { response_body: details.responseBody })));
882
+ debugLog('[FeatureExecutor] executeStep FAILED', Object.assign(Object.assign({ feature_id: this.state.feature_id, step_tag: step.tag, step_type: step.type, durationMs: duration, input: resolvedInput, error: stepErrorMsg }, (details.status != null && { http_status: details.status })), (details.responseBody != null && { response_body: sanitizeForLog(details.responseBody) })));
883
+ this.trace('step.failed', {
884
+ step_tag: step.tag,
885
+ step_type: step.type,
886
+ payload: resolvedInput,
887
+ error: details,
888
+ duration_ms: duration,
889
+ });
798
890
  return {
799
891
  success: false,
800
892
  input: resolvedInput,
@@ -811,9 +903,10 @@ class FeatureExecutor {
811
903
  debugLog('[FeatureExecutor] executeActionStep', { feature_id: this.state.feature_id, step_tag: step.tag, app: step.app });
812
904
  // Step that only returns (no component call): no app → passthrough, output = resolved input
813
905
  if (!step.app) {
906
+ this.trace('action.passthrough', { step_tag: step.tag, payload: input });
814
907
  return input;
815
908
  }
816
- return this.getProcessorService().processAction({
909
+ const payload = {
817
910
  product: this.state.product,
818
911
  env: this.state.env,
819
912
  app: step.app,
@@ -821,25 +914,30 @@ class FeatureExecutor {
821
914
  input: input,
822
915
  retries: ((_a = step.options) === null || _a === void 0 ? void 0 : _a.retries) || 0,
823
916
  cache: (_b = step.options) === null || _b === void 0 ? void 0 : _b.cache,
917
+ session: this.inheritedSession,
824
918
  preloadedBootstrap: this.stepBootstrapCache.get(step.tag),
825
- });
919
+ };
920
+ this.trace('action.request.sent', { step_tag: step.tag, payload });
921
+ return this.getProcessorService().processAction(payload);
826
922
  }
827
923
  /**
828
924
  * Execute a database step: use query/insert/update/delete/upsert for DB operations, execute() for named actions.
829
925
  */
830
926
  async executeDatabaseStep(step, input) {
927
+ var _a;
831
928
  const database = step.database;
832
929
  const product = this.state.product;
833
930
  const env = this.state.env;
834
931
  const event = (step.event || '').toLowerCase();
835
932
  const db = this.getDatabaseService();
836
- const opts = Object.assign({ product, env, database }, input);
933
+ const opts = Object.assign(Object.assign({ product, env, database }, input), { session: (_a = input.session) !== null && _a !== void 0 ? _a : this.inheritedSession });
837
934
  debugLog('[FeatureExecutor] executeDatabaseStep', {
838
935
  feature_id: this.state.feature_id,
839
936
  step_tag: step.tag,
840
937
  database,
841
938
  event,
842
939
  });
940
+ this.trace('database.request.sent', { step_tag: step.tag, event, payload: opts });
843
941
  switch (event) {
844
942
  case 'query':
845
943
  return db.query(opts);
@@ -858,6 +956,7 @@ class FeatureExecutor {
858
956
  database,
859
957
  action: step.event,
860
958
  input: input,
959
+ session: this.inheritedSession,
861
960
  });
862
961
  }
863
962
  }
@@ -868,14 +967,17 @@ class FeatureExecutor {
868
967
  var _a;
869
968
  const event = `${step.notification}:${step.event}`;
870
969
  debugLog('[FeatureExecutor] executeNotificationStep', { feature_id: this.state.feature_id, step_tag: step.tag, event });
871
- return this.getProcessorService().processNotification({
970
+ const payload = {
872
971
  product: this.state.product,
873
972
  env: this.state.env,
874
973
  event,
875
974
  input: input,
876
975
  retries: ((_a = step.options) === null || _a === void 0 ? void 0 : _a.retries) || 0,
976
+ session: this.inheritedSession,
877
977
  preloadedBootstrap: this.stepBootstrapCache.get(step.tag),
878
- });
978
+ };
979
+ this.trace('notification.request.sent', { step_tag: step.tag, payload });
980
+ return this.getProcessorService().processNotification(payload);
879
981
  }
880
982
  /**
881
983
  * Execute a storage step using StorageService (upload, download, or delete by input shape).
@@ -885,9 +987,10 @@ class FeatureExecutor {
885
987
  const product = this.state.product;
886
988
  const env = this.state.env;
887
989
  const storage = step.storage;
888
- const opts = { product, env, storage };
990
+ const opts = { product, env, storage, session: this.inheritedSession };
889
991
  debugLog('[FeatureExecutor] executeStorageStep', { feature_id: this.state.feature_id, step_tag: step.tag, storage, event: step.event });
890
992
  const inp = input;
993
+ this.trace('storage.request.sent', { step_tag: step.tag, event: step.event, payload: Object.assign(Object.assign({}, opts), inp) });
891
994
  if (inp.buffer != null && inp.fileName != null) {
892
995
  return this.getStorageService().upload(Object.assign(Object.assign({}, opts), { fileName: String(inp.fileName), buffer: inp.buffer, mimeType: inp.mimeType != null ? String(inp.mimeType) : undefined }));
893
996
  }
@@ -904,12 +1007,15 @@ class FeatureExecutor {
904
1007
  const event = `${step.broker}:${step.event}`;
905
1008
  const message = (input && input.message != null) ? input.message : (input || {});
906
1009
  debugLog('[FeatureExecutor] executeProduceStep', { feature_id: this.state.feature_id, step_tag: step.tag, event });
907
- return this.getBrokersService().publish({
1010
+ const payload = {
908
1011
  product: this.state.product,
909
1012
  env: this.state.env,
910
1013
  event,
911
1014
  message: message,
912
- });
1015
+ session: this.inheritedBrokerSession(),
1016
+ };
1017
+ this.trace('event.request.sent', { step_tag: step.tag, payload });
1018
+ return this.getBrokersService().publish(payload);
913
1019
  }
914
1020
  /**
915
1021
  * Execute a graph step
@@ -920,6 +1026,7 @@ class FeatureExecutor {
920
1026
  const graphTag = step.graph;
921
1027
  const action = step.event;
922
1028
  debugLog('[FeatureExecutor] executeGraphStep', { feature_id: this.state.feature_id, step_tag: step.tag, graph: graphTag, action });
1029
+ this.trace('graph.request.preparing', { step_tag: step.tag, action, graph: graphTag, payload: input });
923
1030
  this.graphConnectionUsed = true;
924
1031
  await this.getGraphService().connect({
925
1032
  env: this.state.env,
@@ -933,6 +1040,7 @@ class FeatureExecutor {
933
1040
  const result = await this.getGraphService().createNode({
934
1041
  labels: input.labels,
935
1042
  properties: input.properties,
1043
+ session: this.inheritedSession,
936
1044
  });
937
1045
  return result;
938
1046
  }
@@ -940,6 +1048,7 @@ class FeatureExecutor {
940
1048
  const result = await this.getGraphService().updateNode({
941
1049
  id: input.id,
942
1050
  properties: input.properties,
1051
+ session: this.inheritedSession,
943
1052
  });
944
1053
  return result;
945
1054
  }
@@ -947,6 +1056,7 @@ class FeatureExecutor {
947
1056
  const result = await this.getGraphService().deleteNode({
948
1057
  id: input.id,
949
1058
  detach: input.detach,
1059
+ session: this.inheritedSession,
950
1060
  });
951
1061
  return result;
952
1062
  }
@@ -956,17 +1066,19 @@ class FeatureExecutor {
956
1066
  endNodeId: input.endNodeId || input.to,
957
1067
  type: input.type,
958
1068
  properties: input.properties,
1069
+ session: this.inheritedSession,
959
1070
  });
960
1071
  return result;
961
1072
  }
962
1073
  case 'deleteRelationship': {
963
1074
  const result = await this.getGraphService().deleteRelationship({
964
1075
  id: input.id,
1076
+ session: this.inheritedSession,
965
1077
  });
966
1078
  return result;
967
1079
  }
968
1080
  case 'query': {
969
- const result = await this.getGraphService().query(input.query, input.params);
1081
+ const result = await this.getGraphService().query(input.query, input.params, undefined, this.inheritedSession);
970
1082
  return result;
971
1083
  }
972
1084
  case 'findNodes': {
@@ -975,6 +1087,7 @@ class FeatureExecutor {
975
1087
  where: input.where,
976
1088
  limit: input.limit,
977
1089
  skip: input.skip,
1090
+ session: this.inheritedSession,
978
1091
  });
979
1092
  return result;
980
1093
  }
@@ -984,6 +1097,7 @@ class FeatureExecutor {
984
1097
  relationshipTypes: input.relationshipTypes,
985
1098
  direction: input.direction,
986
1099
  maxDepth: input.maxDepth,
1100
+ session: this.inheritedSession,
987
1101
  });
988
1102
  return result;
989
1103
  }
@@ -995,6 +1109,7 @@ class FeatureExecutor {
995
1109
  graph: graphTag,
996
1110
  action,
997
1111
  input,
1112
+ session: this.inheritedSession,
998
1113
  });
999
1114
  return result;
1000
1115
  }
@@ -1008,7 +1123,7 @@ class FeatureExecutor {
1008
1123
  * Execute a vector step (query, upsert, deleteVectors, or custom action via execute).
1009
1124
  */
1010
1125
  async executeVectorStep(step, input) {
1011
- var _a;
1126
+ var _a, _b, _c, _d, _e;
1012
1127
  const vectorTag = step.vector;
1013
1128
  if (!vectorTag) {
1014
1129
  throw new Error(`Vector step "${step.tag}" has no vector tag`);
@@ -1023,21 +1138,22 @@ class FeatureExecutor {
1023
1138
  vector: vectorTag,
1024
1139
  event,
1025
1140
  });
1141
+ this.trace('vector.request.preparing', { step_tag: step.tag, event, vector: vectorTag, payload: input });
1026
1142
  switch (event) {
1027
1143
  case 'query': {
1028
- const result = await svc.query(Object.assign({ product,
1029
- env, tag: vectorTag }, input));
1144
+ const result = await svc.query(Object.assign(Object.assign({ product,
1145
+ env, tag: vectorTag }, input), { session: (_a = input.session) !== null && _a !== void 0 ? _a : this.inheritedSession }));
1030
1146
  return result;
1031
1147
  }
1032
1148
  case 'upsert': {
1033
- const result = await svc.upsert(Object.assign({ product,
1034
- env, tag: vectorTag }, input));
1149
+ const result = await svc.upsert(Object.assign(Object.assign({ product,
1150
+ env, tag: vectorTag }, input), { session: (_b = input.session) !== null && _b !== void 0 ? _b : this.inheritedSession }));
1035
1151
  return result;
1036
1152
  }
1037
1153
  case 'delete':
1038
1154
  case 'deletevectors': {
1039
- const result = await svc.deleteVectors(Object.assign({ product,
1040
- env, tag: vectorTag }, input));
1155
+ const result = await svc.deleteVectors(Object.assign(Object.assign({ product,
1156
+ env, tag: vectorTag }, input), { session: (_c = input.session) !== null && _c !== void 0 ? _c : this.inheritedSession }));
1041
1157
  return result;
1042
1158
  }
1043
1159
  default: {
@@ -1048,9 +1164,10 @@ class FeatureExecutor {
1048
1164
  vector: vectorTag,
1049
1165
  action: step.event,
1050
1166
  input: input,
1167
+ session: this.inheritedSession,
1051
1168
  });
1052
- const op = (_a = resolved === null || resolved === void 0 ? void 0 : resolved._operation) !== null && _a !== void 0 ? _a : resolved === null || resolved === void 0 ? void 0 : resolved.operation;
1053
- const opts = Object.assign({ product, env, tag: vectorTag }, resolved);
1169
+ const op = (_d = resolved === null || resolved === void 0 ? void 0 : resolved._operation) !== null && _d !== void 0 ? _d : resolved === null || resolved === void 0 ? void 0 : resolved.operation;
1170
+ const opts = Object.assign(Object.assign({ product, env, tag: vectorTag }, resolved), { session: (_e = resolved.session) !== null && _e !== void 0 ? _e : this.inheritedSession });
1054
1171
  if (op === 'query' || !op) {
1055
1172
  return svc.query(opts);
1056
1173
  }
@@ -1064,6 +1181,46 @@ class FeatureExecutor {
1064
1181
  }
1065
1182
  }
1066
1183
  }
1184
+ /** Execute a portable application function through a local handler or signed HTTP transport. */
1185
+ async executeFunctionStep(step, input) {
1186
+ const reference = step.function_ref;
1187
+ if (!reference) {
1188
+ throw new Error(`Function step "${step.tag}" has no function_ref. Recompile the feature with ctx.functions.`);
1189
+ }
1190
+ const invocationId = (0, crypto_1.randomUUID)();
1191
+ this.functionInvocations.set(step.tag, {
1192
+ invocation_id: invocationId,
1193
+ namespace: reference.namespace,
1194
+ operation: reference.operation,
1195
+ version: reference.version,
1196
+ });
1197
+ const deadlineAt = reference.timeout_ms ? Date.now() + reference.timeout_ms : undefined;
1198
+ this.trace('function.resolution.started', {
1199
+ step_tag: step.tag,
1200
+ invocation_id: invocationId,
1201
+ function: `${reference.namespace}.${reference.operation}@${reference.version}`,
1202
+ transports: reference.transports.map(transport => transport.type),
1203
+ payload: input,
1204
+ });
1205
+ const output = await functions_1.portableFunctions.invoke(reference, input, {
1206
+ product: this.state.product,
1207
+ env: this.state.env,
1208
+ workspace_id: this.config.workspace_id,
1209
+ feature_id: this.state.feature_id,
1210
+ feature_tag: this.state.feature_tag,
1211
+ step_tag: step.tag,
1212
+ invocation_id: invocationId,
1213
+ session: this.inheritedSession,
1214
+ deadline_at: deadlineAt,
1215
+ }, this.config.access_key);
1216
+ this.trace('function.response.received', {
1217
+ step_tag: step.tag,
1218
+ invocation_id: invocationId,
1219
+ function: `${reference.namespace}.${reference.operation}@${reference.version}`,
1220
+ payload: output,
1221
+ });
1222
+ return output;
1223
+ }
1067
1224
  /**
1068
1225
  * Execute a quota step
1069
1226
  */
@@ -1074,6 +1231,7 @@ class FeatureExecutor {
1074
1231
  env: this.state.env,
1075
1232
  tag: step.quota,
1076
1233
  input,
1234
+ session: this.inheritedSession,
1077
1235
  });
1078
1236
  }
1079
1237
  /**
@@ -1086,6 +1244,7 @@ class FeatureExecutor {
1086
1244
  env: this.state.env,
1087
1245
  tag: step.fallback,
1088
1246
  input,
1247
+ session: this.inheritedSession,
1089
1248
  });
1090
1249
  }
1091
1250
  /**
@@ -1112,7 +1271,8 @@ class FeatureExecutor {
1112
1271
  env: this.state.env,
1113
1272
  tag: childTag,
1114
1273
  input,
1115
- }, this._privateKey);
1274
+ session: this.inheritedSession,
1275
+ }, this._privateKey, this.sessionLogFields, this.productBuilder);
1116
1276
  const result = await childExecutor.execute();
1117
1277
  debugLog('[FeatureExecutor] executeChildWorkflowStep result', {
1118
1278
  feature_id: this.state.feature_id,
@@ -1387,12 +1547,13 @@ class FeatureExecutor {
1387
1547
  * Execute a rollback handler
1388
1548
  */
1389
1549
  async executeRollbackHandler(rollback, stepOutput) {
1390
- var _a, _b, _c, _d, _e, _f, _g;
1550
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
1391
1551
  if (!rollback)
1392
1552
  return;
1393
1553
  debugLog('[FeatureExecutor] executeRollbackHandler', { feature_id: this.state.feature_id, rollback_type: rollback.type });
1394
1554
  // Resolve rollback input, including step output references
1395
1555
  const resolvedInput = await this.resolveInput(rollback.input || {}, stepOutput);
1556
+ this.trace('rollback.input.resolved', { rollback_type: rollback.type, payload: resolvedInput });
1396
1557
  switch (rollback.type) {
1397
1558
  case types_1.FeatureStepType.ACTION:
1398
1559
  await this.getProcessorService().processAction({
@@ -1402,6 +1563,7 @@ class FeatureExecutor {
1402
1563
  action: rollback.event,
1403
1564
  input: resolvedInput,
1404
1565
  retries: (_a = rollback.retries) !== null && _a !== void 0 ? _a : 0,
1566
+ session: this.inheritedSession,
1405
1567
  });
1406
1568
  break;
1407
1569
  case types_1.FeatureStepType.DATABASE_ACTION: {
@@ -1410,7 +1572,7 @@ class FeatureExecutor {
1410
1572
  const env = this.state.env;
1411
1573
  const database = rollback.database;
1412
1574
  const event = ((_b = rollback.event) !== null && _b !== void 0 ? _b : '').toLowerCase();
1413
- const opts = Object.assign({ product, env, database }, resolvedInput);
1575
+ const opts = Object.assign(Object.assign({ product, env, database }, resolvedInput), { session: (_c = resolvedInput.session) !== null && _c !== void 0 ? _c : this.inheritedSession });
1414
1576
  if (event === 'query')
1415
1577
  await db.query(opts);
1416
1578
  else if (event === 'insert')
@@ -1428,6 +1590,7 @@ class FeatureExecutor {
1428
1590
  database,
1429
1591
  action: rollback.event,
1430
1592
  input: resolvedInput,
1593
+ session: this.inheritedSession,
1431
1594
  });
1432
1595
  break;
1433
1596
  }
@@ -1438,14 +1601,15 @@ class FeatureExecutor {
1438
1601
  env: this.state.env,
1439
1602
  event: notifEvent,
1440
1603
  input: resolvedInput,
1441
- retries: (_c = rollback.retries) !== null && _c !== void 0 ? _c : 0,
1604
+ retries: (_d = rollback.retries) !== null && _d !== void 0 ? _d : 0,
1605
+ session: this.inheritedSession,
1442
1606
  });
1443
1607
  break;
1444
1608
  case types_1.FeatureStepType.STORAGE: {
1445
1609
  const product = this.state.product;
1446
1610
  const env = this.state.env;
1447
1611
  const storage = rollback.storage;
1448
- const opts = { product, env, storage };
1612
+ const opts = { product, env, storage, session: this.inheritedSession };
1449
1613
  const inp = resolvedInput;
1450
1614
  if (inp.buffer != null && inp.fileName != null) {
1451
1615
  await this.getStorageService().upload(Object.assign(Object.assign({}, opts), { fileName: String(inp.fileName), buffer: inp.buffer, mimeType: inp.mimeType != null ? String(inp.mimeType) : undefined }));
@@ -1454,7 +1618,7 @@ class FeatureExecutor {
1454
1618
  await this.getStorageService().delete(Object.assign(Object.assign({}, opts), { fileName: String(inp.file_key) }));
1455
1619
  }
1456
1620
  else {
1457
- await this.getStorageService().download(Object.assign(Object.assign({}, opts), { fileName: String((_e = (_d = inp.fileName) !== null && _d !== void 0 ? _d : inp.file_key) !== null && _e !== void 0 ? _e : '') }));
1621
+ await this.getStorageService().download(Object.assign(Object.assign({}, opts), { fileName: String((_f = (_e = inp.fileName) !== null && _e !== void 0 ? _e : inp.file_key) !== null && _f !== void 0 ? _f : '') }));
1458
1622
  }
1459
1623
  break;
1460
1624
  }
@@ -1463,16 +1627,16 @@ class FeatureExecutor {
1463
1627
  const env = this.state.env;
1464
1628
  const vectorTag = rollback.vector;
1465
1629
  const inp = resolvedInput;
1466
- const event = ((_f = rollback.event) !== null && _f !== void 0 ? _f : '').toLowerCase();
1630
+ const event = ((_g = rollback.event) !== null && _g !== void 0 ? _g : '').toLowerCase();
1467
1631
  const svc = this.getVectorService();
1468
1632
  if (event === 'query') {
1469
- await svc.query(Object.assign({ product, env, tag: vectorTag }, inp));
1633
+ await svc.query(Object.assign(Object.assign({ product, env, tag: vectorTag }, inp), { session: (_h = inp.session) !== null && _h !== void 0 ? _h : this.inheritedSession }));
1470
1634
  }
1471
1635
  else if (event === 'upsert') {
1472
- await svc.upsert(Object.assign({ product, env, tag: vectorTag }, inp));
1636
+ await svc.upsert(Object.assign(Object.assign({ product, env, tag: vectorTag }, inp), { session: (_j = inp.session) !== null && _j !== void 0 ? _j : this.inheritedSession }));
1473
1637
  }
1474
1638
  else if (event === 'delete' || event === 'deletevectors') {
1475
- await svc.deleteVectors(Object.assign({ product, env, tag: vectorTag }, inp));
1639
+ await svc.deleteVectors(Object.assign(Object.assign({ product, env, tag: vectorTag }, inp), { session: (_k = inp.session) !== null && _k !== void 0 ? _k : this.inheritedSession }));
1476
1640
  }
1477
1641
  else {
1478
1642
  const resolved = await svc.actions.resolve({
@@ -1481,9 +1645,10 @@ class FeatureExecutor {
1481
1645
  vector: vectorTag,
1482
1646
  action: rollback.event,
1483
1647
  input: inp,
1648
+ session: this.inheritedSession,
1484
1649
  });
1485
- const op = (_g = resolved === null || resolved === void 0 ? void 0 : resolved._operation) !== null && _g !== void 0 ? _g : resolved === null || resolved === void 0 ? void 0 : resolved.operation;
1486
- const opts = Object.assign({ product, env, tag: vectorTag }, resolved);
1650
+ const op = (_l = resolved === null || resolved === void 0 ? void 0 : resolved._operation) !== null && _l !== void 0 ? _l : resolved === null || resolved === void 0 ? void 0 : resolved.operation;
1651
+ const opts = Object.assign(Object.assign({ product, env, tag: vectorTag }, resolved), { session: (_m = resolved.session) !== null && _m !== void 0 ? _m : this.inheritedSession });
1487
1652
  if (op === 'upsert')
1488
1653
  await svc.upsert(opts);
1489
1654
  else if (op === 'delete' || op === 'deleteVectors')
@@ -1501,6 +1666,7 @@ class FeatureExecutor {
1501
1666
  env: this.state.env,
1502
1667
  event: pubEvent,
1503
1668
  input: resolvedInput,
1669
+ session: this.inheritedSession,
1504
1670
  });
1505
1671
  break;
1506
1672
  }
@@ -1830,6 +1996,7 @@ class FeatureExecutor {
1830
1996
  env_slug: env,
1831
1997
  steps: workflowSteps,
1832
1998
  });
1999
+ this.trace('bootstrap.response.fetched', { requested_steps: workflowSteps, payload: bootstraps });
1833
2000
  stepLog('Bootstrap feature API response', {
1834
2001
  received_keys: Object.keys(bootstraps),
1835
2002
  keys_count: Object.keys(bootstraps).length,
@@ -1853,6 +2020,7 @@ class FeatureExecutor {
1853
2020
  var _a;
1854
2021
  try {
1855
2022
  const broker = await this.productBuilder.fetchMessageBroker(tag);
2023
+ this.trace('resource.fetched', { resource_type: 'event', resource_tag: tag, payload: broker });
1856
2024
  return { tag, found: !!broker };
1857
2025
  }
1858
2026
  catch (e) {
@@ -1874,6 +2042,7 @@ class FeatureExecutor {
1874
2042
  var _a;
1875
2043
  try {
1876
2044
  const db = await this.productBuilder.fetchDatabase(tag);
2045
+ this.trace('resource.fetched', { resource_type: 'database', resource_tag: tag, payload: db });
1877
2046
  return { tag, found: !!db };
1878
2047
  }
1879
2048
  catch (e) {
@@ -1895,6 +2064,7 @@ class FeatureExecutor {
1895
2064
  var _a;
1896
2065
  try {
1897
2066
  const graph = await this.productBuilder.fetchGraph(tag);
2067
+ this.trace('resource.fetched', { resource_type: 'graph', resource_tag: tag, payload: graph });
1898
2068
  return { tag, found: !!graph };
1899
2069
  }
1900
2070
  catch (e) {
@@ -1915,6 +2085,7 @@ class FeatureExecutor {
1915
2085
  var _a;
1916
2086
  try {
1917
2087
  const vec = await this.productBuilder.fetchVector(tag);
2088
+ this.trace('resource.fetched', { resource_type: 'vector', resource_tag: tag, payload: vec });
1918
2089
  return { tag, found: !!vec };
1919
2090
  }
1920
2091
  catch (e) {
@@ -1936,6 +2107,7 @@ class FeatureExecutor {
1936
2107
  var _a;
1937
2108
  try {
1938
2109
  const quota = await this.productBuilder.fetchQuota(tag);
2110
+ this.trace('resource.fetched', { resource_type: 'quota', resource_tag: tag, payload: quota });
1939
2111
  return { tag, found: !!quota };
1940
2112
  }
1941
2113
  catch (e) {