{"version":3,"file":"event-CcZYwp50.cjs","names":["getConfig","trace","getOperationContext","getEventsConfig","getOrCreateCorrelationId","context","propagation","validateEvent","getValidationConfig"],"sources":["../src/circuit-breaker.ts","../src/events-config.ts","../src/event.ts"],"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"],"mappings":"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"}