{"version":3,"file":"track-Cb3Q4QmS.cjs","names":["nodeAsyncHooks","context","contextWithManager","propagation","nodeAsyncHooks","context","propagation","trace","DEFAULT_CONFIG","getRuntimeConfig","getLogger","getEventsConfig","getConfig","isInitialized","getValidationConfig","trace"],"sources":["../src/rate-limiter.ts","../src/trace-context.ts","../src/correlation-id.ts","../src/event-queue.ts","../src/validation.ts","../src/track.ts"],"sourcesContent":["/**\n * Token bucket rate limiter for event subscribers\n *\n * Prevents overwhelming downstream events platforms with too many events.\n * Uses token bucket algorithm for smooth rate limiting with burst capacity.\n */\n\nexport interface RateLimiterConfig {\n  /** Maximum events per second (default: 100) */\n  maxEventsPerSecond: number;\n  /** Burst capacity - max events in a single burst (default: 2x rate) */\n  burstCapacity?: number;\n}\n\n/**\n * Token bucket rate limiter\n *\n * Allows bursts up to burstCapacity, then smooths to maxEventsPerSecond.\n * Thread-safe for async operations.\n */\nexport class TokenBucketRateLimiter {\n  private tokens: number;\n  private readonly maxTokens: number;\n  private readonly refillRate: number; // tokens per millisecond\n  private lastRefill: number;\n\n  constructor(config: RateLimiterConfig) {\n    this.maxTokens = config.burstCapacity || config.maxEventsPerSecond * 2;\n    this.tokens = this.maxTokens; // Start with full bucket\n    this.refillRate = config.maxEventsPerSecond / 1000; // Convert to per-ms\n    this.lastRefill = Date.now();\n  }\n\n  /**\n   * Try to consume a token (allow an event)\n   * Returns true if allowed, false if rate limit exceeded\n   */\n  tryConsume(count = 1): boolean {\n    this.refill();\n\n    if (this.tokens >= count) {\n      this.tokens -= count;\n      return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Wait until a token is available (async rate limiting)\n   * Returns a promise that resolves when the event can be processed\n   */\n  async waitForToken(count = 1): Promise<void> {\n    this.refill();\n\n    if (this.tokens >= count) {\n      this.tokens -= count;\n      return;\n    }\n\n    // Calculate wait time until we have enough tokens\n    const tokensNeeded = count - this.tokens;\n    const waitMs = Math.ceil(tokensNeeded / this.refillRate);\n\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n\n    // After waiting, try again (recursive)\n    return this.waitForToken(count);\n  }\n\n  /**\n   * Refill tokens based on elapsed time\n   */\n  private refill(): void {\n    const now = Date.now();\n    const elapsed = now - this.lastRefill;\n    const tokensToAdd = elapsed * this.refillRate;\n\n    this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\n    this.lastRefill = now;\n  }\n\n  /**\n   * Get current available tokens (for testing/debugging)\n   */\n  getAvailableTokens(): number {\n    this.refill();\n    return Math.floor(this.tokens);\n  }\n\n  /**\n   * Reset the rate limiter (for testing)\n   */\n  reset(): void {\n    this.tokens = this.maxTokens;\n    this.lastRefill = Date.now();\n  }\n}\n","/**\n * Trace context types and utilities\n */\n\nimport type {\n  Span,\n  SpanStatusCode,\n  BaggageEntry,\n  Context,\n  Link,\n} from '@opentelemetry/api';\nimport { context, propagation } from '@opentelemetry/api';\n// namespace import for browser-bundler compat; `import type` is erased — see node-require.ts\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport * as nodeAsyncHooks from 'node:async_hooks';\nimport { recordStructuredError } from './structured-error';\nimport { track } from './track';\n\ntype AsyncLocalBox<T> = {\n  value: T;\n};\n\n/**\n * AsyncLocalStorage for storing the active context with baggage\n * This allows setters to update the context and have it persist\n */\nconst contextStorage = new nodeAsyncHooks.AsyncLocalStorage<\n  AsyncLocalBox<Context>\n>();\n\n/**\n * Get the context storage instance (for initialization in functional.ts)\n */\nexport function getContextStorage(): AsyncLocalStorage<AsyncLocalBox<Context>> {\n  return contextStorage;\n}\n\n/**\n * Get the active context, checking our stored context first\n * This ensures baggage setters work with OpenTelemetry's propagation\n */\nexport function getActiveContextWithBaggage(): Context {\n  // Check stored context first (from setters), then fall back to active context\n  // This ensures ctx.setBaggage() changes are visible to OpenTelemetry operations\n  const stored = contextStorage.getStore()?.value;\n  return stored ?? context.active();\n}\n\n/**\n * Set a value in AsyncLocalStorage, preferring enterWith() when available\n * (Node.js) and falling back to run() for environments that only support\n * run() (e.g. Cloudflare Workers).\n *\n * On runtimes without enterWith() we mutate the existing run() scope when one\n * exists. This is what allows baggage/correlation updates to remain visible\n * for the rest of the traced callback in Workers.\n */\nexport function enterOrRun<T>(\n  storage: AsyncLocalStorage<AsyncLocalBox<T>>,\n  value: T,\n): void {\n  const existingStore = storage.getStore();\n  if (existingStore) {\n    existingStore.value = value;\n    return;\n  }\n\n  const boxedValue = { value };\n  try {\n    storage.enterWith(boxedValue);\n  } catch {\n    // Cloudflare Workers define enterWith but throw at runtime\n    storage.run(boxedValue, () => {});\n  }\n}\n\n/**\n * Try to keep OpenTelemetry's context manager in sync with baggage updates\n */\ntype ContextManagerLike = {\n  with?: (ctx: Context, fn: () => void) => void;\n  _asyncLocalStorage?: { enterWith?: (ctx: Context) => void };\n};\n\nfunction updateActiveContext(newContext: Context): void {\n  // Update our storage first so any helper reads see the new context\n  enterOrRun(contextStorage, newContext);\n\n  const contextWithManager = context as unknown as {\n    _getContextManager?: () => ContextManagerLike;\n  };\n\n  const manager = contextWithManager._getContextManager?.();\n  if (!manager) return;\n\n  const asyncLocal =\n    (manager as { _asyncLocalStorage?: { enterWith?: (ctx: Context) => void } })\n      ._asyncLocalStorage ?? undefined;\n  if (asyncLocal?.enterWith) {\n    asyncLocal.enterWith(newContext);\n    return;\n  }\n\n  if (typeof manager.with === 'function') {\n    manager.with(newContext, () => {});\n  }\n}\n\n/**\n * Base trace context containing trace identifiers\n */\nexport interface TraceContextBase {\n  traceId: string;\n  spanId: string;\n  correlationId: string;\n}\n\n/**\n * Attribute value types following OpenTelemetry specification.\n * Supports primitive values and arrays of homogeneous primitives.\n */\nexport type AttributeValue =\n  | string\n  | number\n  | boolean\n  | string[]\n  | number[]\n  | boolean[];\n\n/**\n * Span methods available on trace context\n */\nexport interface SpanMethods {\n  /** Set a single attribute on the span */\n  setAttribute(key: string, value: AttributeValue): void;\n  /** Set multiple attributes on the span */\n  setAttributes(attrs: Record<string, AttributeValue>): void;\n  /** Set the status of the span */\n  setStatus(status: { code: SpanStatusCode; message?: string }): void;\n  /** Add a link to another span */\n  addLink(link: Link): void;\n  /** Add multiple links to other spans */\n  addLinks(links: Link[]): void;\n  /** Update the span name dynamically */\n  updateName(name: string): void;\n  /** Check if the span is recording */\n  isRecording(): boolean;\n  /**\n   * Record an error on the span: sets ERROR status, structured `error.*`\n   * attributes (including `why`/`fix`/`link` from `createStructuredError`),\n   * and during the OTel Span Event API back-compat window also records the\n   * exception via the legacy span event API.\n   *\n   * Replaces the deprecated `recordException` (OTEP 4430). Accepts `unknown`\n   * so it can be called directly with the value caught from a `catch` block.\n   */\n  recordError(error: unknown): void;\n  /**\n   * Emit a tracked event correlated to this span. Equivalent to the standalone\n   * `track(event, data)` but reads naturally on `ctx`. Replaces the deprecated\n   * `ctx.addEvent` (OTEP 4430) — events become correlated logs rather than\n   * span events.\n   */\n  track<Events extends Record<string, unknown> = Record<string, unknown>>(\n    event: keyof Events & string,\n    data?: Events[keyof Events & string],\n  ): void;\n}\n\n/**\n * Baggage methods available on trace context\n *\n * @template TBaggage - Optional type for typed baggage (defaults to undefined for untyped)\n */\nexport interface BaggageMethods<\n  TBaggage extends Record<string, unknown> | undefined = undefined,\n> {\n  /**\n   * Get a baggage entry by key\n   * @param key - Baggage key\n   * @returns Baggage entry value or undefined\n   */\n  getBaggage(key: string): string | undefined;\n\n  /**\n   * Set a baggage entry\n   *\n   * Note: OpenTelemetry contexts are immutable. For proper scoping across async\n   * boundaries, use withBaggage() instead. This method updates baggage in the\n   * current context which may not propagate to all child operations.\n   *\n   * @param key - Baggage key\n   * @param value - Baggage value\n   * @returns The baggage value that was set (for chaining)\n   *\n   * @example Using withBaggage() (recommended)\n   * ```typescript\n   * await withBaggage({ baggage: { 'key': 'value' }, fn: async () => {\n   *   // Baggage is available here and in child spans\n   * });\n   * ```\n   */\n  setBaggage(key: string, value: string): string;\n\n  /**\n   * Delete a baggage entry\n   *\n   * Note: OpenTelemetry contexts are immutable. For proper scoping across async\n   * boundaries, use withBaggage() with only the entries you want instead.\n   *\n   * @param key - Baggage key\n   */\n  deleteBaggage(key: string): void;\n\n  /**\n   * Get all baggage entries\n   * @returns Map of all baggage entries\n   */\n  getAllBaggage(): Map<string, BaggageEntry>;\n\n  /**\n   * Get typed baggage (only available when TBaggage is defined)\n   * This is used internally by defineBaggageSchema()\n   *\n   * @internal\n   */\n  getTypedBaggage?: TBaggage extends Record<string, unknown>\n    ? <T extends TBaggage>(namespace?: string) => Partial<T> | undefined\n    : never;\n\n  /**\n   * Set typed baggage (only available when TBaggage is defined)\n   * This is used internally by defineBaggageSchema()\n   *\n   * @internal\n   */\n  setTypedBaggage?: TBaggage extends Record<string, unknown>\n    ? <T extends TBaggage>(\n        namespace: string | undefined,\n        value: Partial<T>,\n      ) => void\n    : never;\n}\n\n/**\n * Complete trace context that merges base context, span methods, and baggage methods\n *\n * This is the ctx parameter passed to factory functions in trace().\n * It provides access to trace IDs, span manipulation methods, and baggage operations.\n *\n * @template TBaggage - Optional type for typed baggage support\n *\n * @example Untyped (default)\n * ```typescript\n * export const handler = trace((ctx) => async () => {\n *   ctx.getBaggage('key'); // returns string | undefined\n * });\n * ```\n *\n * @example Typed baggage\n * ```typescript\n * type TenantBaggage = { tenantId: string; region?: string };\n *\n * export const handler = trace<TenantBaggage>((ctx) => async () => {\n *   // Use typed schema helper for type-safe access\n *   const schema = defineBaggageSchema<TenantBaggage>('tenant');\n *   const tenant = schema.get(ctx); // Partial<TenantBaggage> | undefined\n * });\n * ```\n */\nexport type TraceContext<\n  TBaggage extends Record<string, unknown> | undefined = undefined,\n> = TraceContextBase & SpanMethods & BaggageMethods<TBaggage>;\n\n/**\n * Create a TraceContext from an OpenTelemetry Span\n *\n * This utility extracts trace context information from a span\n * and provides span manipulation methods and baggage operations in a consistent format.\n *\n * Note: Baggage methods always operate on the currently active context,\n * which may differ from the context when createTraceContext was called.\n */\nexport function createTraceContext<\n  TBaggage extends Record<string, unknown> | undefined = undefined,\n>(span: Span): TraceContext<TBaggage> {\n  const spanContext = span.spanContext();\n\n  // Store the current active context in AsyncLocalStorage so baggage setters can update it\n  // This ensures ctx.setBaggage() changes persist and are visible to OpenTelemetry operations\n  // IMPORTANT: Only initialize if not already set (preserve baggage updates from parent spans)\n  const existingStored = contextStorage.getStore()?.value;\n  if (!existingStored) {\n    const activeContext = context.active();\n    enterOrRun(contextStorage, activeContext);\n  }\n\n  // Baggage helpers that always use the current active context\n  // This ensures baggage operations work correctly even if context changes\n  const baggageHelpers: BaggageMethods<TBaggage> = {\n    getBaggage(key: string): string | undefined {\n      // Check active context first (from withBaggage, context.with, etc.)\n      // Then check stored context (from setters)\n      // This ensures both withBaggage() and ctx.setBaggage() work correctly\n      const activeCtx = context.active();\n      let baggage = propagation.getBaggage(activeCtx);\n      if (!baggage) {\n        const storedContext = contextStorage.getStore()?.value;\n        if (storedContext) {\n          baggage = propagation.getBaggage(storedContext);\n        }\n      }\n      return baggage?.getEntry(key)?.value;\n    },\n\n    setBaggage(key: string, value: string): string {\n      // OpenTelemetry contexts are immutable, so we create a new context with updated baggage\n      // Check active context first (may have baggage from withBaggage), then stored context\n      const activeCtx = context.active();\n      const storedContext = contextStorage.getStore()?.value;\n      const currentContext = storedContext ?? activeCtx;\n      const baggage =\n        propagation.getBaggage(currentContext) ?? propagation.createBaggage();\n      const updated = baggage.setEntry(key, { value });\n      const newContext = propagation.setBaggage(currentContext, updated);\n\n      updateActiveContext(newContext);\n\n      return value;\n    },\n\n    deleteBaggage(key: string): void {\n      // Check active context first, then stored context\n      const activeCtx = context.active();\n      const storedContext = contextStorage.getStore()?.value;\n      const currentContext = storedContext ?? activeCtx;\n      const baggage = propagation.getBaggage(currentContext);\n      if (baggage) {\n        const updated = baggage.removeEntry(key);\n        const newContext = propagation.setBaggage(currentContext, updated);\n\n        updateActiveContext(newContext);\n      }\n    },\n\n    getAllBaggage(): Map<string, BaggageEntry> {\n      // Check active context first, then stored context\n      const activeCtx = context.active();\n      let baggage = propagation.getBaggage(activeCtx);\n      if (!baggage) {\n        const storedContext = contextStorage.getStore()?.value;\n        if (storedContext) {\n          baggage = propagation.getBaggage(storedContext);\n        }\n      }\n      if (!baggage) {\n        return new Map();\n      }\n\n      // Convert baggage entries to a Map\n      const entries = new Map<string, BaggageEntry>();\n      for (const [key, entry] of baggage.getAllEntries()) {\n        entries.set(key, entry);\n      }\n      return entries;\n    },\n\n    // Typed baggage helpers (used by defineBaggageSchema)\n    getTypedBaggage: (<T extends Record<string, unknown>>(\n      namespace?: string,\n    ) => {\n      // Check active context first, then stored context\n      const activeCtx = context.active();\n      let baggage = propagation.getBaggage(activeCtx);\n      if (!baggage) {\n        const storedContext = contextStorage.getStore()?.value;\n        if (storedContext) {\n          baggage = propagation.getBaggage(storedContext);\n        }\n      }\n      if (!baggage) return;\n\n      const prefix = namespace ? `${namespace}.` : '';\n      const result: Record<string, unknown> = {};\n\n      for (const [key, entry] of baggage.getAllEntries()) {\n        if (namespace && key.startsWith(prefix)) {\n          const fieldName = key.slice(prefix.length);\n          result[fieldName] = entry.value;\n        } else if (!namespace) {\n          result[key] = entry.value;\n        }\n      }\n\n      return Object.keys(result).length > 0\n        ? (result as Partial<T>)\n        : undefined;\n    }) as TBaggage extends Record<string, unknown>\n      ? <T extends TBaggage>(namespace?: string) => Partial<T> | undefined\n      : never,\n\n    setTypedBaggage: (<T extends Record<string, unknown>>(\n      namespace: string | undefined,\n      value: Partial<T>,\n    ) => {\n      // Check active context first, then stored context\n      const activeCtx = context.active();\n      const storedContext = contextStorage.getStore()?.value;\n      const currentContext = storedContext ?? activeCtx;\n      let baggage =\n        propagation.getBaggage(currentContext) ?? propagation.createBaggage();\n\n      const prefix = namespace ? `${namespace}.` : '';\n      for (const [key, val] of Object.entries(value)) {\n        if (val !== undefined) {\n          const baggageKey = `${prefix}${key}`;\n          baggage = baggage.setEntry(baggageKey, { value: String(val) });\n        }\n      }\n\n      const newContext = propagation.setBaggage(currentContext, baggage);\n      updateActiveContext(newContext);\n    }) as TBaggage extends Record<string, unknown>\n      ? <T extends TBaggage>(\n          namespace: string | undefined,\n          value: Partial<T>,\n        ) => void\n      : never,\n  };\n\n  // `recordException` and `addEvent` are intentionally bound at runtime but\n  // omitted from the `SpanMethods` type. They exist solely so existing call\n  // sites keep working through the OTel Span Event API deprecation window\n  // (see MIGRATION.md). New code MUST go through `recordStructuredError`,\n  // `emitCorrelatedEvent`, or the request logger. The cast below is what hides\n  // these compatibility-only fields from the public type.\n  const traceCtx = {\n    traceId: spanContext.traceId,\n    spanId: spanContext.spanId,\n    correlationId: spanContext.traceId.slice(0, 16),\n    setAttribute: span.setAttribute.bind(span),\n    setAttributes: span.setAttributes.bind(span),\n    setStatus: span.setStatus.bind(span),\n    recordException: span.recordException.bind(span),\n    addEvent: span.addEvent.bind(span),\n    addLink: span.addLink.bind(span),\n    addLinks: span.addLinks.bind(span),\n    updateName: span.updateName.bind(span),\n    isRecording: span.isRecording.bind(span),\n    recordError: (error: unknown) => {\n      const err = error instanceof Error ? error : new Error(String(error));\n      recordStructuredError(traceCtx, err);\n    },\n    track: (event: string, data?: Record<string, unknown>) => {\n      track(event, data);\n    },\n    ...baggageHelpers,\n  } as unknown as TraceContext<TBaggage>;\n\n  return traceCtx;\n}\n\n/**\n * Define a typed baggage schema for type-safe baggage operations\n *\n * This helper provides a type-safe API for working with baggage entries.\n * The namespace parameter is optional and prefixes all keys to avoid collisions.\n *\n * @template T - The baggage schema type (all fields are treated as optional)\n * @param namespace - Optional namespace to prefix baggage keys\n *\n * @example Basic usage\n * ```typescript\n * type TenantBaggage = { tenantId: string; region?: string };\n * const tenantBaggage = defineBaggageSchema<TenantBaggage>('tenant');\n *\n * export const handler = trace<TenantBaggage>((ctx) => async () => {\n *   // Get typed baggage\n *   const tenant = tenantBaggage.get(ctx);\n *   if (tenant?.tenantId) {\n *     console.log('Tenant:', tenant.tenantId);\n *   }\n *\n *   // Set typed baggage\n *   tenantBaggage.set(ctx, { tenantId: 't1', region: 'us-east-1' });\n * });\n * ```\n *\n * @example With withBaggage helper\n * ```typescript\n * const tenantBaggage = defineBaggageSchema<TenantBaggage>('tenant');\n *\n * export const handler = trace<TenantBaggage>((ctx) => async () => {\n *   return await tenantBaggage.with(ctx, { tenantId: 't1' }, async () => {\n *     // Baggage is available here and in child spans\n *     const tenant = tenantBaggage.get(ctx);\n *   });\n * });\n * ```\n */\nexport function defineBaggageSchema<T extends Record<string, unknown>>(\n  namespace?: string,\n) {\n  return {\n    /**\n     * Get typed baggage from context\n     * @param ctx - Trace context\n     * @returns Partial baggage object or undefined if no baggage is set\n     */\n    get: (ctx: TraceContext<T>): Partial<T> | undefined => {\n      if (!ctx.getTypedBaggage) return undefined;\n      return ctx.getTypedBaggage<T>(namespace);\n    },\n\n    /**\n     * Set typed baggage in context\n     *\n     * Note: For proper scoping across async boundaries, use the `with` method instead\n     *\n     * @param ctx - Trace context\n     * @param value - Partial baggage object to set\n     */\n    set: (ctx: TraceContext<T>, value: Partial<T>): void => {\n      if (!ctx.setTypedBaggage) return;\n      ctx.setTypedBaggage<T>(namespace, value);\n    },\n\n    /**\n     * Run a function with typed baggage properly scoped\n     *\n     * This is the recommended way to set baggage as it ensures proper\n     * scoping across async boundaries.\n     *\n     * @param ctx - Trace context (can be omitted, will use active context)\n     * @param value - Partial baggage object to set\n     * @param fn - Function to execute with the baggage\n     */\n    with: <R>(\n      ctxOrValue: TraceContext<T> | Partial<T>,\n      valueOrFn: Partial<T> | (() => R | Promise<R>),\n      maybeFn?: () => R | Promise<R>,\n    ): R | Promise<R> => {\n      // Support both with(ctx, value, fn) and with(value, fn)\n      const value = maybeFn\n        ? (valueOrFn as Partial<T>)\n        : (ctxOrValue as Partial<T>);\n      const fn = maybeFn || (valueOrFn as () => R | Promise<R>);\n\n      // Serialize typed baggage to flat key-value pairs\n      const prefix = namespace ? `${namespace}.` : '';\n      const flatBaggage: Record<string, string> = {};\n      for (const [key, val] of Object.entries(value)) {\n        if (val !== undefined) {\n          flatBaggage[`${prefix}${key}`] = String(val);\n        }\n      }\n\n      // Use the existing withBaggage helper\n      const currentContext = context.active();\n      let baggage =\n        propagation.getBaggage(currentContext) ?? propagation.createBaggage();\n\n      for (const [key, val] of Object.entries(flatBaggage)) {\n        baggage = baggage.setEntry(key, { value: val });\n      }\n\n      const newContext = propagation.setBaggage(currentContext, baggage);\n      return context.with(newContext, fn);\n    },\n  };\n}\n","/**\n * Correlation ID utilities for event-driven observability\n *\n * Provides a stable join key across events, logs, and spans even when traces fragment.\n * Format: 16 hex chars (64 bits), crypto-random, URL-safe.\n *\n * Lifecycle:\n * 1. Generated at boundary root (HTTP server span, message process span, cron job span)\n * 2. Reused within context (nested work shares it via AsyncLocalStorage)\n * 3. Propagated via baggage (optional, default OFF to avoid header bloat)\n *\n * @example Basic usage\n * ```typescript\n * import { generateCorrelationId, getCorrelationId } from 'autotel/correlation-id';\n *\n * // Generate a new correlation ID\n * const id = generateCorrelationId();\n * // Returns: 'a1b2c3d4e5f67890'\n *\n * // Get current correlation ID from context\n * const currentId = getCorrelationId();\n * ```\n */\n\nimport { trace, propagation, context } from '@opentelemetry/api';\n// namespace import for browser-bundler compat; `import type` is erased — see node-require.ts\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport * as nodeAsyncHooks from 'node:async_hooks';\nimport { enterOrRun } from './trace-context';\n\ntype CorrelationStore = {\n  value: string;\n};\n\n/**\n * AsyncLocalStorage for storing correlation ID\n * This allows correlation IDs to persist across async boundaries\n */\nconst correlationStorage =\n  new nodeAsyncHooks.AsyncLocalStorage<CorrelationStore>();\n\n/**\n * Baggage key for correlation ID propagation\n */\nexport const CORRELATION_ID_BAGGAGE_KEY = 'autotel.correlation_id';\n\n/**\n * Generate a new correlation ID\n *\n * Format: 16 hex chars (64 bits), crypto-random, URL-safe\n *\n * @returns A new correlation ID\n *\n * @example\n * ```typescript\n * const id = generateCorrelationId();\n * // Returns: 'a1b2c3d4e5f67890'\n * ```\n */\nexport function generateCorrelationId(): string {\n  // Use crypto.getRandomValues for secure random bytes\n  const bytes = new Uint8Array(8); // 64 bits\n  crypto.getRandomValues(bytes);\n\n  // Convert to hex string\n  return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Get the current correlation ID from context\n *\n * Resolution order:\n * 1. AsyncLocalStorage (from explicit setCorrelationId or runWithCorrelationId)\n * 2. Baggage (if propagated from upstream)\n * 3. Active span's trace ID (first 16 chars as fallback)\n * 4. undefined (if not in any context)\n *\n * @returns Current correlation ID or undefined\n *\n * @example\n * ```typescript\n * const id = getCorrelationId();\n * if (id) {\n *   console.log('Correlation ID:', id);\n * }\n * ```\n */\nexport function getCorrelationId(): string | undefined {\n  // 1. Check AsyncLocalStorage first (explicit correlation ID)\n  const storedId = correlationStorage.getStore()?.value;\n  if (storedId) {\n    return storedId;\n  }\n\n  // 2. Check baggage (propagated from upstream)\n  const activeContext = context.active();\n  const baggage = propagation.getBaggage(activeContext);\n  const baggageEntry = baggage?.getEntry(CORRELATION_ID_BAGGAGE_KEY);\n  if (baggageEntry?.value) {\n    return baggageEntry.value;\n  }\n\n  // 3. Fall back to active span's trace ID (first 16 chars)\n  const span = trace.getActiveSpan();\n  if (span) {\n    const spanContext = span.spanContext();\n    return spanContext.traceId.slice(0, 16);\n  }\n\n  // 4. No context available\n  return undefined;\n}\n\n/**\n * Get or create a correlation ID\n *\n * If a correlation ID exists in the current context, returns it.\n * Otherwise, generates a new one.\n *\n * @returns Existing or new correlation ID\n *\n * @example\n * ```typescript\n * const id = getOrCreateCorrelationId();\n * // Always returns a valid correlation ID\n * ```\n */\nexport function getOrCreateCorrelationId(): string {\n  return getCorrelationId() ?? generateCorrelationId();\n}\n\n/**\n * Run a function with a specific correlation ID in context\n *\n * The correlation ID will be available via getCorrelationId() throughout\n * the execution of the function and any async operations it spawns.\n *\n * @param correlationId - Correlation ID to use\n * @param fn - Function to execute\n * @returns The return value of the function\n *\n * @example\n * ```typescript\n * await runWithCorrelationId('abc123', async () => {\n *   // getCorrelationId() returns 'abc123' here\n *   await processRequest();\n * });\n * ```\n */\nexport function runWithCorrelationId<T>(correlationId: string, fn: () => T): T {\n  return correlationStorage.run({ value: correlationId }, fn);\n}\n\n/**\n * Set correlation ID in the current context (mutates context)\n *\n * Note: This updates the AsyncLocalStorage context. For proper scoping\n * across async boundaries, prefer runWithCorrelationId() instead.\n *\n * @param correlationId - Correlation ID to set\n *\n * @example\n * ```typescript\n * setCorrelationId('abc123');\n * // Now getCorrelationId() returns 'abc123'\n * ```\n */\nexport function setCorrelationId(correlationId: string): void {\n  enterOrRun(correlationStorage, correlationId);\n}\n\n/**\n * Set correlation ID in baggage for propagation\n *\n * This adds the correlation ID to the W3C baggage header, allowing it\n * to be propagated to downstream services.\n *\n * Note: Only use this when you explicitly want cross-service propagation.\n * Default is OFF to avoid header bloat.\n *\n * @param correlationId - Correlation ID to propagate\n * @returns New context with baggage set\n *\n * @example\n * ```typescript\n * const newContext = setCorrelationIdInBaggage('abc123');\n * context.with(newContext, () => {\n *   // Baggage will be propagated in outgoing requests\n * });\n * ```\n */\nexport function setCorrelationIdInBaggage(\n  correlationId: string,\n): import('@opentelemetry/api').Context {\n  const activeContext = context.active();\n  let baggage =\n    propagation.getBaggage(activeContext) ?? propagation.createBaggage();\n  baggage = baggage.setEntry(CORRELATION_ID_BAGGAGE_KEY, {\n    value: correlationId,\n  });\n  return propagation.setBaggage(activeContext, baggage);\n}\n\n/**\n * Get the correlation storage instance (for internal use in init/shutdown)\n */\nexport function getCorrelationStorage(): AsyncLocalStorage<CorrelationStore> {\n  return correlationStorage;\n}\n","/**\n * Events event queue with batching, backpressure, retry logic, rate limiting, and OTel metrics\n *\n * Exposes delivery pipeline metrics for observability:\n * - autotel.event_delivery.queue.size - Current queue size\n * - autotel.event_delivery.queue.oldest_age_ms - Age of oldest event in queue\n * - autotel.event_delivery.queue.delivered - Successfully delivered events\n * - autotel.event_delivery.queue.failed - Failed event deliveries\n * - autotel.event_delivery.queue.dropped - Dropped events with reason\n * - autotel.event_delivery.queue.latency_ms - Delivery latency histogram\n * - autotel.event_delivery.subscriber.health - Subscriber health (1=healthy, 0=unhealthy)\n */\n\nimport type {\n  Counter,\n  Histogram,\n  ObservableGauge,\n  Attributes,\n} from '@opentelemetry/api';\nimport type { ObservableResult } from '@opentelemetry/api';\nimport type {\n  EventSubscriber,\n  EventAttributes,\n  AutotelEventContext,\n  EventSchemaMetadata,\n} from './event-subscriber';\nimport { getLogger } from './init';\nimport { getConfig as getRuntimeConfig } from './config';\nimport { TokenBucketRateLimiter, type RateLimiterConfig } from './rate-limiter';\nimport { getOrCreateCorrelationId } from './correlation-id';\n\nexport interface EventData {\n  name: string;\n  attributes?: EventAttributes;\n  timestamp: number;\n  /** Internal: correlation ID for debug breadcrumbs */\n  _correlationId?: string;\n  /** Internal: trace ID for debug breadcrumbs */\n  _traceId?: string;\n  /** Autotel context for trace correlation (passed to subscribers) */\n  autotel?: AutotelEventContext;\n  /** Optional schema metadata for contract-aware subscribers. */\n  schema?: EventSchemaMetadata;\n}\n\n/**\n * Drop reasons for event delivery queue metrics\n * LOW CARDINALITY: Only these 4 values allowed in metric labels\n */\nexport type EventDropReason =\n  | 'rate_limit'\n  | 'circuit_open'\n  | 'payload_invalid'\n  | 'shutdown';\n\nexport interface QueueConfig {\n  maxSize: number; // Max events in queue (default: 50,000)\n  batchSize: number; // Events per batch (default: 100)\n  flushInterval: number; // Flush interval in ms (default: 10,000)\n  maxRetries: number; // Max retry attempts (default: 3)\n  rateLimit?: RateLimiterConfig; // Optional rate limiting (default: 100 events/sec)\n}\n\nconst DEFAULT_CONFIG: QueueConfig = {\n  maxSize: 50_000,\n  batchSize: 100,\n  flushInterval: 10_000,\n  maxRetries: 3,\n  rateLimit: {\n    maxEventsPerSecond: 100,\n    burstCapacity: 200,\n  },\n};\n\n/**\n * Metrics for event delivery queue observability\n *\n * All metrics use low-cardinality labels only:\n * - subscriber: stable identifier (e.g., 'posthog', 'mixpanel')\n * - reason: one of EventDropReason values\n */\ninterface EventQueueMetrics {\n  /** Current queue size (observable gauge) */\n  queueSize: ObservableGauge;\n  /** Age of oldest event in queue in ms (observable gauge) */\n  oldestAge: ObservableGauge;\n  /** Successfully delivered events (counter) */\n  delivered: Counter;\n  /** Failed event deliveries after all retries (counter) */\n  failed: Counter;\n  /** Dropped events (counter with reason label) */\n  dropped: Counter;\n  /** Event delivery latency histogram in ms */\n  latency: Histogram;\n  /** Subscriber health: 1=healthy, 0=unhealthy (observable gauge) */\n  subscriberHealth: ObservableGauge;\n}\n\n/**\n * Get subscriber name for metrics (stable, low-cardinality)\n *\n * Priority:\n * 1. Explicit config: subscriber.name\n * 2. Class static property (if available)\n * 3. Fallback: lowercase class name without \"Subscriber\" suffix\n */\nfunction getSubscriberName(subscriber: EventSubscriber): string {\n  // Use explicit name if provided\n  if (subscriber.name) {\n    return subscriber.name.toLowerCase();\n  }\n\n  // Fallback: derive from class name\n  const className = subscriber.constructor?.name || 'unknown';\n  return className.replace(/Subscriber$/i, '').toLowerCase();\n}\n\n/**\n * Events queue with batching and backpressure\n *\n * Features:\n * - Batches events for efficient sending\n * - Bounded queue with drop-oldest policy (prod) or blocking (dev)\n * - Exponential backoff retry\n * - Rate limiting to prevent overwhelming subscribers\n * - Graceful flush on shutdown\n */\nexport class EventQueue {\n  private queue: EventData[] = [];\n  private flushTimer: NodeJS.Timeout | null = null;\n  private readonly config: QueueConfig;\n  private readonly subscribers: EventSubscriber[];\n  private readonly rateLimiter: TokenBucketRateLimiter | null;\n  private flushPromise: Promise<void> | null = null;\n  private isShuttingDown = false;\n\n  // Metrics\n  private metrics: EventQueueMetrics | null = null;\n\n  // Observable callback cleanup functions\n  private observableCleanups: Array<() => void> = [];\n\n  // Subscriber health tracking (for observable gauges)\n  private subscriberHealthy: Map<string, boolean> = new Map();\n\n  constructor(subscribers: EventSubscriber[], config?: Partial<QueueConfig>) {\n    this.subscribers = subscribers;\n    this.config = { ...DEFAULT_CONFIG, ...config };\n\n    // Initialize rate limiter if configured\n    this.rateLimiter = this.config.rateLimit\n      ? new TokenBucketRateLimiter(this.config.rateLimit)\n      : null;\n\n    // Initialize subscriber health tracking\n    for (const subscriber of subscribers) {\n      const name = getSubscriberName(subscriber);\n      this.subscriberHealthy.set(name, true);\n    }\n\n    // Initialize metrics\n    this.initMetrics();\n  }\n\n  /**\n   * Initialize OTel metrics for queue observability\n   */\n  private initMetrics(): void {\n    const runtimeConfig = getRuntimeConfig();\n    const meter = runtimeConfig.meter;\n\n    // Queue size gauge - observe current queue length\n    const queueSize = meter.createObservableGauge(\n      'autotel.event_delivery.queue.size',\n      {\n        description: 'Current number of events in the delivery queue',\n        unit: 'count',\n      },\n    );\n    const queueSizeCallback = (observableResult: ObservableResult) => {\n      observableResult.observe(this.queue.length);\n    };\n    queueSize.addCallback(queueSizeCallback);\n    this.observableCleanups.push(() =>\n      queueSize.removeCallback(queueSizeCallback),\n    );\n\n    // Oldest event age gauge - observe wait time of oldest event\n    const oldestAge = meter.createObservableGauge(\n      'autotel.event_delivery.queue.oldest_age_ms',\n      {\n        description: 'Age of the oldest event in the queue in milliseconds',\n        unit: 'ms',\n      },\n    );\n    const oldestAgeCallback = (observableResult: ObservableResult) => {\n      if (this.queue.length > 0) {\n        const oldest = this.queue[0]!;\n        const ageMs = Date.now() - oldest.timestamp;\n        observableResult.observe(ageMs);\n      } else {\n        observableResult.observe(0);\n      }\n    };\n    oldestAge.addCallback(oldestAgeCallback);\n    this.observableCleanups.push(() =>\n      oldestAge.removeCallback(oldestAgeCallback),\n    );\n\n    // Delivered counter\n    const delivered = meter.createCounter(\n      'autotel.event_delivery.queue.delivered',\n      {\n        description: 'Number of events successfully delivered to subscribers',\n        unit: 'count',\n      },\n    );\n\n    // Failed counter\n    const failed = meter.createCounter('autotel.event_delivery.queue.failed', {\n      description:\n        'Number of events that failed delivery after all retry attempts',\n      unit: 'count',\n    });\n\n    // Dropped counter (with reason label)\n    const dropped = meter.createCounter(\n      'autotel.event_delivery.queue.dropped',\n      {\n        description: 'Number of events dropped from the queue',\n        unit: 'count',\n      },\n    );\n\n    // Latency histogram\n    const latency = meter.createHistogram(\n      'autotel.event_delivery.queue.latency_ms',\n      {\n        description: 'Event delivery latency from enqueue to successful send',\n        unit: 'ms',\n      },\n    );\n\n    // Subscriber health gauge\n    const subscriberHealth = meter.createObservableGauge(\n      'autotel.event_delivery.subscriber.health',\n      {\n        description: 'Subscriber health status (1=healthy, 0=unhealthy)',\n        unit: '1',\n      },\n    );\n    const subscriberHealthCallback = (observableResult: ObservableResult) => {\n      for (const [subscriberName, isHealthy] of this.subscriberHealthy) {\n        observableResult.observe(isHealthy ? 1 : 0, {\n          subscriber: subscriberName,\n        });\n      }\n    };\n    subscriberHealth.addCallback(subscriberHealthCallback);\n    this.observableCleanups.push(() =>\n      subscriberHealth.removeCallback(subscriberHealthCallback),\n    );\n\n    this.metrics = {\n      queueSize,\n      oldestAge,\n      delivered,\n      failed,\n      dropped,\n      latency,\n      subscriberHealth,\n    };\n  }\n\n  /**\n   * Record a dropped event with reason and emit debug breadcrumb\n   */\n  private recordDropped(\n    reason: EventDropReason,\n    event?: EventData,\n    subscriberName?: string,\n  ): void {\n    // Increment metric\n    const attrs: Attributes = { reason };\n    if (subscriberName) {\n      attrs.subscriber = subscriberName;\n    }\n    this.metrics?.dropped.add(1, attrs);\n\n    // Debug breadcrumb log (rate-limited via existing logger)\n    const logLevel = reason === 'payload_invalid' ? 'error' : 'warn';\n    const logger = getLogger();\n\n    if (logLevel === 'error') {\n      logger.error(\n        {\n          eventName: event?.name,\n          subscriber: subscriberName,\n          reason,\n          correlationId: event?._correlationId,\n          traceId: event?._traceId,\n        },\n        `[autotel] Event dropped: ${reason}`,\n      );\n    } else {\n      logger.warn(\n        {\n          eventName: event?.name,\n          subscriber: subscriberName,\n          reason,\n          correlationId: event?._correlationId,\n          traceId: event?._traceId,\n        },\n        `[autotel] Event dropped: ${reason}`,\n      );\n    }\n  }\n\n  /**\n   * Record permanent delivery failure (after all retries exhausted)\n   * Increments failed counter and logs error\n   */\n  private recordFailed(\n    event: EventData,\n    subscriberName: string,\n    error?: Error,\n  ): void {\n    this.metrics?.failed.add(1, { subscriber: subscriberName });\n\n    // Mark subscriber as unhealthy\n    this.subscriberHealthy.set(subscriberName, false);\n\n    // Debug breadcrumb log\n    getLogger().error(\n      {\n        eventName: event.name,\n        subscriber: subscriberName,\n        correlationId: event._correlationId,\n        traceId: event._traceId,\n        err: error,\n      },\n      `[autotel] Event delivery failed after all retries`,\n    );\n  }\n\n  /**\n   * Mark subscriber as unhealthy on transient failure (without incrementing failed counter)\n   * Used during retry attempts - only recordFailed should increment the counter\n   */\n  private markSubscriberUnhealthy(subscriberName: string): void {\n    this.subscriberHealthy.set(subscriberName, false);\n  }\n\n  /**\n   * Record successful delivery\n   */\n  private recordDelivered(\n    event: EventData,\n    subscriberName: string,\n    startTime: number,\n  ): void {\n    const latencyMs = Date.now() - startTime;\n\n    this.metrics?.delivered.add(1, { subscriber: subscriberName });\n    this.metrics?.latency.record(latencyMs, { subscriber: subscriberName });\n\n    // Mark subscriber as healthy\n    this.subscriberHealthy.set(subscriberName, true);\n  }\n\n  /**\n   * Enqueue an event for sending\n   *\n   * Backpressure policy:\n   * - Drops oldest event and logs warning if queue is full (same behavior in all environments)\n   */\n  enqueue(event: EventData): void {\n    // Reject events during shutdown\n    if (this.isShuttingDown) {\n      this.recordDropped('shutdown', event);\n      return;\n    }\n\n    // Check queue size\n    if (this.queue.length >= this.config.maxSize) {\n      // Drop oldest event and log warning (same behavior in all environments)\n      const droppedEvent = this.queue.shift();\n      this.recordDropped('rate_limit', droppedEvent);\n      getLogger().warn(\n        {\n          droppedEvent: droppedEvent?.name,\n        },\n        `[autotel] Events queue full (${this.config.maxSize} events). ` +\n          'Dropping oldest event. Events are being produced faster than they can be sent. ' +\n          'Check your subscribers or reduce tracking frequency.',\n      );\n    }\n\n    // Enrich event with correlation context for debug breadcrumbs\n    const enrichedEvent: EventData = {\n      ...event,\n      _correlationId: event._correlationId || getOrCreateCorrelationId(),\n    };\n\n    this.queue.push(enrichedEvent);\n    this.scheduleBatchFlush();\n  }\n\n  /**\n   * Schedule a batch flush if not already scheduled\n   */\n  private scheduleBatchFlush(): void {\n    if (this.flushTimer || this.flushPromise) return;\n\n    this.flushTimer = setTimeout(() => {\n      this.flushTimer = null;\n      void this.flushBatch();\n    }, this.config.flushInterval);\n  }\n\n  /**\n   * Flush a batch of events\n   * Uses promise-based concurrency control to prevent race conditions\n   */\n  private async flushBatch(): Promise<void> {\n    if (this.queue.length === 0) return;\n\n    // If already flushing, wait for existing flush\n    if (this.flushPromise) {\n      await this.flushPromise;\n      return;\n    }\n\n    this.flushPromise = this.doFlushBatch();\n\n    try {\n      await this.flushPromise;\n    } finally {\n      this.flushPromise = null;\n\n      // Schedule next flush if more events\n      if (this.queue.length > 0) {\n        this.scheduleBatchFlush();\n      }\n    }\n  }\n\n  /**\n   * Internal flush implementation\n   */\n  private async doFlushBatch(): Promise<void> {\n    const batch = this.queue.splice(0, this.config.batchSize);\n    await this.sendWithRetry(batch, this.config.maxRetries);\n  }\n\n  /**\n   * Send events with exponential backoff retry\n   * Tracks per-event, per-subscriber failures so failed counter reflects actual failed deliveries.\n   * On retry, only failed (event, subscriber) pairs are re-sent to avoid double-counting delivered.\n   */\n  private async sendWithRetry(\n    events: EventData[],\n    retriesLeft: number,\n    subscribersByEventIndex?: Map<number, Set<string>>,\n  ): Promise<void> {\n    const failedDeliveries = await this.sendToSubscribers(\n      events,\n      subscribersByEventIndex,\n    );\n\n    if (failedDeliveries.length > 0) {\n      if (retriesLeft > 0) {\n        // Retry only events that had at least one failure, and only to subscribers that failed (avoid re-sending to healthy subscribers and double-counting delivered)\n        const failedEventIndices = new Set(\n          failedDeliveries.map((f) => f.eventIndex),\n        );\n        const failedEventIndicesOrdered = [...failedEventIndices].sort(\n          (a, b) => a - b,\n        );\n        const eventsToRetry = failedEventIndicesOrdered.map(\n          (i) => events[i],\n        ) as EventData[];\n        const failedSubscribersByRetryIndex = new Map<number, Set<string>>();\n        for (let j = 0; j < failedEventIndicesOrdered.length; j++) {\n          const origIndex = failedEventIndicesOrdered[j];\n          const set = new Set<string>();\n          for (const { eventIndex, subscriberName } of failedDeliveries) {\n            if (eventIndex === origIndex) set.add(subscriberName);\n          }\n          failedSubscribersByRetryIndex.set(j, set);\n        }\n        const delay = Math.pow(2, this.config.maxRetries - retriesLeft) * 1000;\n        await new Promise((resolve) => setTimeout(resolve, delay));\n        return this.sendWithRetry(\n          eventsToRetry,\n          retriesLeft - 1,\n          failedSubscribersByRetryIndex,\n        );\n      } else {\n        // Give up after max retries - record one failure per (event, subscriber) pair\n        for (const { eventIndex, subscriberName, error } of failedDeliveries) {\n          const event = events[eventIndex];\n          if (event) this.recordFailed(event, subscriberName, error);\n        }\n\n        const failedSubscriberNames = [\n          ...new Set(failedDeliveries.map((f) => f.subscriberName)),\n        ];\n        getLogger().error(\n          {\n            failedSubscribers: failedSubscriberNames,\n            retriesAttempted: this.config.maxRetries,\n          },\n          '[autotel] Failed to send events after retries',\n        );\n      }\n    }\n  }\n\n  /**\n   * Send events to configured subscribers with rate limiting and metrics.\n   * When subscribersByEventIndex is provided (retry path), only those subscribers are tried per event.\n   * Returns per-event, per-subscriber failures (empty if all succeeded).\n   */\n  private async sendToSubscribers(\n    events: EventData[],\n    subscribersByEventIndex?: Map<number, Set<string>>,\n  ): Promise<\n    Array<{ eventIndex: number; subscriberName: string; error?: Error }>\n  > {\n    const failedDeliveries: Array<{\n      eventIndex: number;\n      subscriberName: string;\n      error?: Error;\n    }> = [];\n\n    const sendOne = async (event: EventData, eventIndex: number) => {\n      // On retry, only try subscribers that failed for this event (never re-send to healthy subscribers)\n      const subscriberNames = subscribersByEventIndex?.get(eventIndex);\n      const failures = await this.sendEventToSubscribers(\n        event,\n        subscriberNames ?? undefined,\n      );\n      for (const failure of failures) {\n        failedDeliveries.push({\n          eventIndex,\n          subscriberName: failure.subscriberName,\n          error: failure.error,\n        });\n      }\n    };\n\n    if (!this.rateLimiter) {\n      for (let i = 0; i < events.length; i++) {\n        const event = events[i];\n        if (event) await sendOne(event, i);\n      }\n      return failedDeliveries;\n    }\n\n    for (let i = 0; i < events.length; i++) {\n      await this.rateLimiter.waitForToken();\n      const event = events[i];\n      if (event) await sendOne(event, i);\n    }\n\n    return failedDeliveries;\n  }\n\n  /**\n   * Send a single event to subscribers.\n   * - When subscriberNames is undefined (initial attempt): send to all subscribers.\n   * - When subscriberNames is provided (retry): send only to those subscribers (never re-send to healthy ones).\n   * Returns list of subscribers that failed (empty if all succeeded).\n   */\n  private async sendEventToSubscribers(\n    event: EventData,\n    subscriberNames?: Set<string>,\n  ): Promise<Array<{ subscriberName: string; error?: Error }>> {\n    const startTime = event.timestamp;\n    const failures: Array<{ subscriberName: string; error?: Error }> = [];\n\n    const subscribersToTry =\n      subscriberNames === undefined\n        ? this.subscribers\n        : this.subscribers.filter((s) =>\n            subscriberNames.has(getSubscriberName(s)),\n          );\n\n    const results = await Promise.allSettled(\n      subscribersToTry.map(async (subscriber) => {\n        const subscriberName = getSubscriberName(subscriber);\n\n        try {\n          await subscriber.trackEvent(event.name, event.attributes, {\n            autotel: event.autotel,\n            schema: event.schema,\n          });\n          this.recordDelivered(event, subscriberName, startTime);\n          return { subscriberName, success: true };\n        } catch (error) {\n          this.markSubscriberUnhealthy(subscriberName);\n          return {\n            subscriberName,\n            success: false,\n            error: error instanceof Error ? error : undefined,\n          };\n        }\n      }),\n    );\n\n    for (const result of results) {\n      if (result.status === 'fulfilled' && !result.value.success) {\n        failures.push({\n          subscriberName: result.value.subscriberName,\n          error: result.value.error,\n        });\n      }\n    }\n\n    return failures;\n  }\n\n  /**\n   * Flush all remaining events. Queue remains usable after flush (e.g. for\n   * auto-flush at root span end). Use shutdown() when tearing down the queue.\n   */\n  async flush(): Promise<void> {\n    // Cancel any pending timer\n    if (this.flushTimer) {\n      clearTimeout(this.flushTimer);\n      this.flushTimer = null;\n    }\n\n    // Wait for any in-progress flush to complete\n    if (this.flushPromise) {\n      await this.flushPromise;\n    }\n\n    // Flush all remaining batches\n    while (this.queue.length > 0) {\n      await this.doFlushBatch();\n    }\n  }\n\n  /**\n   * Flush remaining events and permanently disable the queue (reject new events).\n   * Use for process/SDK shutdown; use flush() for periodic or span-end drain.\n   */\n  async shutdown(): Promise<void> {\n    this.isShuttingDown = true;\n    await this.flush();\n  }\n\n  /**\n   * Cleanup observable metric callbacks to prevent memory leaks\n   * Call this when destroying the EventQueue instance\n   */\n  cleanup(): void {\n    // Remove all observable callbacks\n    for (const cleanupFn of this.observableCleanups) {\n      try {\n        cleanupFn();\n      } catch {\n        // Ignore cleanup errors\n      }\n    }\n    this.observableCleanups = [];\n  }\n\n  /**\n   * Get queue size (for testing/debugging)\n   */\n  size(): number {\n    return this.queue.length;\n  }\n\n  /**\n   * Get subscriber health status (for testing/debugging)\n   */\n  getSubscriberHealth(): Map<string, boolean> {\n    return new Map(this.subscriberHealthy);\n  }\n\n  /**\n   * Check if a specific subscriber is healthy\n   */\n  isSubscriberHealthy(subscriberName: string): boolean {\n    return this.subscriberHealthy.get(subscriberName.toLowerCase()) ?? true;\n  }\n\n  /**\n   * Manually mark a subscriber as healthy or unhealthy\n   * (used for circuit breaker integration)\n   */\n  setSubscriberHealth(subscriberName: string, healthy: boolean): void {\n    this.subscriberHealthy.set(subscriberName.toLowerCase(), healthy);\n  }\n}\n","/**\n * Input validation for events events and attributes\n *\n * Prevents:\n * - Invalid event names\n * - Oversized payloads\n * - Circular references\n * - Sensitive data leaks\n */\n\nimport type { EventAttributes } from './event-subscriber';\n\nexport interface ValidationConfig {\n  /** Max event name length (default: 100) */\n  maxEventNameLength: number;\n  /** Max attribute key length (default: 100) */\n  maxAttributeKeyLength: number;\n  /** Max attribute value length for strings (default: 1000) */\n  maxAttributeValueLength: number;\n  /** Max total attributes per event (default: 50) */\n  maxAttributeCount: number;\n  /** Max nesting depth for objects (default: 3) */\n  maxNestingDepth: number;\n  /** Sensitive field patterns to redact */\n  sensitivePatterns: RegExp[];\n}\n\nconst DEFAULT_CONFIG: ValidationConfig = {\n  maxEventNameLength: 100,\n  maxAttributeKeyLength: 100,\n  maxAttributeValueLength: 1000,\n  maxAttributeCount: 50,\n  maxNestingDepth: 3,\n  sensitivePatterns: [\n    /password/i,\n    /secret/i,\n    /token/i,\n    /api[_-]?key/i,\n    /access[_-]?key/i,\n    /private[_-]?key/i,\n    /auth/i,\n    /credential/i,\n    /ssn/i,\n    /credit[_-]?card/i,\n  ],\n};\n\nexport class ValidationError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'ValidationError';\n  }\n}\n\n/**\n * Validate and sanitize event name\n * Throws ValidationError if invalid\n */\nexport function validateEventName(\n  eventName: string,\n  config: ValidationConfig = DEFAULT_CONFIG,\n): string {\n  // Check type\n  if (typeof eventName !== 'string') {\n    throw new ValidationError(\n      `Event name must be a string, got ${typeof eventName}`,\n    );\n  }\n\n  // Check non-empty\n  const trimmed = eventName.trim();\n  if (trimmed.length === 0) {\n    throw new ValidationError('Event name cannot be empty');\n  }\n\n  // Check length\n  if (trimmed.length > config.maxEventNameLength) {\n    throw new ValidationError(\n      `Event name too long (${trimmed.length} chars). ` +\n        `Max: ${config.maxEventNameLength}`,\n    );\n  }\n\n  // Check valid characters (alphanumeric, dots, underscores, hyphens)\n  if (!/^[a-zA-Z0-9._-]+$/.test(trimmed)) {\n    throw new ValidationError(\n      `Event name contains invalid characters: \"${trimmed}\". ` +\n        'Use only letters, numbers, dots, underscores, and hyphens.',\n    );\n  }\n\n  return trimmed;\n}\n\n/**\n * Validate and sanitize attributes\n * Returns sanitized attributes (sensitive data redacted)\n */\nexport function validateAttributes(\n  attributes: EventAttributes | undefined,\n  config: ValidationConfig = DEFAULT_CONFIG,\n): EventAttributes | undefined {\n  if (attributes === undefined || attributes === null) {\n    return undefined;\n  }\n\n  // Check type\n  if (typeof attributes !== 'object' || Array.isArray(attributes)) {\n    throw new ValidationError('Attributes must be an object');\n  }\n\n  // Count attributes\n  const keys = Object.keys(attributes);\n  if (keys.length > config.maxAttributeCount) {\n    throw new ValidationError(\n      `Too many attributes (${keys.length}). ` +\n        `Max: ${config.maxAttributeCount}`,\n    );\n  }\n\n  // Validate and sanitize each attribute\n  const sanitized: EventAttributes = {};\n\n  for (const key of keys) {\n    // Validate key\n    if (key.length > config.maxAttributeKeyLength) {\n      throw new ValidationError(\n        `Attribute key too long: \"${key.slice(0, 20)}...\" ` +\n          `(${key.length} chars). Max: ${config.maxAttributeKeyLength}`,\n      );\n    }\n\n    const value = attributes[key];\n\n    // Redact sensitive *strings* only. Numeric/boolean values are not\n    // credentials and replacing them with the literal string '[REDACTED]'\n    // both leaks no useful signal and breaks downstream type expectations\n    // (e.g. an LLM `promptTokens` counter becoming a string poisons every\n    // consumer that treats it as a number).\n    const isSensitive =\n      typeof value === 'string' &&\n      config.sensitivePatterns.some((pattern) => pattern.test(key));\n\n    if (isSensitive) {\n      sanitized[key] = '[REDACTED]';\n      continue;\n    }\n\n    sanitized[key] = sanitizeValue(value, config, 1) as\n      | string\n      | number\n      | boolean;\n  }\n\n  return sanitized;\n}\n\n/**\n * Sanitize attribute value (recursive)\n */\nfunction sanitizeValue(\n  value: unknown,\n  config: ValidationConfig,\n  depth: number,\n): unknown {\n  // Check nesting depth\n  if (depth > config.maxNestingDepth) {\n    return '[MAX_DEPTH_EXCEEDED]';\n  }\n\n  // Handle null/undefined\n  if (value === null || value === undefined) {\n    return value;\n  }\n\n  // Handle primitives\n  if (typeof value === 'string') {\n    if (value.length > config.maxAttributeValueLength) {\n      return value.slice(0, config.maxAttributeValueLength) + '...';\n    }\n    return value;\n  }\n\n  if (typeof value === 'number' || typeof value === 'boolean') {\n    return value;\n  }\n\n  // Handle arrays\n  if (Array.isArray(value)) {\n    return value.map((item) => sanitizeValue(item, config, depth + 1));\n  }\n\n  // Handle objects\n  if (typeof value === 'object') {\n    try {\n      // Check for circular references\n      JSON.stringify(value);\n\n      const sanitized: Record<string, unknown> = {};\n      for (const key in value) {\n        if (Object.prototype.hasOwnProperty.call(value, key)) {\n          const nested = (value as Record<string, unknown>)[key];\n          // See top-level branch above: only string values are redacted.\n          const isSensitive =\n            typeof nested === 'string' &&\n            config.sensitivePatterns.some((pattern) => pattern.test(key));\n\n          sanitized[key] = isSensitive\n            ? '[REDACTED]'\n            : sanitizeValue(nested, config, depth + 1);\n        }\n      }\n      return sanitized;\n    } catch {\n      // Circular reference detected\n      return '[CIRCULAR]';\n    }\n  }\n\n  // Unsupported type (function, symbol, etc.)\n  return `[${typeof value}]`;\n}\n\n/**\n * Validate and sanitize an events event\n * Returns { eventName, attributes } with sanitized values\n */\nexport function validateEvent(\n  eventName: string,\n  attributes?: EventAttributes,\n  config?: Partial<ValidationConfig>,\n): { eventName: string; attributes?: EventAttributes } {\n  const fullConfig = { ...DEFAULT_CONFIG, ...config };\n\n  return {\n    eventName: validateEventName(eventName, fullConfig),\n    attributes: validateAttributes(attributes, fullConfig),\n  };\n}\n\n/**\n * Get default validation config (for testing/customization)\n */\nexport function getDefaultValidationConfig(): ValidationConfig {\n  return { ...DEFAULT_CONFIG };\n}\n","/**\n * Global track() function for business events\n *\n * Simple, no instantiation needed, auto-attaches trace context\n */\n\nimport { trace } from '@opentelemetry/api';\nimport { EventQueue } from './event-queue';\nimport {\n  getConfig,\n  warnIfNotInitialized,\n  isInitialized,\n  getValidationConfig,\n  getEventsConfig,\n} from './init';\nimport { validateEvent } from './validation';\nimport { getOrCreateCorrelationId } from './correlation-id';\nimport type { EventTrackingOptions } from './event-subscriber';\nimport type { AutotelEventContext } from './event-subscriber';\n\n// Global events queue (initialized on first track call)\nlet eventsQueue: EventQueue | null = null;\n\n/**\n * Build autotel event context for trace correlation\n *\n * Works in multiple contexts:\n * 1. Inside a span → use current span's trace_id + span_id\n * 2. Outside span → use correlation_id only\n * 3. With trace URL config → include clickable trace URL\n */\nfunction buildAutotelContext(\n  span: ReturnType<typeof trace.getActiveSpan>,\n): AutotelEventContext | undefined {\n  const eventsConfig = getEventsConfig();\n  const config = getConfig();\n\n  // Always generate a correlation_id\n  const correlationId = getOrCreateCorrelationId();\n\n  // Return minimal context if trace context is not enabled\n  if (!eventsConfig?.includeTraceContext) {\n    return {\n      correlation_id: correlationId,\n    };\n  }\n\n  // Build base context\n  const autotelContext: AutotelEventContext = {\n    correlation_id: correlationId,\n  };\n\n  // Add trace context if inside a span\n  const spanContext = span?.spanContext();\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    // Defensive: serialize() is standard OTel API but may be missing in some runtimes\n    const traceState = spanContext.traceState;\n    if (traceState) {\n      try {\n        if (typeof traceState.serialize === 'function') {\n          const traceStateStr = traceState.serialize();\n          if (traceStateStr) {\n            autotelContext.trace_state = traceStateStr;\n          }\n        }\n      } catch {\n        // Silently ignore serialization errors\n      }\n    }\n\n    // Generate trace URL if configured\n    if (eventsConfig.traceUrl && config) {\n      const traceUrl = eventsConfig.traceUrl({\n        traceId: spanContext.traceId,\n        spanId: spanContext.spanId,\n        correlationId,\n        serviceName: config.service,\n        environment: config.environment,\n      });\n      if (traceUrl) {\n        autotelContext.trace_url = traceUrl;\n      }\n    }\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 * Initialize events queue lazily\n */\nfunction getOrCreateQueue(): EventQueue | null {\n  if (!isInitialized()) {\n    warnIfNotInitialized('track()');\n    return null;\n  }\n\n  if (!eventsQueue) {\n    const config = getConfig();\n    if (!config?.subscribers || config.subscribers.length === 0) {\n      // No subscribers configured - no-op\n      return null;\n    }\n\n    eventsQueue = new EventQueue(config.subscribers);\n  }\n\n  return eventsQueue;\n}\n\n/**\n * Track a business events event\n *\n * Features:\n * - Auto-attaches traceId and spanId if in active span\n * - Batched sending with retry\n * - Type-safe with optional generic\n * - No-op if init() not called or no subscribers configured\n *\n * @example Basic usage\n * ```typescript\n * track('user.signup', { userId: '123', plan: 'pro' })\n * ```\n *\n * @example With type safety\n * ```typescript\n * interface EventDatas {\n *   'user.signup': { userId: string; plan: string }\n *   'plan.upgraded': { userId: string; revenue: number }\n * }\n *\n * track<EventDatas>('user.signup', { userId: '123', plan: 'pro' })\n * ```\n *\n * @example Trace correlation (automatic)\n * ```typescript\n * @Instrumented()\n * class UserService {\n *   async createUser(data: CreateUserData) {\n *     // This track call automatically includes traceId + spanId\n *     track('user.signup', { userId: data.id })\n *   }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function track<Events extends Record<string, any> = Record<string, any>>(\n  event: keyof Events & string,\n  data?: Events[typeof event],\n  options?: EventTrackingOptions,\n): void {\n  const queue = getOrCreateQueue();\n  if (!queue) return; // No-op if not initialized or no subscribers\n\n  // Validate and sanitize input (with custom config if provided)\n  const validationConfig = getValidationConfig();\n  const validated = validateEvent(event, data, validationConfig || undefined);\n\n  // Auto-attach trace context if available (free win!)\n  const span = trace.getActiveSpan();\n  const enrichedData = span\n    ? {\n        ...validated.attributes,\n        traceId: span.spanContext().traceId,\n        spanId: span.spanContext().spanId,\n      }\n    : validated.attributes;\n\n  // Build autotel context (same as Event class)\n  const autotelContext = buildAutotelContext(span);\n\n  queue.enqueue({\n    name: validated.eventName,\n    attributes: enrichedData,\n    timestamp: Date.now(),\n    autotel: autotelContext,\n    schema: options?.schema,\n  });\n}\n\n/**\n * Get events queue (for flush/shutdown)\n * @internal\n */\nexport function getEventQueue(): EventQueue | null {\n  return eventsQueue;\n}\n\n/**\n * Reset events queue (for shutdown/cleanup)\n * @internal\n */\nexport function resetEventQueue(): void {\n  eventsQueue = null;\n}\n"],"mappings":"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"}