{"version":3,"sources":["../src/circuit-breaker.ts","../src/events-config.ts","../src/event.ts"],"names":["getConfig","trace","getOperationContext","getEventsConfig","getOrCreateCorrelationId","context","propagation","getValidationConfig","validateEvent","getLogger"],"mappings":"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","file":"chunk-WZOKY3PW.cjs","sourcesContent":["/**\n * Circuit breaker for event subscribers\n *\n * Prevents cascading failures by fast-failing when an (subscriber) is unhealthy.\n * Uses the circuit breaker pattern with three states:\n * - CLOSED: Normal operation ((subscriber) working)\n * - OPEN: Fast-fail mode ((subscriber) down)\n * - HALF_OPEN: Testing if (subscriber) recovered\n */\n\nexport interface CircuitBreakerConfig {\n  /** Number of failures before opening circuit (default: 5) */\n  failureThreshold: number;\n  /** Time to wait before trying again in ms (default: 30000 = 30s) */\n  resetTimeout: number;\n  /** Time window for counting failures in ms (default: 60000 = 1min) */\n  windowSize: number;\n}\n\nconst DEFAULT_CONFIG: CircuitBreakerConfig = {\n  failureThreshold: 5,\n  resetTimeout: 30_000, // 30 seconds\n  windowSize: 60_000, // 1 minute\n};\n\nexport type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';\n\nexport const CircuitState = {\n  CLOSED: 'CLOSED' as const, // Normal operation\n  OPEN: 'OPEN' as const, // Fast-fail mode\n  HALF_OPEN: 'HALF_OPEN' as const, // Testing recovery\n} as const;\n\ninterface FailureRecord {\n  timestamp: number;\n  error: string;\n}\n\n/**\n * Circuit breaker implementation\n *\n * Tracks failures and automatically opens the circuit to prevent\n * overwhelming failing subscribers.\n */\nexport class CircuitBreaker {\n  private state: CircuitState = CircuitState.CLOSED;\n  private failures: FailureRecord[] = [];\n  private lastFailureTime: number = 0;\n  private readonly config: CircuitBreakerConfig;\n  private readonly name: string;\n\n  constructor(name: string, config?: Partial<CircuitBreakerConfig>) {\n    this.name = name;\n    this.config = { ...DEFAULT_CONFIG, ...config };\n  }\n\n  /**\n   * Execute a function with circuit breaker protection\n   * Throws CircuitOpenError if circuit is open\n   */\n  async execute<T>(fn: () => Promise<T>): Promise<T> {\n    // Check if circuit is open\n    if (this.state === CircuitState.OPEN) {\n      // Check if we should transition to half-open\n      const now = Date.now();\n      if (now - this.lastFailureTime >= this.config.resetTimeout) {\n        this.state = CircuitState.HALF_OPEN;\n      } else {\n        throw new CircuitOpenError(\n          `Circuit breaker is OPEN for ${this.name}. ` +\n            `Will retry in ${Math.ceil((this.config.resetTimeout - (now - this.lastFailureTime)) / 1000)}s`,\n        );\n      }\n    }\n\n    try {\n      const result = await fn();\n\n      // Success! Close circuit if it was half-open\n      if (this.state === CircuitState.HALF_OPEN) {\n        this.reset();\n      }\n\n      return result;\n    } catch (error) {\n      this.recordFailure(error);\n      throw error;\n    }\n  }\n\n  /**\n   * Record a failure and potentially open the circuit\n   */\n  private recordFailure(error: unknown): void {\n    const now = Date.now();\n\n    // Remove old failures outside the time window\n    this.failures = this.failures.filter(\n      (f) => now - f.timestamp < this.config.windowSize,\n    );\n\n    // Record new failure\n    this.failures.push({\n      timestamp: now,\n      error: error instanceof Error ? error.message : String(error),\n    });\n\n    this.lastFailureTime = now;\n\n    // Check if we should open the circuit\n    if (this.failures.length >= this.config.failureThreshold) {\n      if (this.state === CircuitState.HALF_OPEN) {\n        // Failed during test - reopen circuit\n        this.state = CircuitState.OPEN;\n      } else if (this.state === CircuitState.CLOSED) {\n        // Too many failures - open circuit\n        this.state = CircuitState.OPEN;\n      }\n    }\n  }\n\n  /**\n   * Reset the circuit breaker (on success)\n   */\n  private reset(): void {\n    this.state = CircuitState.CLOSED;\n    this.failures = [];\n    this.lastFailureTime = 0;\n  }\n\n  /**\n   * Get current state (for monitoring)\n   */\n  getState(): CircuitState {\n    return this.state;\n  }\n\n  /**\n   * Get failure count in current window\n   */\n  getFailureCount(): number {\n    const now = Date.now();\n    // Clean up old failures\n    this.failures = this.failures.filter(\n      (f) => now - f.timestamp < this.config.windowSize,\n    );\n    return this.failures.length;\n  }\n\n  /**\n   * Get recent failures (for debugging)\n   */\n  getRecentFailures(): FailureRecord[] {\n    const now = Date.now();\n    return this.failures.filter(\n      (f) => now - f.timestamp < this.config.windowSize,\n    );\n  }\n\n  /**\n   * Manually reset the circuit breaker (for testing or manual intervention)\n   */\n  forceReset(): void {\n    this.reset();\n  }\n\n  /**\n   * Manually open the circuit (for testing or manual intervention)\n   */\n  forceOpen(): void {\n    this.state = CircuitState.OPEN;\n    this.lastFailureTime = Date.now();\n  }\n}\n\n/**\n * Error thrown when circuit is open\n */\nexport class CircuitOpenError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'CircuitOpenError';\n  }\n}\n","/**\n * Events configuration types for trace context, correlation IDs, and enrichment\n *\n * @example Basic usage\n * ```typescript\n * import { init } from 'autotel';\n *\n * init({\n *   service: 'my-app',\n *   events: {\n *     includeTraceContext: true,\n *     traceUrl: (ctx) => `https://grafana.internal/explore?traceId=${ctx.traceId}`\n *   }\n * });\n * ```\n */\n\n/**\n * Context passed to the traceUrl function for generating clickable trace URLs\n */\nexport interface TraceUrlContext {\n  /** Trace ID (32 hex chars) - may be undefined outside a trace */\n  traceId?: string;\n  /** Span ID (16 hex chars) - may be undefined outside a trace */\n  spanId?: string;\n  /** Correlation ID (always present, 16 hex chars) */\n  correlationId: string;\n  /** Service name from init config */\n  serviceName: string;\n  /** Environment from init config */\n  environment?: string;\n}\n\n/**\n * Per-key transform options for baggage enrichment\n */\nexport type BaggageTransform = 'plain' | 'hash' | ((value: string) => string);\n\n/**\n * Baggage enrichment configuration with guardrails\n */\nexport interface EnrichFromBaggageConfig {\n  /**\n   * Allowlist of baggage keys to include in events\n   * Supports exact matches and patterns (e.g., 'tenant.*')\n   */\n  allow: string[];\n\n  /**\n   * Optional denylist of baggage keys to exclude\n   * Takes precedence over allow list\n   */\n  deny?: string[];\n\n  /**\n   * Optional prefix to add to all enriched keys\n   * @example 'ctx.' results in 'ctx.tenant.id'\n   */\n  prefix?: string;\n\n  /**\n   * Maximum number of keys to include (default: 10)\n   * Prevents payload bloat from excessive baggage\n   */\n  maxKeys?: number;\n\n  /**\n   * Maximum total bytes for enriched values (default: 1024)\n   * Prevents payload bloat from large baggage values\n   */\n  maxBytes?: number;\n\n  /**\n   * Per-key transform options\n   * - 'plain': Include value as-is\n   * - 'hash': Hash the value (for PII protection)\n   * - function: Custom transform function\n   *\n   * @example\n   * ```typescript\n   * transform: {\n   *   'user.id': 'hash',      // Hash user ID for privacy\n   *   'tenant.id': 'plain',   // Include tenant ID as-is\n   *   'session.id': (v) => v.slice(0, 8) // Custom truncation\n   * }\n   * ```\n   */\n  transform?: Record<string, BaggageTransform>;\n}\n\n/**\n * Events configuration for trace context and enrichment\n */\nexport interface EventsConfig {\n  /**\n   * Include trace context in events (default: false)\n   *\n   * When enabled, events automatically include:\n   * - autotel.trace_id (32 hex chars)\n   * - autotel.span_id (16 hex chars)\n   * - autotel.trace_flags (2 hex chars)\n   * - autotel.trace_state (raw tracestate string, if present)\n   * - autotel.correlation_id (always present, 16 hex chars)\n   *\n   * Subscribers map these to platform-specific names:\n   * - PostHog: $trace_id, $span_id\n   * - Mixpanel: trace_id, span_id\n   */\n  includeTraceContext?: boolean;\n\n  /**\n   * Include full array of linked trace IDs for batch/fan-in scenarios (default: false)\n   *\n   * When false (default), batch/fan-in events include:\n   * - autotel.linked_trace_id_count: Number of linked parents\n   * - autotel.linked_trace_id_hash: Stable hash of sorted IDs (keeps payload lean)\n   *\n   * When true, events also include:\n   * - autotel.linked_trace_ids: Full array of linked trace IDs\n   */\n  includeLinkedTraceIds?: boolean;\n\n  /**\n   * Generate clickable trace URL from context\n   *\n   * @param ctx - Trace context with traceId, spanId, correlationId, serviceName, environment\n   * @returns URL string or undefined to skip\n   *\n   * @example Grafana Tempo\n   * ```typescript\n   * traceUrl: (ctx) => ctx.traceId\n   *   ? `https://grafana.internal/explore?traceId=${ctx.traceId}`\n   *   : undefined\n   * ```\n   *\n   * @example Datadog\n   * ```typescript\n   * traceUrl: (ctx) => ctx.traceId\n   *   ? `https://app.datadoghq.com/apm/traces?traceId=${ctx.traceId}`\n   *   : undefined\n   * ```\n   *\n   * @example Jaeger\n   * ```typescript\n   * traceUrl: (ctx) => ctx.traceId\n   *   ? `https://jaeger.internal/trace/${ctx.traceId}`\n   *   : undefined\n   * ```\n   */\n  traceUrl?: (ctx: TraceUrlContext) => string | undefined;\n\n  /**\n   * Auto-enrich events from baggage with guardrails\n   *\n   * Automatically includes baggage entries in events without manual code.\n   * Apply allow/deny lists and per-key transforms for PII protection.\n   *\n   * @example Basic allowlist\n   * ```typescript\n   * enrichFromBaggage: {\n   *   allow: ['tenant.id', 'user.id', 'request.id']\n   * }\n   * // Events include: tenant.id, user.id, request.id from baggage\n   * ```\n   *\n   * @example With prefix and transforms\n   * ```typescript\n   * enrichFromBaggage: {\n   *   allow: ['tenant.id', 'user.id', 'user.email'],\n   *   deny: ['user.ssn'],\n   *   prefix: 'ctx.',\n   *   transform: {\n   *     'user.id': 'hash',\n   *     'user.email': 'hash'\n   *   }\n   * }\n   * // Events include: ctx.tenant.id, ctx.user.id (hashed), ctx.user.email (hashed)\n   * ```\n   */\n  enrichFromBaggage?: EnrichFromBaggageConfig;\n}\n\n/**\n * Autotel context object attached to event envelopes\n *\n * This structured object is attached to events and subscribers\n * decide how to map/flatten for their platform.\n */\nexport interface AutotelEventContext {\n  /** Trace ID (32 hex chars) - present when inside a trace */\n  trace_id?: string;\n  /** Span ID (16 hex chars) - present when inside a span */\n  span_id?: string;\n  /** Trace flags (2 hex chars, e.g., '01' for sampled) */\n  trace_flags?: string;\n  /** Raw tracestate string - present if tracestate exists */\n  trace_state?: string;\n  /** Clickable trace URL - present if traceUrl config is set */\n  trace_url?: string;\n  /** Correlation ID (always present, 16 hex chars) */\n  correlation_id: string;\n  /** Number of linked parent traces (batch/fan-in scenarios) */\n  linked_trace_id_count?: number;\n  /** Stable hash of linked trace IDs (default for batch/fan-in) */\n  linked_trace_id_hash?: string;\n  /** Full array of linked trace IDs (only if includeLinkedTraceIds: true) */\n  linked_trace_ids?: string[];\n}\n\n/**\n * Hash a string value for PII protection\n *\n * Uses a simple, fast hash function suitable for correlation.\n * NOT cryptographically secure - use for PII masking, not security.\n */\nexport function hashValue(value: string): string {\n  let hash = 0;\n  for (let i = 0; i < value.length; i++) {\n    const char = value.charCodeAt(i);\n    hash = (hash << 5) - hash + char;\n    hash = hash & hash; // Convert to 32-bit integer\n  }\n  // Convert to positive hex string\n  return (hash >>> 0).toString(16).padStart(8, '0');\n}\n\n/**\n * Create a stable hash of an array of trace IDs\n *\n * Sorts the array first to ensure deterministic output regardless of order.\n */\nexport function hashLinkedTraceIds(traceIds: string[]): string {\n  const sorted = [...traceIds].sort();\n  return hashValue(sorted.join(','));\n}\n","/**\n * Events API for product events platforms\n *\n * Track user behavior, business events, and critical actions.\n * Sends to product events platforms (PostHog, Mixpanel, Amplitude) via subscribers.\n * For business people who think in events/funnels.\n *\n * For OpenTelemetry metrics (Prometheus/Grafana), use the Metrics class instead.\n *\n * @example Recommended: Configure subscribers in init(), use track() function\n * ```typescript\n * import { init, track } from 'autotel';\n * import { PostHogSubscriber } from 'autotel-subscribers/posthog';\n *\n * init({\n *   service: 'my-app',\n *   subscribers: [new PostHogSubscriber({ apiKey: 'phc_...' })]\n * });\n *\n * // Track events - uses subscribers from init()\n * track('application.submitted', { jobId: '123', userId: '456' });\n * ```\n *\n * @example Create Event instance (inherits subscribers from init)\n * ```typescript\n * import { Event } from 'autotel/event';\n *\n * // Uses subscribers configured in init()\n * const event = new Event('job-application');\n * event.trackEvent('application.submitted', { jobId: '123' });\n * ```\n *\n * @example Override subscribers for specific Event instance\n * ```typescript\n * import { Event } from 'autotel/event';\n * import { PostHogSubscriber } from 'autotel-subscribers/posthog';\n *\n * // Override: use different subscribers for this instance\n * const event = new Event('job-application', {\n *   subscribers: [new PostHogSubscriber({ apiKey: 'phc_different_project' })]\n * });\n *\n * event.trackEvent('application.submitted', { jobId: '123' });\n * ```\n */\n\nimport { trace, propagation, context, TraceFlags } from '@opentelemetry/api';\nimport { type Logger } from './logger';\nimport {\n  getLogger,\n  getValidationConfig,\n  getConfig,\n  getEventsConfig,\n} from './init';\nimport {\n  type EventSubscriber,\n  type EventAttributes,\n  type EventAttributesInput,\n  type FunnelStatus,\n  type OutcomeStatus,\n  type AutotelEventContext,\n} from './event-subscriber';\nimport { type EventCollector } from './event-testing';\nimport { CircuitBreaker, CircuitOpenError } from './circuit-breaker';\nimport { validateEvent } from './validation';\nimport { getOperationContext } from './operation-context';\nimport {\n  type EnrichFromBaggageConfig,\n  hashValue,\n  hashLinkedTraceIds,\n} from './events-config';\nimport { getOrCreateCorrelationId } from './correlation-id';\n\n// Re-export types for convenience\nexport type {\n  EventAttributes,\n  EventAttributesInput,\n  FunnelStatus,\n  OutcomeStatus,\n} from './event-subscriber';\n\n/**\n * Events class for tracking user behavior and product events\n *\n * Track critical indicators such as:\n * - User events (signups, purchases, feature usage)\n * - Conversion funnels (signup → activation → purchase)\n * - Business outcomes (success/failure rates)\n * - Product metrics (revenue, engagement, retention)\n *\n * All events are sent to events platforms via subscribers (PostHog, Mixpanel, etc.).\n * For OpenTelemetry metrics, use the Metrics class instead.\n */\n/**\n * Events options\n */\nexport interface EventsOptions {\n  /** Optional logger for audit trail */\n  logger?: Logger;\n  /** Optional collector for testing (captures events in memory) */\n  collector?: EventCollector;\n  /**\n   * Optional subscribers to send events to other platforms\n   * (e.g., PostHog, Mixpanel, Amplitude)\n   *\n   * **Subscriber Resolution**:\n   * - If provided → uses these subscribers (instance override)\n   * - If not provided → falls back to subscribers from `init()` (global config)\n   * - If neither → no subscribers (events logged only)\n   *\n   * Install `autotel-subscribers` package for ready-made subscribers\n   */\n  subscribers?: EventSubscriber[];\n}\n\nexport class Event {\n  private serviceName: string;\n  private logger?: Logger;\n  private collector?: EventCollector;\n  private subscribers: EventSubscriber[];\n  private hasSubscribers: boolean; // Cached for performance\n  private circuitBreakers: Map<EventSubscriber, CircuitBreaker>; // One per subscriber\n\n  /**\n   * Create a new Event instance\n   *\n   * **Note**: Most users should use `init()` + `track()` instead of creating Event instances directly.\n   *\n   * **Subscriber Resolution**:\n   * - If `subscribers` provided in options → uses those (instance override)\n   * - If `subscribers` not provided → falls back to subscribers from `init()` (global config)\n   * - If neither → no subscribers (events logged only)\n   *\n   * @param serviceName - Service name for identifying events\n   * @param options - Optional configuration (logger, collector, subscribers)\n   *\n   * @example Recommended: Use track() with init()\n   * ```typescript\n   * import { init, track } from 'autotel';\n   * import { PostHogSubscriber } from 'autotel-subscribers/posthog';\n   *\n   * init({\n   *   service: 'checkout',\n   *   subscribers: [new PostHogSubscriber({ apiKey: 'phc_...' })]\n   * });\n   *\n   * track('purchase.completed', { amount: 99.99 });\n   * ```\n   *\n   * @example Inherit subscribers from init()\n   * ```typescript\n   * // Uses subscribers configured in init()\n   * const event = new Event('checkout');\n   * event.trackEvent('purchase.completed', { amount: 99.99 });\n   * ```\n   *\n   * @example Override subscribers for this instance\n   * ```typescript\n   * import { Event } from 'autotel/event';\n   * import { PostHogSubscriber } from 'autotel-subscribers/posthog';\n   *\n   * // Override: use different subscribers for this instance only\n   * const event = new Event('checkout', {\n   *   subscribers: [new PostHogSubscriber({ apiKey: 'phc_different_project' })]\n   * });\n   * ```\n   */\n  constructor(serviceName: string, options: EventsOptions = {}) {\n    this.serviceName = serviceName;\n    this.logger = options.logger;\n    this.collector = options.collector;\n\n    // Subscriber resolution: instance-level overrides global init() config\n    // If subscribers provided to constructor, use those\n    // Otherwise, fall back to subscribers from init()\n    this.subscribers =\n      options.subscribers === undefined\n        ? getConfig()?.subscribers || []\n        : options.subscribers;\n\n    this.hasSubscribers = this.subscribers.length > 0; // Cache for hot path\n\n    // Create circuit breaker for each subscriber\n    this.circuitBreakers = new Map();\n    for (const subscriber of this.subscribers) {\n      const subscriberName = subscriber.name || 'Unknown';\n      this.circuitBreakers.set(\n        subscriber,\n        new CircuitBreaker(subscriberName, {\n          failureThreshold: 5,\n          resetTimeout: 30_000, // 30s\n          windowSize: 60_000, // 1min\n        }),\n      );\n    }\n  }\n\n  /**\n   * Automatically enrich attributes with all available telemetry context\n   *\n   * Auto-captures:\n   * - Resource attributes: service.version, deployment.environment\n   * - Trace context: traceId, spanId, correlationId\n   * - Operation context: operation.name\n   */\n  private enrichWithTelemetryContext(\n    attributes: EventAttributes = {},\n  ): EventAttributes {\n    const enriched: EventAttributes = {\n      service: this.serviceName,\n      ...attributes,\n    };\n\n    // 1. Resource attributes (service-level context)\n    const config = getConfig();\n    if (config) {\n      if (config.version) {\n        enriched['service.version'] = config.version;\n      }\n      if (config.environment) {\n        enriched['deployment.environment'] = config.environment;\n      }\n    }\n\n    // 2. Trace context (if inside a traced operation)\n    const span = trace.getActiveSpan();\n    const spanContext = span?.spanContext();\n    if (spanContext) {\n      enriched.traceId = spanContext.traceId;\n      enriched.spanId = spanContext.spanId;\n      // Add correlation ID (first 16 chars of trace ID) for easier log grouping\n      enriched.correlationId = spanContext.traceId.slice(0, 16);\n    }\n\n    // 3. Operation context (if inside a trace/span)\n    const operationContext = getOperationContext();\n    if (operationContext) {\n      enriched['operation.name'] = operationContext.name;\n    }\n\n    return enriched;\n  }\n\n  /**\n   * Build autotel event context for trace correlation\n   *\n   * Works in 4 contexts:\n   * 1. Inside a span → use current span's trace_id + span_id\n   * 2. Outside span but in AsyncLocalStorage context → use trace_id + correlation_id\n   * 3. Totally standalone → use correlation_id + service/env/version\n   * 4. Batch/fan-in (multiple linked parents) → use count + hash or full array\n   *\n   * @returns AutotelEventContext or undefined if trace context is disabled\n   */\n  private buildAutotelContext(): AutotelEventContext | undefined {\n    const eventsConfig = getEventsConfig();\n\n    // Return undefined if trace context is not enabled\n    if (!eventsConfig?.includeTraceContext) {\n      // Still generate correlation_id even without full trace context\n      // This provides a stable join key across events/logs/spans\n      return {\n        correlation_id: getOrCreateCorrelationId(),\n      };\n    }\n\n    const config = getConfig();\n    const span = trace.getActiveSpan();\n    const spanContext = span?.spanContext();\n\n    // Always generate a correlation_id\n    const correlationId = getOrCreateCorrelationId();\n\n    // Build base context\n    const autotelContext: AutotelEventContext = {\n      correlation_id: correlationId,\n    };\n\n    // Add trace context if inside a span\n    if (spanContext) {\n      autotelContext.trace_id = spanContext.traceId;\n      autotelContext.span_id = spanContext.spanId;\n\n      // Trace flags as 2-char hex string (canonical format)\n      autotelContext.trace_flags = spanContext.traceFlags\n        .toString(16)\n        .padStart(2, '0');\n\n      // Tracestate if present\n      const traceState = spanContext.traceState;\n      if (traceState) {\n        // Convert TraceState to string representation safely\n        let traceStateStr = '';\n        try {\n          if (typeof traceState.serialize === 'function') {\n            traceStateStr = traceState.serialize();\n          }\n        } catch {\n          // Silently ignore serialization errors - traceState is optional metadata\n        }\n        if (traceStateStr) {\n          autotelContext.trace_state = traceStateStr;\n        }\n      }\n\n      // Generate trace URL if configured\n      if (eventsConfig.traceUrl) {\n        const traceUrl = eventsConfig.traceUrl({\n          traceId: spanContext.traceId,\n          spanId: spanContext.spanId,\n          correlationId,\n          serviceName: config?.service || this.serviceName,\n          environment: config?.environment,\n        });\n        if (traceUrl) {\n          autotelContext.trace_url = traceUrl;\n        }\n      }\n\n      // Handle linked spans (batch/fan-in scenarios)\n      // Note: This would require access to span links which are not easily accessible\n      // from the public OpenTelemetry API. For now, we skip this unless we have\n      // explicit linked trace IDs passed in.\n    } else {\n      // Outside span but may still have trace URL generator\n      if (eventsConfig.traceUrl && config) {\n        const traceUrl = eventsConfig.traceUrl({\n          correlationId,\n          serviceName: config.service,\n          environment: config.environment,\n        });\n        if (traceUrl) {\n          autotelContext.trace_url = traceUrl;\n        }\n      }\n    }\n\n    return autotelContext;\n  }\n\n  /**\n   * Enrich event attributes from baggage with guardrails\n   *\n   * @param attributes - Current event attributes\n   * @returns Enriched attributes with baggage values\n   */\n  private enrichFromBaggage(attributes: EventAttributes): EventAttributes {\n    const eventsConfig = getEventsConfig();\n    const enrichConfig = eventsConfig?.enrichFromBaggage;\n\n    if (!enrichConfig) {\n      return attributes;\n    }\n\n    const enriched = { ...attributes };\n    const activeContext = context.active();\n    const baggage = propagation.getBaggage(activeContext);\n\n    if (!baggage) {\n      return enriched;\n    }\n\n    let keyCount = 0;\n    let byteCount = 0;\n    const maxKeys = enrichConfig.maxKeys ?? 10;\n    const maxBytes = enrichConfig.maxBytes ?? 1024;\n    const prefix = enrichConfig.prefix ?? '';\n\n    // Get all baggage entries\n    for (const [key, entry] of baggage.getAllEntries()) {\n      // Check if key is allowed\n      if (!this.isBaggageKeyAllowed(key, enrichConfig)) {\n        continue;\n      }\n\n      // Check limits\n      if (keyCount >= maxKeys) {\n        break;\n      }\n\n      const value = entry.value;\n\n      // Apply transform first so maxBytes is checked against transformed size (e.g. hash output)\n      const transform = enrichConfig.transform?.[key];\n      let transformedValue: string;\n\n      if (transform === 'hash') {\n        transformedValue = hashValue(value);\n      } else if (transform === 'plain' || !transform) {\n        transformedValue = value;\n      } else if (typeof transform === 'function') {\n        transformedValue = transform(value);\n      } else {\n        transformedValue = value;\n      }\n\n      const valueBytes = new TextEncoder().encode(transformedValue).length;\n\n      if (byteCount + valueBytes > maxBytes) {\n        continue; // Skip this entry if transformed value would exceed byte limit\n      }\n\n      // Add to enriched attributes with prefix\n      const enrichedKey = `${prefix}${key}`;\n      enriched[enrichedKey] = transformedValue;\n\n      keyCount++;\n      byteCount += valueBytes;\n    }\n\n    return enriched;\n  }\n\n  /**\n   * Check if a baggage key is allowed based on config\n   */\n  private isBaggageKeyAllowed(\n    key: string,\n    config: EnrichFromBaggageConfig,\n  ): boolean {\n    // Check deny list first (takes precedence)\n    if (config.deny) {\n      for (const pattern of config.deny) {\n        if (this.matchesBaggagePattern(key, pattern)) {\n          return false;\n        }\n      }\n    }\n\n    // Check allow list\n    for (const pattern of config.allow) {\n      if (this.matchesBaggagePattern(key, pattern)) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  /**\n   * Check if a key matches a baggage pattern\n   * Supports exact matches and wildcard patterns (e.g., 'tenant.*')\n   */\n  private matchesBaggagePattern(key: string, pattern: string): boolean {\n    if (pattern.endsWith('.*')) {\n      const prefix = pattern.slice(0, -2);\n      return key.startsWith(prefix + '.');\n    }\n    return key === pattern;\n  }\n\n  /**\n   * Track a business event\n   *\n   * Use this for tracking user actions, business events, product usage:\n   * - \"user.signup\"\n   * - \"order.completed\"\n   * - \"feature.used\"\n   *\n   * Events are sent to configured subscribers (PostHog, Mixpanel, etc.).\n   *\n   * @example\n   * ```typescript\n   * // Track user signup\n   * events.trackEvent('user.signup', {\n   *   userId: '123',\n   *   plan: 'pro'\n   * })\n   *\n   * // Track order\n   * events.trackEvent('order.completed', {\n   *   orderId: 'ord_123',\n   *   amount: 99.99\n   * })\n   * ```\n   */\n  trackEvent(eventName: string, attributes?: EventAttributes): void {\n    // Validate and sanitize input (with custom config if provided)\n    const validationConfig = getValidationConfig();\n    const validated = validateEvent(\n      eventName,\n      attributes,\n      validationConfig || undefined,\n    );\n\n    // Auto-attach all available telemetry context\n    const enrichedAttributes = this.enrichWithTelemetryContext(\n      validated.attributes,\n    );\n\n    this.logger?.info(\n      {\n        event: validated.eventName,\n        attributes: enrichedAttributes,\n      },\n      'Event tracked',\n    );\n\n    // Record for testing\n    this.collector?.recordEvent({\n      event: validated.eventName,\n      attributes: enrichedAttributes,\n      service: this.serviceName,\n      timestamp: Date.now(),\n    });\n\n    // Notify subscribers (zero overhead if no subscribers)\n    // Run in background - don't block event recording\n    if (this.hasSubscribers) {\n      // Build autotel context for trace correlation\n      const autotelContext = this.buildAutotelContext();\n\n      // Enrich from baggage if configured\n      const finalAttributes = this.enrichFromBaggage(enrichedAttributes);\n\n      void this.notifySubscribers((subscriber) =>\n        subscriber.trackEvent(validated.eventName, finalAttributes, {\n          autotel: autotelContext,\n        }),\n      );\n    }\n  }\n\n  /**\n   * Notify all subscribers concurrently without blocking\n   * Uses circuit breakers to protect against failing subscribers\n   * Uses Promise.allSettled to prevent subscriber errors from affecting other subscribers\n   */\n  private async notifySubscribers(\n    fn: (subscriber: EventSubscriber) => Promise<void>,\n  ): Promise<void> {\n    const promises = this.subscribers.map(async (subscriber) => {\n      const circuitBreaker = this.circuitBreakers.get(subscriber);\n      if (!circuitBreaker) return; // Should never happen\n\n      try {\n        // Execute with circuit breaker protection\n        await circuitBreaker.execute(() => fn(subscriber));\n      } catch (error) {\n        // Handle circuit open errors (expected behavior when subscriber is down)\n        if (error instanceof CircuitOpenError) {\n          // Circuit is open - subscriber is down, log at warn level for visibility (same behavior in all environments)\n          getLogger().warn(\n            {\n              subscriberName: subscriber.name || 'Unknown',\n            },\n            `[Events] ${error.message}`,\n          );\n          return;\n        }\n\n        // Log other subscriber errors but don't throw - event failures shouldn't break business logic\n        getLogger().error(\n          {\n            err: error instanceof Error ? error : undefined,\n            subscriberName: subscriber.name || 'Unknown',\n          },\n          `[Events] Subscriber ${subscriber.name || 'Unknown'} failed`,\n        );\n      }\n    });\n\n    // Wait for all subscribers (success or failure)\n    await Promise.allSettled(promises);\n  }\n\n  /**\n   * Track conversion funnel steps\n   *\n   * Monitor where users drop off in multi-step processes.\n   *\n   * @example\n   * ```typescript\n   * // Track signup funnel\n   * events.trackFunnelStep('signup', 'started', { userId: '123' })\n   * events.trackFunnelStep('signup', 'email_verified', { userId: '123' })\n   * events.trackFunnelStep('signup', 'completed', { userId: '123' })\n   *\n   * // Track checkout flow\n   * events.trackFunnelStep('checkout', 'started', { cartValue: 99.99 })\n   * events.trackFunnelStep('checkout', 'payment_info', { cartValue: 99.99 })\n   * events.trackFunnelStep('checkout', 'completed', { cartValue: 99.99 })\n   * ```\n   */\n  trackFunnelStep(\n    funnelName: string,\n    status: FunnelStatus,\n    attributes?: EventAttributes,\n  ): void {\n    // Auto-attach all available telemetry context\n    const enrichedAttributes = this.enrichWithTelemetryContext(attributes);\n\n    this.logger?.info(\n      {\n        funnel: funnelName,\n        status,\n        attributes: enrichedAttributes,\n      },\n      'Funnel step tracked',\n    );\n\n    // Record for testing\n    this.collector?.recordFunnelStep({\n      funnel: funnelName,\n      status,\n      attributes: enrichedAttributes,\n      service: this.serviceName,\n      timestamp: Date.now(),\n    });\n\n    // Notify subscribers\n    if (this.hasSubscribers) {\n      const autotelContext = this.buildAutotelContext();\n      const finalAttributes = this.enrichFromBaggage(enrichedAttributes);\n\n      void this.notifySubscribers((subscriber) =>\n        subscriber.trackFunnelStep(funnelName, status, finalAttributes, {\n          autotel: autotelContext,\n        }),\n      );\n    }\n  }\n\n  /**\n   * Track outcomes (success/failure/partial)\n   *\n   * Monitor success rates of critical operations.\n   *\n   * @example\n   * ```typescript\n   * // Track email delivery\n   * events.trackOutcome('email.delivery', 'success', {\n   *   recipientType: 'user',\n   *   emailType: 'welcome'\n   * })\n   *\n   * events.trackOutcome('email.delivery', 'failure', {\n   *   recipientType: 'user',\n   *   errorCode: 'invalid_email'\n   * })\n   *\n   * // Track payment processing\n   * events.trackOutcome('payment.process', 'success', { amount: 99.99 })\n   * events.trackOutcome('payment.process', 'failure', { error: 'insufficient_funds' })\n   * ```\n   */\n  trackOutcome(\n    operationName: string,\n    status: OutcomeStatus,\n    attributes?: EventAttributes,\n  ): void {\n    // Auto-attach all available telemetry context\n    const enrichedAttributes = this.enrichWithTelemetryContext(attributes);\n\n    this.logger?.info(\n      {\n        operation: operationName,\n        status,\n        attributes: enrichedAttributes,\n      },\n      'Outcome tracked',\n    );\n\n    // Record for testing\n    this.collector?.recordOutcome({\n      operation: operationName,\n      status,\n      attributes: enrichedAttributes,\n      service: this.serviceName,\n      timestamp: Date.now(),\n    });\n\n    // Notify subscribers\n    if (this.hasSubscribers) {\n      const autotelContext = this.buildAutotelContext();\n      const finalAttributes = this.enrichFromBaggage(enrichedAttributes);\n\n      void this.notifySubscribers((subscriber) =>\n        subscriber.trackOutcome(operationName, status, finalAttributes, {\n          autotel: autotelContext,\n        }),\n      );\n    }\n  }\n\n  /**\n   * Track value metrics\n   *\n   * Record numerical values like revenue, transaction amounts,\n   * item counts, processing times, engagement scores, etc.\n   *\n   * @example\n   * ```typescript\n   * // Track revenue\n   * events.trackValue('order.revenue', 149.99, {\n   *   currency: 'USD',\n   *   productCategory: 'electronics'\n   * })\n   *\n   * // Track items per cart\n   * events.trackValue('cart.item_count', 5, {\n   *   userId: '123'\n   * })\n   *\n   * // Track processing time\n   * events.trackValue('api.response_time', 250, {\n   *   unit: 'ms',\n   *   endpoint: '/api/checkout'\n   * })\n   * ```\n   */\n  trackValue(\n    metricName: string,\n    value: number,\n    attributes?: EventAttributes,\n  ): void {\n    // Auto-attach all available telemetry context\n    const enrichedAttributes = this.enrichWithTelemetryContext({\n      metric: metricName,\n      ...attributes,\n    });\n\n    this.logger?.debug(\n      {\n        metric: metricName,\n        value,\n        attributes: enrichedAttributes,\n      },\n      'Value tracked',\n    );\n\n    // Record for testing\n    this.collector?.recordValue({\n      metric: metricName,\n      value,\n      attributes: enrichedAttributes,\n      service: this.serviceName,\n      timestamp: Date.now(),\n    });\n\n    // Notify subscribers\n    if (this.hasSubscribers) {\n      const autotelContext = this.buildAutotelContext();\n      const finalAttributes = this.enrichFromBaggage(enrichedAttributes);\n\n      void this.notifySubscribers((subscriber) =>\n        subscriber.trackValue(metricName, value, finalAttributes, {\n          autotel: autotelContext,\n        }),\n      );\n    }\n  }\n\n  /**\n   * Flush all subscribers and wait for pending events\n   *\n   * Call this before shutdown to ensure all events are delivered.\n   *\n   * @example\n   * ```typescript\n   * const event =new Event('app', { subscribers: [...] });\n   *\n   * // Before shutdown\n   * await events.flush();\n   * ```\n   */\n  async flush(): Promise<void> {\n    if (!this.hasSubscribers) return;\n\n    const shutdownPromises = this.subscribers.map(async (subscriber) => {\n      if (subscriber.shutdown) {\n        try {\n          await subscriber.shutdown();\n        } catch (error) {\n          getLogger().error(\n            {\n              err: error instanceof Error ? error : undefined,\n              subscriberName: subscriber.name || 'Unknown',\n            },\n            `[Events] Failed to shutdown subscriber ${subscriber.name || 'Unknown'}`,\n          );\n        }\n      }\n    });\n\n    await Promise.allSettled(shutdownPromises);\n  }\n\n  /**\n   * Shutdown the Event instance and all subscribers\n   *\n   * Unlike `flush()`, this method:\n   * - Shuts down all subscribers\n   * - Prevents further event tracking (hasSubscribers becomes false)\n   * - Should only be called once at application shutdown\n   *\n   * @example\n   * ```typescript\n   * // In Next.js API route with after()\n   * import { after } from 'next/server';\n   *\n   * export async function POST(req: Request) {\n   *   const event = new Event('checkout', { subscribers: [...] });\n   *   event.trackEvent('order.completed', { orderId: '123' });\n   *\n   *   after(async () => {\n   *     await event.shutdown();\n   *   });\n   *\n   *   return Response.json({ success: true });\n   * }\n   * ```\n   */\n  async shutdown(): Promise<void> {\n    if (!this.hasSubscribers) return;\n\n    await Promise.allSettled(\n      this.subscribers.map(async (subscriber) => {\n        if (subscriber.shutdown) {\n          try {\n            await subscriber.shutdown();\n          } catch (error) {\n            getLogger().error(\n              {\n                err: error instanceof Error ? error : undefined,\n                subscriberName: subscriber.name || 'Unknown',\n              },\n              `[Events] Failed to shutdown subscriber ${subscriber.name || 'Unknown'}`,\n            );\n          }\n        }\n      }),\n    );\n\n    // Prevent further tracking after shutdown\n    this.hasSubscribers = false;\n  }\n\n  /**\n   * Track funnel progression with custom step names\n   *\n   * Unlike trackFunnelStep which uses FunnelStatus enum values,\n   * this method allows any string as the step name for flexible funnel tracking.\n   *\n   * @param funnelName - Name of the funnel (e.g., \"checkout\", \"onboarding\")\n   * @param stepName - Custom step name (e.g., \"cart_viewed\", \"payment_entered\")\n   * @param stepNumber - Optional numeric position in the funnel\n   * @param attributes - Optional event attributes\n   *\n   * @example\n   * ```typescript\n   * // Track custom checkout steps\n   * event.trackFunnelProgression('checkout', 'cart_viewed', 1);\n   * event.trackFunnelProgression('checkout', 'shipping_selected', 2);\n   * event.trackFunnelProgression('checkout', 'payment_entered', 3);\n   * event.trackFunnelProgression('checkout', 'order_confirmed', 4);\n   * ```\n   */\n  trackFunnelProgression(\n    funnelName: string,\n    stepName: string,\n    stepNumber?: number,\n    attributes?: EventAttributes,\n  ): void {\n    // Auto-attach all available telemetry context\n    const enrichedAttributes = this.enrichWithTelemetryContext(attributes);\n\n    this.logger?.info(\n      {\n        funnel: funnelName,\n        stepName,\n        stepNumber,\n        attributes: enrichedAttributes,\n      },\n      'Funnel progression tracked',\n    );\n\n    // Record for testing (as funnel step with custom name)\n    this.collector?.recordFunnelStep({\n      funnel: funnelName,\n      status: stepName as FunnelStatus, // Cast for testing collector\n      attributes: {\n        ...enrichedAttributes,\n        step_name: stepName,\n        ...(stepNumber === undefined ? {} : { step_number: stepNumber }),\n      },\n      service: this.serviceName,\n      timestamp: Date.now(),\n    });\n\n    // Notify subscribers that support trackFunnelProgression\n    if (this.hasSubscribers) {\n      const autotelContext = this.buildAutotelContext();\n      const finalAttributes = this.enrichFromBaggage(enrichedAttributes);\n\n      void this.notifySubscribers(async (subscriber) => {\n        await (subscriber.trackFunnelProgression\n          ? subscriber.trackFunnelProgression(\n              funnelName,\n              stepName,\n              stepNumber,\n              finalAttributes,\n              { autotel: autotelContext },\n            )\n          : // Fall back to trackFunnelStep with step as custom name (cast)\n            subscriber.trackFunnelStep(\n              funnelName,\n              stepName as FunnelStatus,\n              {\n                ...finalAttributes,\n                step_name: stepName,\n                ...(stepNumber === undefined\n                  ? {}\n                  : { step_number: stepNumber }),\n              },\n              { autotel: autotelContext },\n            ));\n      });\n    }\n  }\n\n  /**\n   * Track multiple events in a batch\n   *\n   * Useful for bulk event tracking with consistent timestamps.\n   * Events are sent to subscribers individually but processed together.\n   *\n   * @param events - Array of events to track\n   *\n   * @example\n   * ```typescript\n   * event.trackBatch([\n   *   { name: 'item.viewed', attributes: { itemId: '1' } },\n   *   { name: 'item.viewed', attributes: { itemId: '2' } },\n   *   { name: 'cart.updated', attributes: { itemCount: 2 } },\n   * ]);\n   * ```\n   */\n  trackBatch(\n    events: Array<{ name: string; attributes?: EventAttributesInput }>,\n  ): void {\n    // Filter attributes and track each event\n    for (const event of events) {\n      // Filter undefined/null values from attributes\n      const filteredAttributes = event.attributes\n        ? (Object.fromEntries(\n            Object.entries(event.attributes).filter(\n              ([, v]) => v !== undefined && v !== null,\n            ),\n          ) as EventAttributes)\n        : undefined;\n\n      this.trackEvent(event.name, filteredAttributes);\n    }\n  }\n}\n\n/**\n * Global events instances (singleton pattern)\n */\nconst eventsInstances = new Map<string, Event>();\n\n/**\n * Get or create an Events instance for a service\n *\n * @param serviceName - Service name for identifying events\n * @param logger - Optional logger\n * @returns Events instance\n *\n * @example\n * ```typescript\n * const event =getEvents('job-application')\n * events.trackEvent('application.submitted', { jobId: '123' })\n * ```\n */\nexport function getEvents(serviceName: string, logger?: Logger): Event {\n  if (!eventsInstances.has(serviceName)) {\n    eventsInstances.set(serviceName, new Event(serviceName, { logger }));\n  }\n  return eventsInstances.get(serviceName)!;\n}\n\n/**\n * Reset all events instances (mainly for testing)\n */\nexport function resetEvents(): void {\n  eventsInstances.clear();\n}\n"]}