@active-reach/web-sdk 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"analytics-6PR9ERDS.mjs","sources":["../src/types/config.ts","../src/utils/uuid.ts","../src/utils/logger.ts","../src/utils/identity.ts","../src/core/session.ts","../src/core/queue.ts","../src/core/transport.ts","../src/utils/storage.ts","../src/utils/url-parser.ts","../src/utils/device.ts","../src/plugins/registry.ts","../src/utils/consent.ts","../src/utils/meta-cookies.ts","../src/ecommerce/index.ts","../src/core/rate-limiter.ts","../src/governance/murmur3.ts","../src/governance/bloom-filter.ts","../src/governance/name-governor.ts","../src/governance/trait-governor.ts","../src/core/analytics.ts"],"sourcesContent":["export type CellRegion = 'us-east' | 'us-west' | 'eu-central' | 'ap-south' | 'ap-southeast';\n\nexport interface CellEndpoint {\n region: CellRegion;\n url: string;\n priority: number;\n healthy: boolean;\n}\n\nexport interface AegisConfig {\n write_key: string;\n\n workspace_id?: string;\n \n api_host?: string;\n \n cell_endpoints?: CellEndpoint[];\n \n preferred_region?: CellRegion;\n \n auto_region_detection?: boolean;\n \n batch_size?: number;\n \n batch_interval?: number;\n \n capture_utm?: boolean;\n \n capture_referrer?: boolean;\n \n auto_page_view?: boolean;\n \n session_timeout?: number;\n \n debug?: boolean;\n \n respect_dnt?: boolean;\n \n cross_domain_tracking?: boolean;\n \n cookie_domain?: string;\n \n secure_cookie?: boolean;\n \n enable_offline_mode?: boolean;\n \n max_offline_events?: number;\n \n retry_failed_requests?: boolean;\n \n max_retries?: number;\n \n retry_backoff_multiplier?: number;\n \n request_timeout?: number;\n\n /** Client-side rate limiter — burst (token bucket capacity). Default 100. */\n rate_limit_burst?: number;\n\n /** Client-side rate limiter — sustained tokens per second. Default 20. */\n rate_limit_per_second?: number;\n\n plugins?: string[];\n\n wait_for_consent?: boolean;\n\n default_consent?: {\n analytics?: boolean;\n marketing?: boolean;\n functional?: boolean;\n };\n\n enable_consent_mode?: boolean;\n\n integrate_onetrust?: boolean;\n\n integrate_cookiebot?: boolean;\n\n integrate_google_consent_mode?: boolean;\n\n /** Push notification configuration. When provided, AegisWebPush is initialized. */\n push?: {\n /** VAPID public key for Web Push subscription. */\n vapidPublicKey: string;\n /** Automatically prompt for push permission after SDK init. Default: false. */\n autoPrompt?: boolean;\n /** Delay in ms before showing auto-prompt. Default: 5000. */\n promptDelay?: number;\n /** Path to the service worker file. Default: '/aegis-sw.js'. */\n serviceWorkerPath?: string;\n /** Scope for the service worker registration. Default: '/'. Critical for e-commerce platforms. */\n serviceWorkerScope?: string;\n };\n}\n\nexport interface AegisConfigInternal extends Required<Omit<AegisConfig, 'api_host' | 'cell_endpoints' | 'preferred_region' | 'cookie_domain' | 'plugins' | 'default_consent' | 'workspace_id'>> {\n initialized: boolean;\n workspace_id: string | null;\n api_host: string | null;\n cell_endpoints: CellEndpoint[];\n preferred_region: CellRegion | null;\n cookie_domain: string | null;\n plugins: string[];\n active_cell: CellEndpoint | null;\n default_consent: {\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n };\n}\n\nexport const DEFAULT_CONFIG: Partial<AegisConfigInternal> = {\n workspace_id: null,\n batch_size: 10,\n batch_interval: 1000,\n capture_utm: true,\n capture_referrer: true,\n auto_page_view: false,\n session_timeout: 30,\n debug: false,\n respect_dnt: true,\n cross_domain_tracking: false,\n secure_cookie: true,\n enable_offline_mode: true,\n max_offline_events: 100,\n retry_failed_requests: true,\n max_retries: 3,\n retry_backoff_multiplier: 2,\n request_timeout: 5000,\n rate_limit_burst: 100,\n rate_limit_per_second: 20,\n auto_region_detection: true,\n wait_for_consent: false,\n enable_consent_mode: false,\n integrate_onetrust: false,\n integrate_cookiebot: false,\n integrate_google_consent_mode: false,\n default_consent: {\n analytics: false,\n marketing: false,\n functional: true,\n },\n initialized: false,\n api_host: null,\n cell_endpoints: [],\n preferred_region: null,\n cookie_domain: null,\n plugins: [],\n active_cell: null,\n};\n","export function generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function generateSessionId(): string {\n return `sess_${Date.now()}_${generateUUID().slice(0, 8)}`;\n}\n\nexport function generateMessageId(): string {\n return `msg_${Date.now()}_${generateUUID().slice(0, 8)}`;\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nclass Logger {\n private enabled: boolean = false;\n private prefix: string = '[Aegis SDK]';\n\n enable(): void {\n this.enabled = true;\n }\n\n disable(): void {\n this.enabled = false;\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n debug(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n console.debug(`${this.prefix} ${message}`, ...args);\n }\n\n info(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n console.info(`${this.prefix} ${message}`, ...args);\n }\n\n warn(message: string, ...args: any[]): void {\n console.warn(`${this.prefix} ${message}`, ...args);\n }\n\n error(message: string, ...args: any[]): void {\n console.error(`${this.prefix} ${message}`, ...args);\n }\n}\n\nexport const logger = new Logger();\n","import { generateUUID } from './uuid';\nimport { Storage } from './storage';\nimport { logger } from './logger';\n\nexport interface IdentityState {\n anonymousId: string;\n userId: string | null;\n traits: Record<string, any>;\n}\n\nexport class Identity {\n private storage: Storage;\n private anonymousId: string;\n private userId: string | null = null;\n private traits: Record<string, any> = {};\n\n constructor(storage: Storage) {\n this.storage = storage;\n this.anonymousId = this.getOrCreateAnonymousId();\n this.loadUserIdentity();\n }\n\n private getOrCreateAnonymousId(): string {\n let id = this.storage.get('anon_id');\n\n if (!id) {\n id = generateUUID();\n this.storage.set('anon_id', id, 365);\n logger.debug('Created new anonymous ID:', id);\n } else {\n logger.debug('Loaded existing anonymous ID:', id);\n }\n\n return id;\n }\n\n private loadUserIdentity(): void {\n const storedUserId = this.storage.get('user_id');\n const storedTraits = this.storage.get('user_traits');\n\n if (storedUserId) {\n this.userId = storedUserId;\n logger.debug('Loaded user ID:', storedUserId);\n }\n\n if (storedTraits) {\n try {\n this.traits = JSON.parse(storedTraits);\n logger.debug('Loaded user traits:', this.traits);\n } catch (error) {\n logger.warn('Failed to parse stored traits:', error);\n this.traits = {};\n }\n }\n }\n\n getAnonymousId(): string {\n return this.anonymousId;\n }\n\n setUserId(userId: string, traits?: Record<string, any>): void {\n this.userId = userId;\n this.storage.set('user_id', userId, 365);\n logger.info('User identified:', userId);\n\n if (traits) {\n this.setTraits(traits);\n }\n }\n\n getUserId(): string | null {\n return this.userId;\n }\n\n setTraits(traits: Record<string, any>): void {\n this.traits = { ...this.traits, ...traits };\n this.storage.set('user_traits', JSON.stringify(this.traits), 365);\n logger.debug('User traits updated:', this.traits);\n }\n\n getTraits(): Record<string, any> {\n return { ...this.traits };\n }\n\n reset(): void {\n this.userId = null;\n this.traits = {};\n this.anonymousId = generateUUID();\n\n this.storage.remove('user_id');\n this.storage.remove('user_traits');\n this.storage.set('anon_id', this.anonymousId, 365);\n\n logger.info('Identity reset, new anonymous ID:', this.anonymousId);\n }\n\n alias(newUserId: string): { previousId: string; newUserId: string } {\n const previousId = this.userId || this.anonymousId;\n\n this.setUserId(newUserId);\n\n logger.info('User aliased:', { previousId, newUserId });\n\n return { previousId, newUserId };\n }\n\n getState(): IdentityState {\n return {\n anonymousId: this.anonymousId,\n userId: this.userId,\n traits: this.getTraits(),\n };\n }\n}\n","import { Storage } from '../utils/storage';\nimport { generateSessionId } from '../utils/uuid';\nimport { logger } from '../utils/logger';\nimport { AdClickIDs } from '../utils/url-parser';\n\nexport interface SessionState {\n sessionId: string;\n startTime: number;\n lastActivityTime: number;\n eventCount: number;\n adClickIDs?: AdClickIDs;\n landingPage?: string;\n}\n\nexport class SessionManager {\n private storage: Storage;\n private sessionId: string;\n private sessionTimeout: number;\n private lastActivityTime: number;\n private sessionStartTime: number;\n private eventCount: number = 0;\n private checkInterval: number | null = null;\n private activityThrottle: number = 1000;\n private lastActivityUpdate: number = 0;\n private adClickIDs: AdClickIDs = {};\n private landingPage?: string;\n\n constructor(storage: Storage, sessionTimeoutMinutes: number = 30) {\n this.storage = storage;\n this.sessionTimeout = sessionTimeoutMinutes * 60 * 1000;\n this.lastActivityTime = Date.now();\n this.sessionStartTime = Date.now();\n\n const session = this.loadSession();\n if (session) {\n this.sessionId = session.sessionId;\n this.sessionStartTime = session.startTime;\n this.lastActivityTime = session.lastActivityTime;\n this.eventCount = session.eventCount;\n this.adClickIDs = session.adClickIDs || {};\n this.landingPage = session.landingPage;\n logger.debug('Session loaded:', session);\n } else {\n this.sessionId = this.createNewSession();\n }\n\n this.startActivityTracking();\n this.startExpiryCheck();\n }\n\n private loadSession(): SessionState | null {\n const sessionData = this.storage.get('session');\n\n if (!sessionData) {\n return null;\n }\n\n try {\n const session: SessionState = JSON.parse(sessionData);\n const elapsed = Date.now() - session.lastActivityTime;\n\n if (elapsed < this.sessionTimeout) {\n return session;\n } else {\n logger.debug('Session expired, creating new session');\n this.storage.remove('session');\n return null;\n }\n } catch (error) {\n logger.warn('Failed to parse session data:', error);\n this.storage.remove('session');\n return null;\n }\n }\n\n private createNewSession(): string {\n const newSessionId = generateSessionId();\n this.sessionStartTime = Date.now();\n this.lastActivityTime = Date.now();\n this.eventCount = 0;\n\n this.persistSession();\n logger.info('New session created:', newSessionId);\n\n return newSessionId;\n }\n\n private persistSession(): void {\n const sessionData: SessionState = {\n sessionId: this.sessionId,\n startTime: this.sessionStartTime,\n lastActivityTime: this.lastActivityTime,\n eventCount: this.eventCount,\n adClickIDs: this.adClickIDs,\n landingPage: this.landingPage,\n };\n\n this.storage.set('session', JSON.stringify(sessionData));\n }\n\n private startActivityTracking(): void {\n const events = ['click', 'scroll', 'keypress', 'mousemove', 'touchstart'];\n\n const activityHandler = () => this.onActivity();\n\n events.forEach((event) => {\n window.addEventListener(event, activityHandler, { passive: true });\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') {\n this.onActivity();\n }\n });\n }\n\n private startExpiryCheck(): void {\n this.checkInterval = window.setInterval(() => {\n this.checkSessionExpiry();\n }, 60000);\n }\n\n private onActivity(): void {\n const now = Date.now();\n const timeSinceLastUpdate = now - this.lastActivityUpdate;\n\n if (timeSinceLastUpdate < this.activityThrottle) {\n return;\n }\n\n this.lastActivityUpdate = now;\n const timeSinceLastActivity = now - this.lastActivityTime;\n\n if (timeSinceLastActivity > this.sessionTimeout) {\n logger.info('Session expired due to inactivity, creating new session');\n this.sessionId = this.createNewSession();\n } else {\n this.lastActivityTime = now;\n this.persistSession();\n }\n }\n\n private checkSessionExpiry(): void {\n const elapsed = Date.now() - this.lastActivityTime;\n\n if (elapsed > this.sessionTimeout) {\n logger.info('Session expired during check, creating new session');\n this.sessionId = this.createNewSession();\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n incrementEventCount(): void {\n this.eventCount++;\n this.lastActivityTime = Date.now();\n this.persistSession();\n }\n\n getSessionDuration(): number {\n return Date.now() - this.sessionStartTime;\n }\n\n getEventCount(): number {\n return this.eventCount;\n }\n\n getState(): SessionState {\n return {\n sessionId: this.sessionId,\n startTime: this.sessionStartTime,\n lastActivityTime: this.lastActivityTime,\n eventCount: this.eventCount,\n adClickIDs: this.adClickIDs,\n landingPage: this.landingPage,\n };\n }\n\n setAdClickIDs(adClickIDs: AdClickIDs, landingPage?: string): void {\n if (Object.keys(adClickIDs).length > 0) {\n this.adClickIDs = { ...this.adClickIDs, ...adClickIDs };\n if (landingPage) {\n this.landingPage = landingPage;\n }\n this.persistSession();\n logger.info('Ad click IDs stored in session:', this.adClickIDs);\n }\n }\n\n getAdClickIDs(): AdClickIDs {\n return this.adClickIDs;\n }\n\n getLandingPage(): string | undefined {\n return this.landingPage;\n }\n\n destroy(): void {\n if (this.checkInterval) {\n clearInterval(this.checkInterval);\n this.checkInterval = null;\n }\n }\n}\n","import { AegisEvent } from '../types/events';\nimport { Transport } from './transport';\nimport { Storage } from '../utils/storage';\nimport { logger } from '../utils/logger';\n\nexport interface QueueConfig {\n batchSize: number;\n batchInterval: number;\n enableOfflineMode: boolean;\n maxOfflineEvents: number;\n}\n\nexport class EventQueue {\n private buffer: AegisEvent[] = [];\n private config: QueueConfig;\n private transport: Transport;\n private storage: Storage;\n private flushInterval: number | null = null;\n private isFlushing: boolean = false;\n private offlineQueue: AegisEvent[] = [];\n private isOnline: boolean = navigator.onLine;\n\n constructor(config: QueueConfig, transport: Transport, storage: Storage) {\n this.config = config;\n this.transport = transport;\n this.storage = storage;\n\n if (config.enableOfflineMode) {\n this.loadOfflineQueue();\n this.setupOnlineListener();\n }\n\n this.startFlushTimer();\n this.setupUnloadHandlers();\n }\n\n private loadOfflineQueue(): void {\n const offlineData = this.storage.get('offline_queue');\n\n if (!offlineData) {\n return;\n }\n\n try {\n const events = JSON.parse(offlineData) as AegisEvent[];\n\n if (Array.isArray(events) && events.length > 0) {\n this.offlineQueue = events.slice(0, this.config.maxOfflineEvents);\n logger.info(`Loaded ${this.offlineQueue.length} offline events`);\n\n if (this.isOnline) {\n this.flushOfflineQueue();\n }\n }\n } catch (error) {\n logger.warn('Failed to load offline queue:', error);\n this.storage.remove('offline_queue');\n }\n }\n\n private saveOfflineQueue(): void {\n if (this.offlineQueue.length === 0) {\n this.storage.remove('offline_queue');\n return;\n }\n\n try {\n const data = JSON.stringify(this.offlineQueue);\n this.storage.set('offline_queue', data);\n logger.debug(`Saved ${this.offlineQueue.length} events to offline queue`);\n } catch (error) {\n logger.warn('Failed to save offline queue:', error);\n }\n }\n\n private setupOnlineListener(): void {\n window.addEventListener('online', () => {\n logger.info('Connection restored');\n this.isOnline = true;\n this.flushOfflineQueue();\n this.flush();\n });\n\n window.addEventListener('offline', () => {\n logger.warn('Connection lost, entering offline mode');\n this.isOnline = false;\n });\n }\n\n private async flushOfflineQueue(): Promise<void> {\n if (this.offlineQueue.length === 0) {\n return;\n }\n\n logger.info(`Flushing ${this.offlineQueue.length} offline events`);\n\n const events = [...this.offlineQueue];\n this.offlineQueue = [];\n this.storage.remove('offline_queue');\n\n const result = await this.transport.send(events);\n\n if (!result.success) {\n logger.warn('Failed to send offline events, re-queueing');\n this.offlineQueue = [...events, ...this.offlineQueue].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n } else {\n logger.info('Offline events sent successfully');\n }\n }\n\n push(event: AegisEvent): void {\n if (!this.isOnline && this.config.enableOfflineMode) {\n this.addToOfflineQueue(event);\n return;\n }\n\n this.buffer.push(event);\n logger.debug('Event queued:', event.type, event);\n\n if (this.buffer.length >= this.config.batchSize) {\n this.flush();\n }\n }\n\n private addToOfflineQueue(event: AegisEvent): void {\n if (this.offlineQueue.length >= this.config.maxOfflineEvents) {\n logger.warn('Offline queue full, dropping oldest event');\n this.offlineQueue.shift();\n }\n\n this.offlineQueue.push(event);\n this.saveOfflineQueue();\n logger.debug('Event added to offline queue');\n }\n\n async flush(): Promise<void> {\n if (this.isFlushing) {\n logger.debug('Flush already in progress, skipping');\n return;\n }\n\n if (this.buffer.length === 0) {\n return;\n }\n\n this.isFlushing = true;\n\n const events = [...this.buffer];\n this.buffer = [];\n\n logger.info(`Flushing ${events.length} events`);\n\n try {\n const result = await this.transport.send(events);\n\n if (!result.success) {\n logger.error('Failed to send events:', result.error);\n\n if (this.config.enableOfflineMode) {\n this.offlineQueue = [...this.offlineQueue, ...events].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n logger.info('Events saved to offline queue');\n } else {\n this.buffer.unshift(...events);\n logger.warn('Events re-queued for retry');\n }\n } else {\n logger.info('Events sent successfully');\n }\n } catch (error) {\n logger.error('Flush error:', error);\n\n if (this.config.enableOfflineMode) {\n this.offlineQueue = [...this.offlineQueue, ...events].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n }\n } finally {\n this.isFlushing = false;\n }\n }\n\n private startFlushTimer(): void {\n if (this.flushInterval) {\n clearInterval(this.flushInterval);\n }\n\n this.flushInterval = window.setInterval(() => {\n this.flush();\n }, this.config.batchInterval);\n\n logger.debug(\n `Flush timer started with interval: ${this.config.batchInterval}ms`\n );\n }\n\n private setupUnloadHandlers(): void {\n const flushBeforeUnload = () => {\n if (this.buffer.length > 0 || this.offlineQueue.length > 0) {\n this.persistBufferToOfflineQueue();\n this.flush();\n }\n };\n\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n flushBeforeUnload();\n }\n });\n\n window.addEventListener('beforeunload', flushBeforeUnload);\n\n window.addEventListener('pagehide', flushBeforeUnload);\n }\n\n private persistBufferToOfflineQueue(): void {\n if (this.buffer.length === 0) {\n return;\n }\n\n if (this.config.enableOfflineMode) {\n this.offlineQueue = [...this.offlineQueue, ...this.buffer].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n logger.debug('Buffer persisted to offline queue before unload');\n }\n }\n\n getQueueSize(): number {\n return this.buffer.length;\n }\n\n getOfflineQueueSize(): number {\n return this.offlineQueue.length;\n }\n\n clear(): void {\n this.buffer = [];\n this.offlineQueue = [];\n this.storage.remove('offline_queue');\n logger.info('Queue cleared');\n }\n\n destroy(): void {\n if (this.flushInterval) {\n clearInterval(this.flushInterval);\n this.flushInterval = null;\n }\n\n this.flush();\n }\n}\n","import { AegisEvent, BatchPayload, BatchResponse } from '../types/events';\nimport { CellEndpoint, CellRegion } from '../types/config';\nimport { logger } from '../utils/logger';\nimport { Storage } from '../utils/storage';\n\nexport interface TransportConfig {\n writeKey: string;\n apiHost: string | null;\n cellEndpoints: CellEndpoint[];\n preferredRegion: CellRegion | null;\n autoRegionDetection: boolean;\n requestTimeout: number;\n retryFailedRequests: boolean;\n maxRetries: number;\n retryBackoffMultiplier: number;\n}\n\nexport interface SendResult {\n success: boolean;\n response?: BatchResponse;\n error?: Error;\n endpoint?: string;\n}\n\nexport class Transport {\n private config: TransportConfig;\n private storage: Storage;\n private activeCell: CellEndpoint | null = null;\n private healthCheckInterval: number | null = null;\n private regionLatencyMap: Map<string, number> = new Map();\n\n constructor(config: TransportConfig, storage: Storage) {\n this.config = config;\n this.storage = storage;\n\n if (config.cellEndpoints.length > 0) {\n this.initializeCellularArchitecture();\n }\n }\n\n private async initializeCellularArchitecture(): Promise<void> {\n const cachedCell = this.loadCachedCell();\n\n if (cachedCell && this.isCellHealthy(cachedCell)) {\n this.activeCell = cachedCell;\n logger.info('Using cached cell:', cachedCell);\n } else {\n await this.selectOptimalCell();\n }\n\n this.startHealthChecks();\n }\n\n private loadCachedCell(): CellEndpoint | null {\n const cached = this.storage.get('active_cell');\n\n if (!cached) {\n return null;\n }\n\n try {\n return JSON.parse(cached) as CellEndpoint;\n } catch (error) {\n logger.warn('Failed to parse cached cell:', error);\n return null;\n }\n }\n\n private saveCachedCell(cell: CellEndpoint): void {\n this.storage.set('active_cell', JSON.stringify(cell), 7);\n }\n\n private isCellHealthy(cell: CellEndpoint): boolean {\n return (\n cell.healthy &&\n this.config.cellEndpoints.some(\n (c) => c.region === cell.region && c.url === cell.url\n )\n );\n }\n\n private async selectOptimalCell(): Promise<void> {\n logger.info('Selecting optimal cell...');\n\n if (this.config.preferredRegion) {\n const preferredCell = this.config.cellEndpoints.find(\n (cell) => cell.region === this.config.preferredRegion && cell.healthy\n );\n\n if (preferredCell) {\n this.activeCell = preferredCell;\n this.saveCachedCell(preferredCell);\n logger.info('Using preferred region cell:', preferredCell);\n return;\n }\n }\n\n if (this.config.autoRegionDetection) {\n await this.detectOptimalRegion();\n } else {\n this.selectCellByPriority();\n }\n }\n\n private async detectOptimalRegion(): Promise<void> {\n const healthyCells = this.config.cellEndpoints.filter((cell) => cell.healthy);\n\n if (healthyCells.length === 0) {\n logger.error('No healthy cells available');\n return;\n }\n\n const latencyPromises = healthyCells.map(async (cell) => {\n const latency = await this.measureLatency(cell);\n this.regionLatencyMap.set(cell.region, latency);\n return { cell, latency };\n });\n\n const results = await Promise.all(latencyPromises);\n results.sort((a, b) => a.latency - b.latency);\n\n const optimalCell = results[0].cell;\n this.activeCell = optimalCell;\n this.saveCachedCell(optimalCell);\n\n logger.info('Optimal cell selected:', {\n region: optimalCell.region,\n latency: results[0].latency,\n });\n }\n\n private async measureLatency(cell: CellEndpoint): Promise<number> {\n const startTime = performance.now();\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 2000);\n\n const response = await fetch(`${cell.url}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n return performance.now() - startTime;\n } else {\n return Infinity;\n }\n } catch (error) {\n logger.warn(`Health check failed for ${cell.region}:`, error);\n return Infinity;\n }\n }\n\n private selectCellByPriority(): void {\n const sortedCells = [...this.config.cellEndpoints]\n .filter((cell) => cell.healthy)\n .sort((a, b) => a.priority - b.priority);\n\n if (sortedCells.length > 0) {\n this.activeCell = sortedCells[0];\n this.saveCachedCell(sortedCells[0]);\n logger.info('Cell selected by priority:', sortedCells[0]);\n } else {\n logger.error('No healthy cells available');\n }\n }\n\n private startHealthChecks(): void {\n this.healthCheckInterval = window.setInterval(() => {\n this.performHealthChecks();\n }, 60000);\n }\n\n private async performHealthChecks(): Promise<void> {\n const healthPromises = this.config.cellEndpoints.map(async (cell) => {\n const isHealthy = await this.checkCellHealth(cell);\n cell.healthy = isHealthy;\n return { cell, isHealthy };\n });\n\n const results = await Promise.all(healthPromises);\n\n if (this.activeCell && !this.activeCell.healthy) {\n logger.warn('Active cell unhealthy, selecting new cell');\n await this.selectOptimalCell();\n }\n\n logger.debug('Health check results:', results);\n }\n\n private async checkCellHealth(cell: CellEndpoint): Promise<boolean> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 3000);\n\n const response = await fetch(`${cell.url}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n return response.ok;\n } catch (error) {\n return false;\n }\n }\n\n async send(events: AegisEvent[]): Promise<SendResult> {\n if (events.length === 0) {\n return { success: true };\n }\n\n const endpoint = this.getActiveEndpoint();\n const payload = this.buildPayload(events);\n\n logger.debug('Sending batch:', { endpoint, eventCount: events.length });\n\n if (document.visibilityState === 'hidden' && typeof navigator.sendBeacon === 'function') {\n const result = this.sendViaBeacon(endpoint, payload);\n return Promise.resolve(result);\n } else {\n return this.sendViaFetch(endpoint, payload);\n }\n }\n\n private getActiveEndpoint(): string {\n if (this.activeCell) {\n return `${this.activeCell.url}/v1/batch`;\n }\n\n if (this.config.apiHost) {\n return `${this.config.apiHost}/v1/batch`;\n }\n\n throw new Error('No active endpoint available');\n }\n\n private buildPayload(events: AegisEvent[]): BatchPayload {\n return {\n batch: events,\n sentAt: new Date().toISOString(),\n writeKey: this.config.writeKey,\n context: this.activeCell\n ? {\n cell: {\n region: this.activeCell.region,\n endpoint: this.activeCell.url,\n },\n }\n : undefined,\n };\n }\n\n private sendViaBeacon(endpoint: string, payload: BatchPayload): SendResult | Promise<SendResult> {\n try {\n const blob = new Blob([JSON.stringify(payload)], {\n type: 'application/json',\n });\n\n const sent = navigator.sendBeacon(endpoint, blob);\n\n if (sent) {\n logger.debug('Batch sent via Beacon');\n return { success: true, endpoint };\n } else {\n logger.warn('Beacon send failed, falling back to fetch');\n return this.sendViaFetch(endpoint, payload);\n }\n } catch (error) {\n logger.error('Beacon send error:', error);\n return {\n success: false,\n error: error as Error,\n endpoint,\n };\n }\n }\n\n private async sendViaFetch(\n endpoint: string,\n payload: BatchPayload,\n attempt: number = 1\n ): Promise<SendResult> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n this.config.requestTimeout\n );\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.writeKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n const result: BatchResponse = await response.json();\n logger.debug('Batch sent successfully:', result);\n return { success: true, response: result, endpoint };\n } else {\n const errorText = await response.text();\n const error = new Error(\n `HTTP ${response.status}: ${errorText || response.statusText}`\n );\n\n logger.error('Batch send failed:', error);\n\n if (this.shouldRetry(response.status, attempt)) {\n return this.retryRequest(endpoint, payload, attempt);\n }\n\n return { success: false, error, endpoint };\n }\n } catch (error) {\n logger.error('Fetch error:', error);\n\n if (this.shouldRetry(0, attempt)) {\n return this.retryRequest(endpoint, payload, attempt);\n }\n\n return {\n success: false,\n error: error as Error,\n endpoint,\n };\n }\n }\n\n private shouldRetry(statusCode: number, attempt: number): boolean {\n if (!this.config.retryFailedRequests) {\n return false;\n }\n\n if (attempt >= this.config.maxRetries) {\n return false;\n }\n\n if (statusCode === 0) {\n return true;\n }\n\n return statusCode >= 500 || statusCode === 429;\n }\n\n private async retryRequest(\n endpoint: string,\n payload: BatchPayload,\n attempt: number\n ): Promise<SendResult> {\n const delay =\n Math.pow(this.config.retryBackoffMultiplier, attempt) * 1000;\n\n logger.info(`Retrying request in ${delay}ms (attempt ${attempt + 1})`);\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return this.sendViaFetch(endpoint, payload, attempt + 1);\n }\n\n getActiveCell(): CellEndpoint | null {\n return this.activeCell;\n }\n\n getRegionLatencies(): Map<string, number> {\n return new Map(this.regionLatencyMap);\n }\n\n destroy(): void {\n if (this.healthCheckInterval) {\n clearInterval(this.healthCheckInterval);\n this.healthCheckInterval = null;\n }\n }\n}\n","const STORAGE_PREFIX = 'aegis_';\n\nexport interface StorageOptions {\n cookieDomain?: string | null;\n secureCookie?: boolean;\n crossDomain?: boolean;\n}\n\nexport class Storage {\n private useLocalStorage: boolean;\n private options: StorageOptions;\n\n constructor(options: StorageOptions = {}) {\n this.options = options;\n this.useLocalStorage = this.isLocalStorageAvailable();\n }\n\n private isLocalStorageAvailable(): boolean {\n try {\n const test = '__aegis_test__';\n localStorage.setItem(test, test);\n localStorage.removeItem(test);\n return true;\n } catch {\n return false;\n }\n }\n\n set(key: string, value: string, expiryDays: number = 365): void {\n const fullKey = STORAGE_PREFIX + key;\n\n if (this.useLocalStorage) {\n try {\n const item = {\n value,\n expiry: Date.now() + expiryDays * 24 * 60 * 60 * 1000,\n };\n localStorage.setItem(fullKey, JSON.stringify(item));\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.setItem failed:', error);\n }\n }\n\n this.setCookie(fullKey, value, expiryDays);\n }\n\n get(key: string): string | null {\n const fullKey = STORAGE_PREFIX + key;\n\n if (this.useLocalStorage) {\n try {\n const itemStr = localStorage.getItem(fullKey);\n if (itemStr) {\n const item = JSON.parse(itemStr);\n if (Date.now() < item.expiry) {\n return item.value;\n } else {\n localStorage.removeItem(fullKey);\n }\n }\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.getItem failed:', error);\n }\n }\n\n return this.getCookie(fullKey);\n }\n\n remove(key: string): void {\n const fullKey = STORAGE_PREFIX + key;\n\n if (this.useLocalStorage) {\n try {\n localStorage.removeItem(fullKey);\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.removeItem failed:', error);\n }\n }\n\n this.deleteCookie(fullKey);\n }\n\n clear(): void {\n if (this.useLocalStorage) {\n try {\n const keys = Object.keys(localStorage);\n keys.forEach((key) => {\n if (key.startsWith(STORAGE_PREFIX)) {\n localStorage.removeItem(key);\n }\n });\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.clear failed:', error);\n }\n }\n\n const cookies = document.cookie.split(';');\n cookies.forEach((cookie) => {\n const key = cookie.split('=')[0].trim();\n if (key.startsWith(STORAGE_PREFIX)) {\n this.deleteCookie(key);\n }\n });\n }\n\n private setCookie(name: string, value: string, days: number): void {\n try {\n const date = new Date();\n date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);\n const expires = `expires=${date.toUTCString()}`;\n \n let cookieStr = `${name}=${value};${expires};path=/`;\n \n if (this.options.secureCookie && window.location.protocol === 'https:') {\n cookieStr += ';Secure';\n }\n \n cookieStr += ';SameSite=Lax';\n \n if (this.options.cookieDomain) {\n cookieStr += `;domain=${this.options.cookieDomain}`;\n } else if (this.options.crossDomain) {\n const domain = this.getRootDomain();\n if (domain) {\n cookieStr += `;domain=${domain}`;\n }\n }\n \n document.cookie = cookieStr;\n } catch (error) {\n console.warn('[Aegis Storage] setCookie failed:', error);\n }\n }\n\n private getCookie(name: string): string | null {\n try {\n const nameEQ = name + '=';\n const ca = document.cookie.split(';');\n \n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1, c.length);\n }\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n } catch (error) {\n console.warn('[Aegis Storage] getCookie failed:', error);\n }\n \n return null;\n }\n\n private deleteCookie(name: string): void {\n try {\n let cookieStr = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`;\n \n if (this.options.cookieDomain) {\n cookieStr += `;domain=${this.options.cookieDomain}`;\n } else if (this.options.crossDomain) {\n const domain = this.getRootDomain();\n if (domain) {\n cookieStr += `;domain=${domain}`;\n }\n }\n \n document.cookie = cookieStr;\n } catch (error) {\n console.warn('[Aegis Storage] deleteCookie failed:', error);\n }\n }\n\n private getRootDomain(): string | null {\n try {\n const hostname = window.location.hostname;\n \n if (/^(\\d{1,3}\\.){3}\\d{1,3}$/.test(hostname)) {\n return null;\n }\n \n if (hostname === 'localhost') {\n return null;\n }\n \n const parts = hostname.split('.');\n \n if (parts.length <= 2) {\n return `.${hostname}`;\n }\n \n return `.${parts.slice(-2).join('.')}`;\n } catch (error) {\n console.warn('[Aegis Storage] getRootDomain failed:', error);\n return null;\n }\n }\n}\n","export interface UTMParams {\n source?: string;\n medium?: string;\n campaign?: string;\n term?: string;\n content?: string;\n name?: string;\n}\n\nexport function parseUTMParameters(url?: string): UTMParams {\n try {\n const searchParams = url\n ? new URL(url).searchParams\n : new URLSearchParams(window.location.search);\n\n const utm: UTMParams = {};\n\n const utmKeys: Array<keyof UTMParams> = [\n 'source',\n 'medium',\n 'campaign',\n 'term',\n 'content',\n 'name',\n ];\n\n utmKeys.forEach((key) => {\n const value = searchParams.get(`utm_${key}`);\n if (value) {\n utm[key] = value;\n }\n });\n\n return utm;\n } catch (error) {\n console.warn('[Aegis URL Parser] parseUTMParameters failed:', error);\n return {};\n }\n}\n\nexport function parseQueryParameters(url?: string): Record<string, string> {\n try {\n const searchParams = url\n ? new URL(url).searchParams\n : new URLSearchParams(window.location.search);\n\n const params: Record<string, string> = {};\n\n searchParams.forEach((value, key) => {\n params[key] = value;\n });\n\n return params;\n } catch (error) {\n console.warn('[Aegis URL Parser] parseQueryParameters failed:', error);\n return {};\n }\n}\n\nexport function getCanonicalURL(): string {\n try {\n const canonical = document.querySelector('link[rel=\"canonical\"]');\n if (canonical && canonical.getAttribute('href')) {\n return canonical.getAttribute('href')!;\n }\n \n return window.location.href;\n } catch (error) {\n console.warn('[Aegis URL Parser] getCanonicalURL failed:', error);\n return window.location.href;\n }\n}\n\nexport function stripQueryParameters(url: string): string {\n try {\n const urlObj = new URL(url);\n return `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`;\n } catch (error) {\n console.warn('[Aegis URL Parser] stripQueryParameters failed:', error);\n return url;\n }\n}\n\nexport interface AdClickIDs {\n gclid?: string;\n fbclid?: string;\n msclkid?: string;\n ctwa_clid?: string;\n ttclid?: string;\n li_fat_id?: string;\n}\n\nexport function parseAdClickIDs(url?: string): AdClickIDs {\n try {\n const searchParams = url\n ? new URL(url).searchParams\n : new URLSearchParams(window.location.search);\n\n const adClickIDs: AdClickIDs = {};\n\n const clickIDKeys: Array<keyof AdClickIDs> = [\n 'gclid',\n 'fbclid',\n 'msclkid',\n 'ctwa_clid',\n 'ttclid',\n 'li_fat_id',\n ];\n\n clickIDKeys.forEach((key) => {\n const value = searchParams.get(key);\n if (value) {\n adClickIDs[key] = value;\n }\n });\n\n return adClickIDs;\n } catch (error) {\n console.warn('[Aegis URL Parser] parseAdClickIDs failed:', error);\n return {};\n }\n}\n\nexport function hasAdClickIDs(adClickIDs: AdClickIDs): boolean {\n return Object.keys(adClickIDs).length > 0;\n}\n","import { EventContext } from '../types/events';\nimport { parseUTMParameters } from './url-parser';\nimport { AegisConfigInternal } from '../types/config';\nimport type { SessionManager } from '../core/session';\n\nexport function buildContext(config: AegisConfigInternal, session?: SessionManager): EventContext {\n const utm = config.capture_utm ? parseUTMParameters() : undefined;\n const device = detectDevice();\n const os = detectOS();\n const browser = detectBrowser();\n const network = detectNetworkInfo();\n\n const adClickIDs = session?.getAdClickIDs();\n const landingPage = session?.getLandingPage();\n\n return {\n library: {\n name: '@active-reach/web-sdk',\n version: '1.0.0',\n },\n page: {\n path: window.location.pathname,\n referrer: config.capture_referrer ? document.referrer : '',\n search: window.location.search,\n title: document.title,\n url: window.location.href,\n hash: window.location.hash,\n },\n userAgent: navigator.userAgent,\n locale: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n screen: {\n width: window.screen.width,\n height: window.screen.height,\n density: window.devicePixelRatio || 1,\n },\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n ...(utm && Object.keys(utm).length > 0 && { campaign: utm }),\n ...(adClickIDs && Object.keys(adClickIDs).length > 0 && { adClickIDs }),\n ...(landingPage && { landingPage }),\n ...(network && { network }),\n ...(device && { device }),\n ...(os && { os }),\n ...(browser && { browser }),\n ...(config.active_cell && {\n cell: {\n region: config.active_cell.region,\n endpoint: config.active_cell.url,\n },\n }),\n };\n}\n\nfunction detectDevice(): EventContext['device'] {\n const ua = navigator.userAgent;\n\n if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {\n return { type: 'tablet' };\n }\n\n if (/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(ua)) {\n return { type: 'mobile' };\n }\n\n return { type: 'desktop' };\n}\n\nfunction detectOS(): EventContext['os'] {\n const ua = navigator.userAgent;\n\n if (/Windows NT 10/i.test(ua)) return { name: 'Windows', version: '10' };\n if (/Windows NT 6.3/i.test(ua)) return { name: 'Windows', version: '8.1' };\n if (/Windows NT 6.2/i.test(ua)) return { name: 'Windows', version: '8' };\n if (/Windows NT 6.1/i.test(ua)) return { name: 'Windows', version: '7' };\n if (/Windows/i.test(ua)) return { name: 'Windows', version: 'Unknown' };\n\n if (/Mac OS X (\\d+)[._](\\d+)/.test(ua)) {\n const match = ua.match(/Mac OS X (\\d+)[._](\\d+)/);\n return { name: 'macOS', version: `${match![1]}.${match![2]}` };\n }\n if (/Mac/i.test(ua)) return { name: 'macOS', version: 'Unknown' };\n\n if (/Android (\\d+\\.\\d+)/.test(ua)) {\n const match = ua.match(/Android (\\d+\\.\\d+)/);\n return { name: 'Android', version: match![1] };\n }\n if (/Android/i.test(ua)) return { name: 'Android', version: 'Unknown' };\n\n if (/iPhone OS (\\d+)_(\\d+)/.test(ua)) {\n const match = ua.match(/iPhone OS (\\d+)_(\\d+)/);\n return { name: 'iOS', version: `${match![1]}.${match![2]}` };\n }\n if (/iPad.*OS (\\d+)_(\\d+)/.test(ua)) {\n const match = ua.match(/iPad.*OS (\\d+)_(\\d+)/);\n return { name: 'iOS', version: `${match![1]}.${match![2]}` };\n }\n if (/iPhone|iPad/i.test(ua)) return { name: 'iOS', version: 'Unknown' };\n\n if (/Linux/i.test(ua)) return { name: 'Linux', version: 'Unknown' };\n\n return { name: 'Unknown', version: 'Unknown' };\n}\n\nfunction detectBrowser(): EventContext['browser'] {\n const ua = navigator.userAgent;\n\n if (/Edg\\/(\\d+\\.\\d+)/.test(ua)) {\n const match = ua.match(/Edg\\/(\\d+\\.\\d+)/);\n return { name: 'Edge', version: match![1] };\n }\n\n if (/Chrome\\/(\\d+\\.\\d+)/.test(ua) && !/Edg/.test(ua)) {\n const match = ua.match(/Chrome\\/(\\d+\\.\\d+)/);\n return { name: 'Chrome', version: match![1] };\n }\n\n if (/Firefox\\/(\\d+\\.\\d+)/.test(ua)) {\n const match = ua.match(/Firefox\\/(\\d+\\.\\d+)/);\n return { name: 'Firefox', version: match![1] };\n }\n\n if (/Safari\\/(\\d+\\.\\d+)/.test(ua) && !/Chrome/.test(ua)) {\n const match = ua.match(/Version\\/(\\d+\\.\\d+)/);\n return { name: 'Safari', version: match ? match[1] : 'Unknown' };\n }\n\n if (/MSIE (\\d+\\.\\d+)/.test(ua) || /Trident\\//.test(ua)) {\n const match = ua.match(/MSIE (\\d+\\.\\d+)/) || ua.match(/rv:(\\d+\\.\\d+)/);\n return { name: 'Internet Explorer', version: match ? match[1] : 'Unknown' };\n }\n\n return { name: 'Unknown', version: 'Unknown' };\n}\n\nfunction detectNetworkInfo(): EventContext['network'] | undefined {\n try {\n const connection =\n (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n\n if (connection) {\n return {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n };\n }\n } catch (error) {\n console.warn('[Aegis Device] detectNetworkInfo failed:', error);\n }\n\n return undefined;\n}\n\nexport function isBot(): boolean {\n const ua = navigator.userAgent.toLowerCase();\n const botPatterns = [\n 'bot',\n 'crawl',\n 'spider',\n 'slurp',\n 'mediapartners',\n 'googlebot',\n 'bingbot',\n 'yahoo',\n 'duckduckbot',\n 'baiduspider',\n 'yandex',\n 'facebookexternalhit',\n 'linkedinbot',\n 'twitterbot',\n 'slackbot',\n 'telegrambot',\n 'whatsapp',\n 'pingdom',\n 'uptimerobot',\n ];\n\n return botPatterns.some((pattern) => ua.includes(pattern));\n}\n","import { Plugin } from '../types/plugin';\nimport { logger } from '../utils/logger';\n\nexport class PluginRegistry {\n private plugins: Map<string, Plugin> = new Map();\n\n register(plugin: Plugin): void {\n if (this.plugins.has(plugin.name)) {\n logger.warn(`Plugin \"${plugin.name}\" already registered, skipping`);\n return;\n }\n\n this.plugins.set(plugin.name, plugin);\n logger.info(`Plugin registered: ${plugin.name} v${plugin.version}`);\n }\n\n unregister(pluginName: string): void {\n const plugin = this.plugins.get(pluginName);\n\n if (!plugin) {\n logger.warn(`Plugin \"${pluginName}\" not found`);\n return;\n }\n\n if (plugin.destroy) {\n try {\n plugin.destroy();\n } catch (error) {\n logger.error(`Error destroying plugin \"${pluginName}\":`, error);\n }\n }\n\n this.plugins.delete(pluginName);\n logger.info(`Plugin unregistered: ${pluginName}`);\n }\n\n get(pluginName: string): Plugin | undefined {\n return this.plugins.get(pluginName);\n }\n\n getAll(): Plugin[] {\n return Array.from(this.plugins.values());\n }\n\n async executeHook<T = any>(\n hookName: keyof Plugin,\n ...args: any[]\n ): Promise<T | undefined> {\n for (const plugin of this.plugins.values()) {\n const hook = plugin[hookName];\n\n if (typeof hook === 'function') {\n try {\n const result = await (hook as Function).apply(plugin, args);\n\n if (result !== undefined) {\n return result as T;\n }\n } catch (error) {\n logger.error(\n `Error executing ${String(hookName)} in plugin \"${plugin.name}\":`,\n error\n );\n\n if (plugin.onError) {\n try {\n plugin.onError(error as Error, { hookName, args });\n } catch (onErrorError) {\n logger.error(\n `Error in onError handler for plugin \"${plugin.name}\":`,\n onErrorError\n );\n }\n }\n }\n }\n }\n\n return undefined;\n }\n\n async executeHookChain<T = any>(\n hookName: keyof Plugin,\n initialValue: T,\n ...additionalArgs: any[]\n ): Promise<T> {\n let value = initialValue;\n\n for (const plugin of this.plugins.values()) {\n const hook = plugin[hookName];\n\n if (typeof hook === 'function') {\n try {\n const result = await (hook as Function).apply(plugin, [\n value,\n ...additionalArgs,\n ]);\n\n if (result !== undefined && result !== null) {\n value = result;\n }\n } catch (error) {\n logger.error(\n `Error executing ${String(hookName)} in plugin \"${plugin.name}\":`,\n error\n );\n\n if (plugin.onError) {\n try {\n plugin.onError(error as Error, { hookName, value, additionalArgs });\n } catch (onErrorError) {\n logger.error(\n `Error in onError handler for plugin \"${plugin.name}\":`,\n onErrorError\n );\n }\n }\n }\n }\n }\n\n return value;\n }\n\n async executeHookParallel<T = any>(\n hookName: keyof Plugin,\n ...args: any[]\n ): Promise<T[]> {\n const promises: Promise<T>[] = [];\n\n for (const plugin of this.plugins.values()) {\n const hook = plugin[hookName];\n\n if (typeof hook === 'function') {\n const promise = (async () => {\n try {\n return await (hook as Function).apply(plugin, args);\n } catch (error) {\n logger.error(\n `Error executing ${String(hookName)} in plugin \"${plugin.name}\":`,\n error\n );\n\n if (plugin.onError) {\n try {\n plugin.onError(error as Error, { hookName, args });\n } catch (onErrorError) {\n logger.error(\n `Error in onError handler for plugin \"${plugin.name}\":`,\n onErrorError\n );\n }\n }\n\n return undefined;\n }\n })();\n\n promises.push(promise);\n }\n }\n\n const results = await Promise.all(promises);\n return results.filter((r) => r !== undefined) as T[];\n }\n\n clear(): void {\n for (const plugin of this.plugins.values()) {\n if (plugin.destroy) {\n try {\n plugin.destroy();\n } catch (error) {\n logger.error(`Error destroying plugin \"${plugin.name}\":`, error);\n }\n }\n }\n\n this.plugins.clear();\n logger.info('All plugins cleared');\n }\n}\n","import { Storage } from './storage';\nimport { logger } from './logger';\n\nexport type ConsentCategory =\n | 'analytics'\n | 'marketing'\n | 'functional'\n | 'necessary';\n\nexport interface ConsentPreferences {\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n necessary: boolean;\n}\n\nexport type ConsentStatus = 'granted' | 'denied' | 'pending';\n\nexport interface ConsentManagerConfig {\n defaultConsent?: Partial<ConsentPreferences>;\n waitForConsent?: boolean;\n consentStorageKey?: string;\n}\n\nexport class ConsentManager {\n private storage: Storage;\n private config: Required<ConsentManagerConfig>;\n private preferences: ConsentPreferences;\n private listeners: Array<(preferences: ConsentPreferences) => void> = [];\n\n constructor(storage: Storage, config: ConsentManagerConfig = {}) {\n this.storage = storage;\n this.config = {\n defaultConsent: config.defaultConsent || {},\n waitForConsent: config.waitForConsent ?? false,\n consentStorageKey: config.consentStorageKey || 'aegis_consent',\n };\n\n this.preferences = this.loadPreferences();\n }\n\n private loadPreferences(): ConsentPreferences {\n const stored = this.storage.get(this.config.consentStorageKey);\n\n if (stored) {\n try {\n const parsed = JSON.parse(stored);\n logger.info('Loaded consent preferences:', parsed);\n return this.mergeWithDefaults(parsed);\n } catch (error) {\n logger.warn('Failed to parse consent preferences:', error);\n }\n }\n\n return this.getDefaultPreferences();\n }\n\n private getDefaultPreferences(): ConsentPreferences {\n return {\n analytics: this.config.defaultConsent.analytics ?? false,\n marketing: this.config.defaultConsent.marketing ?? false,\n functional: this.config.defaultConsent.functional ?? true,\n necessary: true,\n };\n }\n\n private mergeWithDefaults(\n preferences: Partial<ConsentPreferences>\n ): ConsentPreferences {\n return {\n necessary: true,\n analytics: preferences.analytics ?? this.config.defaultConsent.analytics ?? false,\n marketing: preferences.marketing ?? this.config.defaultConsent.marketing ?? false,\n functional: preferences.functional ?? this.config.defaultConsent.functional ?? true,\n };\n }\n\n private savePreferences(): void {\n try {\n this.storage.set(\n this.config.consentStorageKey,\n JSON.stringify(this.preferences),\n 365\n );\n logger.info('Saved consent preferences:', this.preferences);\n } catch (error) {\n logger.error('Failed to save consent preferences:', error);\n }\n }\n\n setConsent(preferences: Partial<ConsentPreferences>): void {\n const updated = { ...this.preferences, ...preferences };\n updated.necessary = true;\n\n this.preferences = updated;\n this.savePreferences();\n this.notifyListeners();\n\n logger.info('Consent updated:', this.preferences);\n }\n\n grantAll(): void {\n this.setConsent({\n analytics: true,\n marketing: true,\n functional: true,\n necessary: true,\n });\n }\n\n denyAll(): void {\n this.setConsent({\n analytics: false,\n marketing: false,\n functional: false,\n necessary: true,\n });\n }\n\n hasConsent(category: ConsentCategory): boolean {\n return this.preferences[category];\n }\n\n getPreferences(): ConsentPreferences {\n return { ...this.preferences };\n }\n\n getStatus(category: ConsentCategory): ConsentStatus {\n if (this.hasConsent(category)) {\n return 'granted';\n }\n\n const stored = this.storage.get(this.config.consentStorageKey);\n if (!stored && this.config.waitForConsent) {\n return 'pending';\n }\n\n return 'denied';\n }\n\n isAnalyticsEnabled(): boolean {\n return this.hasConsent('analytics');\n }\n\n isMarketingEnabled(): boolean {\n return this.hasConsent('marketing');\n }\n\n onChange(callback: (preferences: ConsentPreferences) => void): () => void {\n this.listeners.push(callback);\n\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n private notifyListeners(): void {\n this.listeners.forEach((listener) => {\n try {\n listener(this.getPreferences());\n } catch (error) {\n logger.error('Consent listener error:', error);\n }\n });\n }\n\n reset(): void {\n this.storage.remove(this.config.consentStorageKey);\n this.preferences = this.getDefaultPreferences();\n this.notifyListeners();\n logger.info('Consent preferences reset');\n }\n\n integrateOneTrust(): void {\n if (typeof window === 'undefined') return;\n\n const oneTrust = (window as any).OneTrust;\n if (!oneTrust) {\n logger.warn('OneTrust not detected');\n return;\n }\n\n const syncWithOneTrust = () => {\n const activeGroups = (window as any).OnetrustActiveGroups || '';\n\n this.setConsent({\n necessary: true,\n functional: activeGroups.includes('C0003'),\n analytics: activeGroups.includes('C0002'),\n marketing: activeGroups.includes('C0004'),\n });\n\n logger.info('Synced with OneTrust consent');\n };\n\n if ((window as any).OptanonWrapper) {\n const originalWrapper = (window as any).OptanonWrapper;\n (window as any).OptanonWrapper = function () {\n originalWrapper();\n syncWithOneTrust();\n };\n } else {\n (window as any).OptanonWrapper = syncWithOneTrust;\n }\n\n syncWithOneTrust();\n }\n\n integrateCookiebot(): void {\n if (typeof window === 'undefined') return;\n\n const cookiebot = (window as any).Cookiebot;\n if (!cookiebot) {\n logger.warn('Cookiebot not detected');\n return;\n }\n\n const syncWithCookiebot = () => {\n const consent = cookiebot.consent || {};\n\n this.setConsent({\n necessary: true,\n functional: consent.preferences || false,\n analytics: consent.statistics || false,\n marketing: consent.marketing || false,\n });\n\n logger.info('Synced with Cookiebot consent');\n };\n\n window.addEventListener('CookiebotOnAccept', syncWithCookiebot);\n window.addEventListener('CookiebotOnDecline', syncWithCookiebot);\n\n if (cookiebot.consent) {\n syncWithCookiebot();\n }\n }\n\n integrateGoogleConsentMode(): void {\n if (typeof window === 'undefined') return;\n\n const gtag = (window as any).gtag;\n if (!gtag) {\n logger.warn('Google Tag Manager not detected');\n return;\n }\n\n const updateGoogleConsent = () => {\n gtag('consent', 'update', {\n ad_storage: this.preferences.marketing ? 'granted' : 'denied',\n analytics_storage: this.preferences.analytics ? 'granted' : 'denied',\n ad_user_data: this.preferences.marketing ? 'granted' : 'denied',\n ad_personalization: this.preferences.marketing ? 'granted' : 'denied',\n functionality_storage: this.preferences.functional ? 'granted' : 'denied',\n personalization_storage: this.preferences.functional ? 'granted' : 'denied',\n security_storage: 'granted',\n });\n\n logger.info('Updated Google Consent Mode');\n };\n\n this.onChange(updateGoogleConsent);\n updateGoogleConsent();\n }\n}\n","/**\n * Meta Pixel companion cookies (_fbp, _fbc) — B1.2 of META_CAPI_PHASE1_TRACKER.\n *\n * We do NOT fire `fbq()` browser-side. We write the cookies Meta uses to\n * identify the same browser so server-side CAPI events (forwarded from\n * `meta_conversions_api_service.py`) carry the high-EMQ match keys\n * (fbp + fbc) without the cost of running a full Meta Pixel.\n *\n * Cookie spec (Meta docs, verified May 2026):\n * _fbp = fb.<subdomain_index>.<creation_ms>.<random>\n * _fbc = fb.<subdomain_index>.<click_ms>.<fbclid>\n * subdomain_index = number of dots in cookie domain\n * (example.com → 1, sub.example.com → 2)\n * random = 10-digit random integer\n * Lifetime: 90 days (Meta's default; longer doesn't increase EMQ)\n *\n * Reasoning for raw document.cookie writes (instead of utils/storage.ts):\n * The Storage helper prefixes every key with `aegis_` so writes go to\n * `aegis__fbp` / `aegis__fbc`. Meta only honors the exact names\n * `_fbp` and `_fbc`. We bypass the helper and write directly.\n *\n * Domain scope: written to the eTLD+1 (root domain) so a tenant who\n * later wires their own Meta Pixel via GTM sees the same cookies a\n * subdomain-rooted set would not.\n *\n * SSR-safe: every helper is no-op when `document` / `window` are\n * undefined. Callers don't need to guard.\n */\n\nconst FBP_COOKIE = '_fbp';\nconst FBC_COOKIE = '_fbc';\nconst COOKIE_LIFETIME_DAYS = 90;\n\nexport interface MetaCookies {\n fbp: string | null;\n fbc: string | null;\n fbclid: string | null;\n}\n\n/** Read a cookie value or null. SSR-safe. */\nfunction readCookie(name: string): string | null {\n if (typeof document === 'undefined') return null;\n try {\n const target = `${name}=`;\n const parts = document.cookie.split(';');\n for (let i = 0; i < parts.length; i++) {\n let c = parts[i];\n while (c.charAt(0) === ' ') c = c.substring(1);\n if (c.indexOf(target) === 0) {\n return decodeURIComponent(c.substring(target.length));\n }\n }\n } catch {\n /* swallow — cookie access can throw in cross-origin / sandboxed iframes */\n }\n return null;\n}\n\n/** Write a cookie at root-domain scope so cross-subdomain reads work. SSR-safe. */\nfunction writeCookie(name: string, value: string, days: number): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return;\n try {\n const expiry = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();\n const domain = getRootDomain();\n const isHttps = window.location.protocol === 'https:';\n let cookieStr = `${name}=${encodeURIComponent(value)};expires=${expiry};path=/;SameSite=Lax`;\n if (isHttps) cookieStr += ';Secure';\n if (domain) cookieStr += `;domain=${domain}`;\n document.cookie = cookieStr;\n } catch {\n /* ignore — best effort */\n }\n}\n\n/**\n * Get eTLD+1 of current host. Returns null on localhost / IP / single-label\n * hosts so we fall through to host-only cookie scope (browser default).\n *\n * Heuristic, not PSL-perfect: produces `example.com` for `a.b.example.com`.\n * Edge cases (`co.uk` etc.) get the wrong answer, but Meta itself uses\n * the same heuristic when their own pixel writes _fbp, so we stay aligned.\n */\nfunction getRootDomain(): string | null {\n if (typeof window === 'undefined') return null;\n const host = window.location.hostname;\n if (!host || host === 'localhost') return null;\n // IP address — host-only cookie scope.\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(host)) return null;\n const parts = host.split('.');\n if (parts.length < 2) return null;\n return '.' + parts.slice(-2).join('.');\n}\n\n/**\n * Subdomain index per Meta spec — count of dots in the cookie domain.\n * Counts components, not literal dots:\n * example.com → 1\n * sub.example.com → 2\n * sub.sub.example.com → 3\n */\nfunction subdomainIndex(): number {\n if (typeof window === 'undefined') return 1;\n const host = window.location.hostname;\n if (!host || host === 'localhost' || /^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(host)) return 1;\n const parts = host.split('.');\n return Math.max(1, parts.length - 1);\n}\n\n/** 10-digit random integer (Meta's spec format). */\nfunction randomToken(): string {\n // Math.random() * 1e10 produces a 10-digit-ish integer; pad-left to be safe.\n const n = Math.floor(Math.random() * 1e10);\n return n.toString().padStart(10, '0');\n}\n\n/**\n * Read `_fbp` from cookies, write a fresh one if absent.\n * Returns the resulting `_fbp` value or null if cookies unavailable.\n */\nexport function ensureFbp(): string | null {\n const existing = readCookie(FBP_COOKIE);\n if (existing) return existing;\n const fbp = `fb.${subdomainIndex()}.${Date.now()}.${randomToken()}`;\n writeCookie(FBP_COOKIE, fbp, COOKIE_LIFETIME_DAYS);\n return fbp;\n}\n\n/**\n * Read `_fbc` from cookies. If absent and the URL carries `fbclid`, write\n * a fresh `_fbc` per Meta's spec. Returns the resulting value or null.\n *\n * Note: `_fbc` has no value to write without an `fbclid` source — unlike\n * `_fbp` which is browser-identity-only and can be self-generated.\n */\nexport function ensureFbc(): string | null {\n const existing = readCookie(FBC_COOKIE);\n if (existing) return existing;\n const fbclid = readFbclidFromUrl();\n if (!fbclid) return null;\n const fbc = `fb.${subdomainIndex()}.${Date.now()}.${fbclid}`;\n writeCookie(FBC_COOKIE, fbc, COOKIE_LIFETIME_DAYS);\n return fbc;\n}\n\n/** Pull `fbclid` from `?fbclid=...` query string. Null if absent or SSR. */\nexport function readFbclidFromUrl(): string | null {\n if (typeof window === 'undefined') return null;\n try {\n return new URLSearchParams(window.location.search).get('fbclid');\n } catch {\n return null;\n }\n}\n\n/**\n * Single call that returns `{fbp, fbc, fbclid}` for injection into every\n * event's `properties` (which lands in ClickHouse `in_app_events.metadata`,\n * which the cell-side CAPI service reads directly).\n *\n * Side effects: ensures both cookies are present before returning. Idempotent\n * — safe to call on every event capture.\n */\nexport function captureMetaCookies(): MetaCookies {\n return {\n fbp: ensureFbp(),\n fbc: ensureFbc(),\n fbclid: readFbclidFromUrl(),\n };\n}\n","/**\n * E-Commerce helper methods for the Aegis SDK.\n *\n * Provides standardized e-commerce event tracking that maps to the\n * Active Reach Intelligence data governance pipeline.\n *\n * Event names follow the canonical mapper:\n * product_viewed → engagement.product_view\n * product_list_viewed → engagement.product_list_view\n * cart_item_added → cart_item_added\n * cart_item_removed → cart_item_removed\n * cart_viewed → cart_viewed\n * checkout_started → checkout_started\n * checkout_step → checkout_step\n * order_completed → transaction.purchase\n * order_refunded → transaction.refund\n * coupon_applied → coupon_applied\n * coupon_removed → coupon_removed\n * search_performed → search_performed\n * wishlist_item_added → wishlist_item_added\n * promotion_viewed → promotion_viewed\n * promotion_clicked → promotion_clicked\n */\n\nimport type { Aegis } from '../core/analytics';\nimport type {\n EcommerceProduct,\n EcommerceCart,\n EcommerceCheckout,\n EcommerceOrder,\n EcommerceCoupon,\n EcommerceSearch,\n EcommerceProductList,\n EcommerceWishlist,\n EcommercePromotion,\n} from './types';\n\nfunction sumItems(products: EcommerceProduct[]): number {\n return products.reduce((sum, p) => sum + (p.quantity ?? 1), 0);\n}\n\n// Cart abandonment detection is SERVER-SIDE. The SDK fires the canonical\n// e-commerce events (`cart_item_added`, `cart_item_removed`, `cart_viewed`,\n// `transaction.purchase`); a Kafka consumer on cell-plane maintains cart\n// state in Redis (`cart_state:{org}:{contact}:{cart_id}`) and a Celery beat\n// task scans for carts with no activity for N minutes, emitting\n// `cart_abandoned` to BEHAVIORAL_EVENTS_TOPIC.\n//\n// We deliberately do NOT run a JS timer on the client — mobile browsers\n// throttle background timers to ~1Hz and they're unreliable for any\n// abandonment threshold beyond a few seconds. Industry alignment: WebEngage,\n// MoEngage, CleverTap, Bitespeed, Klaviyo all detect server-side.\n//\n// See: `apps/cell-plane/app/workers/cart_state_tracker.py`\n\nfunction mapProducts(products: EcommerceProduct[]) {\n return products.map((p) => ({\n product_id: p.product_id,\n sku: p.sku ?? p.product_id,\n name: p.name,\n price: p.price,\n quantity: p.quantity ?? 1,\n currency: p.currency,\n category: p.category,\n brand: p.brand,\n variant_id: p.variant_id,\n variant_label: p.variant_label,\n position: p.position,\n }));\n}\n\nexport class EcommerceTracker {\n constructor(private aegis: Aegis) {}\n\n // -- Product Discovery --\n\n productViewed(product: EcommerceProduct): void {\n this.aegis.track('product_viewed', {\n product_id: product.product_id,\n sku: product.sku ?? product.product_id,\n name: product.name,\n price: product.price,\n currency: product.currency ?? 'INR',\n category: product.category,\n brand: product.brand,\n variant_id: product.variant_id,\n variant_label: product.variant_label,\n image_url: product.image_url,\n url: product.url,\n });\n }\n\n productListViewed(list: EcommerceProductList): void {\n this.aegis.track('product_list_viewed', {\n list_id: list.list_id,\n list_name: list.list_name,\n category: list.category,\n products: mapProducts(list.products),\n });\n }\n\n productClicked(product: EcommerceProduct, source?: { list_id?: string; position?: number; section?: string }): void {\n this.aegis.track('product_clicked', {\n product_id: product.product_id,\n sku: product.sku ?? product.product_id,\n name: product.name,\n price: product.price,\n currency: product.currency ?? 'INR',\n category: product.category,\n brand: product.brand,\n variant_id: product.variant_id,\n list_id: source?.list_id,\n position: source?.position ?? product.position,\n section: source?.section,\n });\n }\n\n productImpressed(product: EcommerceProduct, source?: { list_id?: string; position?: number; section?: string }): void {\n this.aegis.track('product_impression', {\n product_id: product.product_id,\n sku: product.sku ?? product.product_id,\n name: product.name,\n price: product.price,\n currency: product.currency ?? 'INR',\n category: product.category,\n list_id: source?.list_id,\n position: source?.position ?? product.position,\n section: source?.section,\n });\n }\n\n categoryFiltered(category: string, options?: { previous_category?: string; result_count?: number }): void {\n this.aegis.track('category_filtered', {\n category,\n previous_category: options?.previous_category,\n result_count: options?.result_count,\n });\n }\n\n searchPerformed(search: EcommerceSearch): void {\n this.aegis.track('search_performed', {\n query: search.query,\n results_count: search.results_count,\n filters: search.filters,\n });\n }\n\n // -- Cart --\n\n addToCart(product: EcommerceProduct): void {\n this.aegis.track('cart_item_added', {\n product_id: product.product_id,\n sku: product.sku ?? product.product_id,\n name: product.name,\n price: product.price,\n quantity: product.quantity ?? 1,\n currency: product.currency ?? 'INR',\n category: product.category,\n brand: product.brand,\n variant_id: product.variant_id,\n variant_label: product.variant_label,\n });\n }\n\n removeFromCart(product: EcommerceProduct): void {\n this.aegis.track('cart_item_removed', {\n product_id: product.product_id,\n sku: product.sku ?? product.product_id,\n name: product.name,\n price: product.price,\n quantity: product.quantity ?? 1,\n currency: product.currency ?? 'INR',\n variant_id: product.variant_id,\n });\n }\n\n cartViewed(cart: EcommerceCart): void {\n this.aegis.track('cart_viewed', {\n cart_id: cart.cart_id,\n value: cart.value,\n currency: cart.currency ?? 'INR',\n num_items: sumItems(cart.products),\n products: mapProducts(cart.products),\n });\n }\n\n // -- Checkout --\n\n checkoutStarted(checkout: EcommerceCheckout): void {\n this.aegis.track('checkout_started', {\n checkout_id: checkout.checkout_id,\n value: checkout.value,\n currency: checkout.currency ?? 'INR',\n num_items: sumItems(checkout.products),\n coupon: checkout.coupon,\n shipping: checkout.shipping,\n tax: checkout.tax,\n products: mapProducts(checkout.products),\n });\n }\n\n checkoutStep(step: number, options?: Record<string, unknown>): void {\n this.aegis.track('checkout_step', {\n step,\n ...options,\n });\n }\n\n // -- Order --\n\n orderCompleted(order: EcommerceOrder): void {\n this.aegis.track('order_completed', {\n order_id: order.order_id,\n value: order.value,\n revenue: order.revenue ?? order.value,\n currency: order.currency ?? 'INR',\n num_items: sumItems(order.products),\n coupon: order.coupon,\n shipping: order.shipping,\n tax: order.tax,\n discount: order.discount,\n payment_method: order.payment_method,\n products: mapProducts(order.products),\n });\n }\n\n orderRefunded(orderId: string, value?: number, products?: EcommerceProduct[]): void {\n this.aegis.track('order_refunded', {\n order_id: orderId,\n value,\n products: products ? mapProducts(products) : undefined,\n });\n }\n\n // -- Coupons --\n\n couponApplied(coupon: EcommerceCoupon): void {\n this.aegis.track('coupon_applied', { ...coupon });\n }\n\n couponRemoved(coupon: EcommerceCoupon): void {\n this.aegis.track('coupon_removed', { ...coupon });\n }\n\n // -- Wishlist --\n\n wishlistItemAdded(wishlist: EcommerceWishlist): void {\n this.aegis.track('wishlist_item_added', {\n wishlist_id: wishlist.wishlist_id,\n wishlist_name: wishlist.wishlist_name,\n product_id: wishlist.product.product_id,\n sku: wishlist.product.sku ?? wishlist.product.product_id,\n name: wishlist.product.name,\n price: wishlist.product.price,\n variant_id: wishlist.product.variant_id,\n });\n }\n\n // -- Promotions --\n\n promotionViewed(promo: EcommercePromotion): void {\n this.aegis.track('promotion_viewed', { ...promo });\n }\n\n promotionClicked(promo: EcommercePromotion): void {\n this.aegis.track('promotion_clicked', { ...promo });\n }\n}\n\nexport type {\n EcommerceProduct,\n EcommerceCart,\n EcommerceCheckout,\n EcommerceOrder,\n EcommerceCoupon,\n EcommerceSearch,\n EcommerceProductList,\n EcommerceWishlist,\n EcommercePromotion,\n} from './types';\n","/**\n * Token bucket rate limiter for client-side event throttling.\n *\n * Limits per session: burst (default 100) + sustained (default 20/sec).\n * Drops events with a console warning once a burst sustains. Drops are\n * emitted as a single coalesced `aegis.client.rate_limited` meta-event\n * per second so we don't flood ingress with drop notifications.\n *\n * Defaults are deliberately generous — the goal is to prevent runaway\n * loops (a buggy app firing 10k events/sec) without affecting normal use.\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface RateLimiterOptions {\n /** Max tokens (burst size). Default 100. */\n burstCapacity?: number;\n /** Sustained rate per second. Default 20. */\n refillPerSecond?: number;\n /** Window in ms over which dropped events are coalesced. Default 1000. */\n dropCoalesceWindowMs?: number;\n /** Optional callback fired with the count of dropped events per coalesce window. */\n onDropBatch?: (droppedCount: number, sampleEventName: string | null) => void;\n}\n\nexport class RateLimiter {\n private tokens: number;\n private readonly capacity: number;\n private readonly refillPerSecond: number;\n private lastRefillMs: number;\n\n private droppedThisWindow = 0;\n private firstDroppedName: string | null = null;\n private windowFlushTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly windowMs: number;\n private readonly onDropBatch?: (droppedCount: number, sampleEventName: string | null) => void;\n\n constructor(options: RateLimiterOptions = {}) {\n this.capacity = Math.max(1, options.burstCapacity ?? 100);\n this.refillPerSecond = Math.max(1, options.refillPerSecond ?? 20);\n this.windowMs = options.dropCoalesceWindowMs ?? 1000;\n this.onDropBatch = options.onDropBatch;\n this.tokens = this.capacity;\n this.lastRefillMs = Date.now();\n }\n\n /**\n * Try to consume 1 token. Returns true if allowed, false if throttled.\n * Throttled events are coalesced into a single onDropBatch callback per window.\n */\n tryConsume(eventName: string): boolean {\n this.refill();\n\n if (this.tokens >= 1) {\n this.tokens -= 1;\n return true;\n }\n\n this.droppedThisWindow += 1;\n if (this.firstDroppedName === null) {\n this.firstDroppedName = eventName;\n logger.warn(\n `[Aegis] Rate limit reached — dropping event \"${eventName}\" and any further events for ${this.windowMs}ms. Burst=${this.capacity}, refill=${this.refillPerSecond}/s.`,\n );\n }\n\n if (!this.windowFlushTimer) {\n this.windowFlushTimer = setTimeout(() => this.flushWindow(), this.windowMs);\n }\n\n return false;\n }\n\n /** Diagnostics — current token count (rounded down). */\n getAvailableTokens(): number {\n this.refill();\n return Math.floor(this.tokens);\n }\n\n /** Cleanup. Idempotent. */\n destroy(): void {\n if (this.windowFlushTimer) {\n clearTimeout(this.windowFlushTimer);\n this.windowFlushTimer = null;\n }\n this.flushWindow();\n }\n\n // ---------------------------------------------------------------------\n\n private refill(): void {\n const now = Date.now();\n const elapsedSec = (now - this.lastRefillMs) / 1000;\n if (elapsedSec <= 0) return;\n\n const newTokens = elapsedSec * this.refillPerSecond;\n this.tokens = Math.min(this.capacity, this.tokens + newTokens);\n this.lastRefillMs = now;\n }\n\n private flushWindow(): void {\n if (this.windowFlushTimer) {\n clearTimeout(this.windowFlushTimer);\n this.windowFlushTimer = null;\n }\n if (this.droppedThisWindow > 0 && this.onDropBatch) {\n try {\n this.onDropBatch(this.droppedThisWindow, this.firstDroppedName);\n } catch (err) {\n logger.warn('[Aegis] RateLimiter.onDropBatch threw:', err);\n }\n }\n this.droppedThisWindow = 0;\n this.firstDroppedName = null;\n }\n}\n","/**\n * MurmurHash3 x86-32 — deterministic, byte-identical with Python `mmh3.hash`.\n *\n * We hand-roll rather than pull a dep because (a) our bundle-budget is\n * aggressive for storefront first-paint, and (b) this is the authoritative\n * cross-language hash for the event-governance bloom filter — any behavior\n * drift between Python and JS produces silent FP-rate spikes in prod.\n *\n * Contract:\n * • Input is a JS string. It is UTF-8 encoded via TextEncoder before hashing.\n * • Output is an unsigned 32-bit integer (0 .. 2^32-1).\n * • Matches `mmh3.hash(s.encode('utf-8'), seed=seed, signed=False)` in\n * Python exactly — verified by libs/shared-types/bloom-test-vectors.json\n * in CI.\n *\n * Reference: Austin Appleby, MurmurHash3 (public domain).\n * https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp\n *\n * Implementation notes:\n * • All arithmetic on 32-bit ints. JS does bitwise ops on 32-bit ints natively;\n * `Math.imul` gives us correct 32-bit multiplication without overflow.\n * • We use `>>> 0` to coerce to unsigned after every step that could produce\n * a negative or >32-bit value.\n * • UTF-8 encoding matters — a naive `charCodeAt` loop would mis-hash any\n * string with non-ASCII characters (e.g. emoji, accented chars) and the\n * Python side would disagree. We always encode via TextEncoder first.\n */\n\nconst C1 = 0xcc9e2d51;\nconst C2 = 0x1b873593;\n\n/**\n * Compute MurmurHash3 x86-32 of a UTF-8 encoded string.\n *\n * @param input The string to hash.\n * @param seed 32-bit unsigned seed.\n * @returns Unsigned 32-bit integer hash.\n */\nexport function murmurhash3_x86_32(input: string, seed: number = 0): number {\n // Encode to UTF-8 bytes — matches Python's `s.encode('utf-8')`.\n const bytes = new TextEncoder().encode(input);\n return murmurhash3_bytes(bytes, seed);\n}\n\n/**\n * Compute MurmurHash3 x86-32 over a byte buffer directly.\n *\n * Exposed for callers that already have UTF-8 bytes and want to skip the\n * encode step (e.g., internal bloom-hash paths).\n */\nexport function murmurhash3_bytes(bytes: Uint8Array, seed: number = 0): number {\n const len = bytes.length;\n const nBlocks = Math.floor(len / 4);\n\n let h1 = seed >>> 0;\n\n // Body — consume 4-byte blocks.\n for (let i = 0; i < nBlocks; i++) {\n const offset = i * 4;\n let k1 =\n bytes[offset] |\n (bytes[offset + 1] << 8) |\n (bytes[offset + 2] << 16) |\n (bytes[offset + 3] << 24);\n\n k1 = Math.imul(k1, C1);\n k1 = (k1 << 15) | (k1 >>> 17);\n k1 = Math.imul(k1, C2);\n\n h1 ^= k1;\n h1 = (h1 << 13) | (h1 >>> 19);\n h1 = (Math.imul(h1, 5) + 0xe6546b64) >>> 0;\n }\n\n // Tail — up to 3 trailing bytes.\n const tailStart = nBlocks * 4;\n let k1 = 0;\n const tailLen = len - tailStart;\n if (tailLen === 3) k1 ^= bytes[tailStart + 2] << 16;\n if (tailLen >= 2) k1 ^= bytes[tailStart + 1] << 8;\n if (tailLen >= 1) {\n k1 ^= bytes[tailStart];\n k1 = Math.imul(k1, C1);\n k1 = (k1 << 15) | (k1 >>> 17);\n k1 = Math.imul(k1, C2);\n h1 ^= k1;\n }\n\n // Finalization — avalanche (fmix32).\n h1 ^= len;\n h1 ^= h1 >>> 16;\n h1 = Math.imul(h1, 0x85ebca6b);\n h1 ^= h1 >>> 13;\n h1 = Math.imul(h1, 0xc2b2ae35);\n h1 ^= h1 >>> 16;\n\n return h1 >>> 0;\n}\n","/**\n * Bloom filter — wire-compatible with the Python builder in\n * apps/control-plane/app/services/event_governance_bloom.py\n *\n * This SDK-side variant is QUERY-ONLY. The filter is built server-side\n * from the org's registered event-name set, base64-encoded, and shipped\n * to the browser on `/v1/sdk/bootstrap`. The SDK reads it once, uses it\n * to gate `track()` calls, and discards it on the next bootstrap.\n *\n * Wire format:\n * • `m` bits of storage, represented as m/8 bytes, base64-encoded.\n * • Bit `i` is at byte `i >> 3`, bitmask `1 << (i & 7)` — LSB-first.\n * • `m` MUST be a power of two — allows `idx & (m-1)` modulo.\n * • `k` hash functions synthesized via Kirsch-Mitzenmacher from two\n * MurmurHash3 x86-32 hashes with seeds (seedA, seedB):\n * h_i(x) = (h1(x) + i * h2(x)) mod m\n * • Input strings are UTF-8 encoded (handled inside murmurhash3_x86_32).\n */\n\nimport { murmurhash3_x86_32 } from './murmur3';\n\n/** Decode a base64 string to a Uint8Array. Accepts web (atob) and node (Buffer). */\nfunction base64ToBytes(b64: string): Uint8Array {\n if (typeof atob !== 'undefined') {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n }\n // Node.js fallback — used by tests and SSR integrations.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const B = (globalThis as any).Buffer;\n if (B && typeof B.from === 'function') {\n const buf: Uint8Array = B.from(b64, 'base64');\n // Copy into a plain Uint8Array so callers don't observe Buffer semantics.\n return new Uint8Array(buf);\n }\n throw new Error('No base64 decoder available (neither atob nor Buffer)');\n}\n\nexport interface BloomFilterParams {\n /** Bits in the filter (must be power of 2). */\n m: number;\n /** Number of hash functions (Kirsch-Mitzenmacher synthesized). */\n k: number;\n /** Seed for the first MurmurHash3 call. */\n seedA: number;\n /** Seed for the second MurmurHash3 call. */\n seedB: number;\n}\n\nexport class BloomFilter {\n private readonly buf: Uint8Array;\n private readonly mask: number;\n\n constructor(buf: Uint8Array, private readonly params: BloomFilterParams) {\n if ((params.m & (params.m - 1)) !== 0) {\n throw new Error(`Bloom filter m must be a power of 2, got ${params.m}`);\n }\n if (buf.length !== params.m >> 3) {\n throw new Error(\n `Bloom filter buffer size mismatch: expected ${params.m >> 3} bytes, got ${buf.length}`\n );\n }\n this.buf = buf;\n this.mask = params.m - 1;\n }\n\n /** Build from the wire format (base64 bytes + explicit params). */\n static fromBase64(bloomB64: string, params: BloomFilterParams): BloomFilter {\n const bytes = base64ToBytes(bloomB64);\n return new BloomFilter(bytes, params);\n }\n\n /**\n * Returns true if `name` is probably in the set — possibly with the\n * filter's configured false-positive rate. FALSE is always authoritative.\n *\n * FP here means: SDK thinks a name is already registered when it isn't.\n * That costs one wasted server round-trip (gateway does the exact check\n * and catches it) — strictly safer than a false-negative, which could\n * leak a novel name past the SDK.\n */\n has(name: string): boolean {\n const h1 = murmurhash3_x86_32(name, this.params.seedA);\n const h2 = murmurhash3_x86_32(name, this.params.seedB);\n\n for (let i = 0; i < this.params.k; i++) {\n // >>> 0 at each step to keep arithmetic in unsigned 32-bit land;\n // we can't just take & mask at the end because h1 + i*h2 could\n // overflow past 2^32 when i*h2 is large.\n const combined = (h1 + Math.imul(i, h2)) >>> 0;\n const idx = combined & this.mask;\n const bit = this.buf[idx >> 3] & (1 << (idx & 7));\n if (bit === 0) return false;\n }\n return true;\n }\n}\n","/**\n * NameGovernor — client-side event-name cap enforcement.\n *\n * The governor consumes an `EventGovernanceHint` from the bootstrap response\n * and decides whether to let a `track()` call proceed to the network or drop\n * it locally.\n *\n * Why this exists:\n * Without it, a page that calls `track('new_btn_' + Date.now())` in a\n * render loop would (a) pass the local rate-limiter if within burst, (b)\n * force the gateway to ask control-plane for a verdict on every unique\n * name, and (c) amplify the CP `/event-governance/check` load quadratically\n * in the number of tabs firing the same bug. The bloom filter gives the\n * SDK enough information to drop novel names locally once the org hits\n * its cap, collapsing the amplification to zero.\n *\n * Design constraints:\n * • FAIL-OPEN — missing hint (Enterprise org, Redis outage) lets every\n * name through. The gateway is still the authoritative cap.\n * • FALSE-POSITIVE-SAFE — if the bloom says \"known\" for a name that isn't\n * actually registered, we send to gateway and the gateway's exact check\n * catches it. FPs cost one round trip, not a cap bypass.\n * • LOCAL-MEMO — a novel name that has already charged `remainingNewNames`\n * in this tab must NOT charge again on subsequent calls within the same\n * hint TTL. Without this, `track('new_btn_click')` fired 50 times would\n * drain 50 from the counter and block every OTHER legitimate novel name.\n * See `localNovelNames`.\n *\n * See docs/architecture/RFC_2026_04_SDK_GOVERNANCE_HINTS.md §3.3.\n */\n\nimport { BloomFilter } from './bloom-filter';\n\n/** Shape of the hint delivered by `/v1/sdk/bootstrap`. */\nexport interface EventGovernanceHint {\n bloom_algo: string;\n seed_a: number;\n seed_b: number;\n k: number;\n m: number;\n bloom_b64: string;\n remaining_new_names: number | null;\n /**\n * When true, the server is in its 7-day soft-cap grace window: it accepts\n * novel event names past the cap. SDK must NOT drop locally in this mode —\n * doing so would enforce harder than the server. See\n * apps/control-plane/app/schemas/event_governance_hint.py for the canonical\n * contract.\n */\n grace_active?: boolean;\n ttl_seconds: number;\n}\n\nexport interface DropReport {\n /** Map of event_name → count of local drops since last drain. */\n events: Record<string, number>;\n /** Total events dropped across all names (sum of values). */\n total: number;\n /** When the report window started (ms since epoch). */\n since: number;\n}\n\n/** Matches the `bloom_algo` tag shipped by the current control-plane build. */\nconst SUPPORTED_ALGO = 'mmh3_x86_32_km';\n\n/**\n * Best-effort console.warn — coalesced so a runaway render loop doesn't\n * flood the dev console. We only warn on the FIRST distinct dropped name;\n * subsequent names silently increment the telemetry counter.\n */\nfunction warnOncePerSession(message: string): void {\n if (typeof console === 'undefined' || typeof console.warn !== 'function') return;\n console.warn(message);\n}\n\nexport class NameGovernor {\n private bloom: BloomFilter | null = null;\n private remainingNewNames: number = Infinity;\n private graceActive: boolean = false;\n\n /**\n * Names this SDK instance has seen AS NOVEL and already charged against\n * `remainingNewNames`. Reset on every `ingestHint()` so we don't leak\n * accounting across hint refreshes.\n */\n private localNovelNames: Set<string> = new Set();\n\n /** Coalesced telemetry — flushed to the transport via drainDropReport(). */\n private droppedSinceLastReport: Map<string, number> = new Map();\n private reportWindowStart: number = Date.now();\n private hasWarnedThisSession = false;\n\n /**\n * Ingest a freshly-bootstrapped hint. Call on every successful bootstrap.\n * Passing `null` disables governance (fail-open).\n */\n ingestHint(hint: EventGovernanceHint | null): void {\n if (!hint || hint.bloom_algo !== SUPPORTED_ALGO) {\n // Unknown algo — a newer CP ships a version this SDK can't decode.\n // Silently disable governance; gateway remains authoritative.\n this.bloom = null;\n this.remainingNewNames = Infinity;\n this.graceActive = false;\n this.localNovelNames.clear();\n return;\n }\n\n try {\n this.bloom = BloomFilter.fromBase64(hint.bloom_b64, {\n m: hint.m,\n k: hint.k,\n seedA: hint.seed_a,\n seedB: hint.seed_b,\n });\n } catch {\n // Malformed hint — fail-open. Logged by the caller.\n this.bloom = null;\n }\n\n this.remainingNewNames = hint.remaining_new_names ?? Infinity;\n this.graceActive = hint.grace_active === true;\n this.localNovelNames.clear();\n }\n\n /**\n * Decide whether a `track()` call should proceed.\n *\n * Returns true = send to network (rate-limiter still runs after).\n * Returns false = drop locally; caller should return early.\n */\n shouldSend(eventName: string): boolean {\n // No hint = unlimited plan or fail-open. Send everything.\n if (!this.bloom) return true;\n\n // 7-day soft-cap grace window is active — server accepts novel names\n // past the cap, so SDK must not enforce harder. Fail-open to gateway.\n if (this.graceActive) return true;\n\n // Known name — send.\n if (this.bloom.has(eventName)) return true;\n\n // Already charged in this session — send (gateway has it cached too).\n if (this.localNovelNames.has(eventName)) return true;\n\n // Novel name, within headroom — charge once, send.\n if (this.remainingNewNames > 0) {\n this.localNovelNames.add(eventName);\n this.remainingNewNames -= 1;\n return true;\n }\n\n // Novel name, over the cap — drop locally, record for telemetry.\n const prev = this.droppedSinceLastReport.get(eventName) ?? 0;\n this.droppedSinceLastReport.set(eventName, prev + 1);\n\n // Only warn once per session, only on the first distinct dropped name —\n // a runaway loop will fill droppedSinceLastReport silently.\n if (!this.hasWarnedThisSession) {\n this.hasWarnedThisSession = true;\n warnOncePerSession(\n `[aegis] Event-name cap reached — \"${eventName}\" dropped locally. ` +\n `Upgrade your plan or remove dynamically-generated event names.`\n );\n }\n return false;\n }\n\n /**\n * Snapshot + reset the dropped-names counter. Called by the telemetry\n * beacon on batch flush so the gateway gets visibility into client-side\n * drops for ops dashboards.\n */\n drainDropReport(): DropReport | null {\n if (this.droppedSinceLastReport.size === 0) return null;\n\n const events: Record<string, number> = {};\n let total = 0;\n for (const [name, count] of this.droppedSinceLastReport) {\n events[name] = count;\n total += count;\n }\n\n const since = this.reportWindowStart;\n this.droppedSinceLastReport.clear();\n this.reportWindowStart = Date.now();\n\n return { events, total, since };\n }\n\n // Test-only accessors — not part of public API but easier than reflection.\n /** @internal */\n _debugState(): {\n hasBloom: boolean;\n remaining: number;\n localNovel: number;\n graceActive: boolean;\n } {\n return {\n hasBloom: this.bloom !== null,\n remaining: this.remainingNewNames,\n localNovel: this.localNovelNames.size,\n graceActive: this.graceActive,\n };\n }\n}\n","/**\n * TraitGovernor — client-side guards for trait writes (P10.5).\n *\n * Runs the same 5 ingestion guards client-side that the cell-plane backend\n * runs at the trait-write chokepoint (`record_attribute_keys`), so the SDK\n * can warn developers about problematic keys/values BEFORE network send.\n *\n * Why two chokepoints:\n * - **Backend** (`record_attribute_keys` → DLQ): authoritative; rejects\n * payloads that bypass the SDK (direct HTTP, CSV import, integration\n * workers). Operators see rejections via /Validation tab.\n * - **SDK** (this file): developer-facing; warns in console.warn at dev\n * time so the issue is caught BEFORE the bad data hits production. We\n * normalize what we can (key casing, value truncation, date format)\n * and warn-then-drop what we can't (reserved prefixes).\n *\n * \"First-3 per verdict per session\" — we warn at most 3 times for each\n * verdict per `(workspace_id, verdict)` key in any given page load. After\n * that, silent — the developer got the message; further warnings would\n * just spam the console and obscure other issues.\n *\n * Canonical contract: the verdict codes here MUST match\n * `data_governance.ingestion_guards.GuardResult.verdict` codes + the\n * `ingestion_dlq.verdict` DB CHECK + the FE `IngestionDLQVerdict` union.\n * Real-env smoke asserts BE ↔ DB drift; TS narrowing catches FE drift;\n * this file completes the four-surface drift protection.\n */\n\nexport type TraitVerdict =\n | 'bad_key_format'\n | 'value_too_long'\n | 'bad_date_format'\n | 'name_too_long' // not used here (event-name guard); kept in union for symmetry\n | 'reserved_prefix';\n\nexport interface TraitDrop {\n /** Original key as the developer wrote it. */\n originalKey: string;\n /** What the guard decided. */\n verdict: TraitVerdict;\n /** Human-readable reason — same text we'd log to ingestion_dlq.reason. */\n reason: string;\n}\n\nexport interface TraitResult {\n /**\n * Sanitized traits to actually send. Reserved-prefix keys are absent;\n * camelCase keys are rewritten to snake_case; long values truncated;\n * ISO dates → epoch ms.\n */\n sanitized: Record<string, unknown>;\n /** Keys that were dropped or modified (one row per change). */\n drops: TraitDrop[];\n}\n\n// Reserved namespace prefixes — mirrors\n// data_governance.ingestion_guards.DEFAULT_RESERVED_PREFIXES.\nconst RESERVED_PREFIXES: readonly string[] = [\n 'system.',\n 'user.',\n 'loyalty.',\n 'review.',\n 'cart.',\n 'checkout.',\n 'product.',\n 'pos.',\n 'bill.',\n 'feedback.',\n 'chat.',\n 'delivery.',\n 'event.',\n '$',\n '_',\n];\n\n// PII not detected here — that's done server-side by the canonical\n// is_likely_pii helper. SDK side handles only normalization + format\n// rejections that benefit from early warning.\n\nconst KEY_SOFT_VALUE_CAP = 512; // truncate\nconst KEY_HARD_VALUE_CAP = 10_000; // reject (DoS protection)\n\nconst CAMEL_BOUNDARY_1 = /(.)([A-Z][a-z]+)/g;\nconst CAMEL_BOUNDARY_2 = /([a-z0-9])([A-Z])/g;\nconst NON_SNAKE = /[\\s\\-.]+/g;\nconst DUPE_UNDERSCORE = /_+/g;\nconst ISO_8601 = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\nconst DATE_KEY_HINTS = new Set([\n 'at', 'on', 'date', 'time', 'timestamp', 'dob', 'birthday',\n 'joined', 'expired', 'expires', 'created', 'updated', 'started', 'ended',\n]);\n\n/**\n * Normalize camelCase / PascalCase / dash-or-space-separated keys to\n * snake_case. Returns `null` if the key reduces to empty (caller treats\n * as `bad_key_format`).\n */\nfunction normalizeKey(key: string): string | null {\n if (!key) return null;\n const stage1 = key.replace(CAMEL_BOUNDARY_1, '$1_$2').replace(CAMEL_BOUNDARY_2, '$1_$2');\n const stage2 = stage1.replace(NON_SNAKE, '_').toLowerCase();\n const result = stage2.replace(DUPE_UNDERSCORE, '_').replace(/^_+|_+$/g, '');\n return result || null;\n}\n\nfunction startsWithReserved(key: string): string | null {\n const lower = key.toLowerCase();\n for (const prefix of RESERVED_PREFIXES) {\n if (lower.startsWith(prefix)) return prefix;\n }\n return null;\n}\n\nfunction looksLikeDateKey(key: string): boolean {\n for (const part of key.toLowerCase().split(/[_\\-.\\s]+/)) {\n if (DATE_KEY_HINTS.has(part)) return true;\n }\n return false;\n}\n\n/**\n * ISO-8601 / epoch string → epoch ms (number). Returns null on parse\n * failure. Numeric inputs assumed epoch (seconds if <1e11, else ms).\n */\nfunction parseDateValue(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value < 1e11 ? Math.floor(value * 1000) : Math.floor(value);\n }\n if (typeof value === 'string' && value) {\n const s = value.trim();\n if (ISO_8601.test(s)) {\n const ms = Date.parse(s);\n if (!Number.isNaN(ms)) return ms;\n }\n const asNum = Number(s);\n if (Number.isFinite(asNum)) {\n return asNum < 1e11 ? Math.floor(asNum * 1000) : Math.floor(asNum);\n }\n }\n return null;\n}\n\nfunction warnOnConsole(message: string): void {\n if (typeof console === 'undefined' || typeof console.warn !== 'function') return;\n console.warn(message);\n}\n\nexport class TraitGovernor {\n /** Cap warnings at 3 per (workspace_id, verdict) per session. */\n private static readonly WARN_CAP = 3;\n /** workspace_id || '__no_workspace__' → verdict → count. */\n private warnCounts: Map<string, Map<TraitVerdict, number>> = new Map();\n\n /**\n * Apply all guards to a traits object. Returns the sanitized payload\n * to send + a list of drops/modifications.\n *\n * Pass `workspace_id` so warning rate-limits scope per workspace; an\n * agency user switching workspaces won't have their warning budget\n * consumed cross-workspace.\n */\n process(\n traits: Record<string, unknown> | null | undefined,\n workspace_id?: string | null,\n ): TraitResult {\n const sanitized: Record<string, unknown> = {};\n const drops: TraitDrop[] = [];\n if (!traits || typeof traits !== 'object') {\n return { sanitized, drops };\n }\n\n for (const rawKey of Object.keys(traits)) {\n // 1. Reserved-prefix check runs on the ORIGINAL key, BEFORE\n // normalization. Otherwise `system.foo` would normalize to\n // `system_foo` (the `.` collapses to `_`) and bypass the\n // reserved check. This is the same order-of-operations bug\n // we caught at smoke time on the backend (2026-05-13).\n const prefix = startsWithReserved(rawKey);\n if (prefix !== null) {\n drops.push({\n originalKey: rawKey,\n verdict: 'reserved_prefix',\n reason: `key uses reserved namespace ${JSON.stringify(prefix)}`,\n });\n continue;\n }\n\n // 2. Normalize key casing.\n const normalizedKey = normalizeKey(rawKey);\n if (normalizedKey === null) {\n drops.push({\n originalKey: rawKey,\n verdict: 'bad_key_format',\n reason: `key reduced to empty after normalization`,\n });\n continue;\n }\n\n // 3. Re-check reserved on normalized form (belt-and-braces).\n if (startsWithReserved(normalizedKey) !== null) {\n drops.push({\n originalKey: rawKey,\n verdict: 'reserved_prefix',\n reason: `normalized key ${JSON.stringify(normalizedKey)} still uses a reserved namespace`,\n });\n continue;\n }\n\n // 4. Value-side guards.\n let value = traits[rawKey];\n\n // 4a. Truncate long strings (soft cap); reject huge strings (hard cap).\n if (typeof value === 'string') {\n if (value.length > KEY_HARD_VALUE_CAP) {\n drops.push({\n originalKey: rawKey,\n verdict: 'value_too_long',\n reason: `value length ${value.length} exceeds hard cap ${KEY_HARD_VALUE_CAP}`,\n });\n continue;\n }\n if (value.length > KEY_SOFT_VALUE_CAP) {\n drops.push({\n originalKey: rawKey,\n verdict: 'value_too_long',\n reason: `value truncated from ${value.length} to ${KEY_SOFT_VALUE_CAP} chars`,\n });\n value = value.slice(0, KEY_SOFT_VALUE_CAP);\n }\n }\n\n // 4b. Date normalization — only when the key hints at date semantics\n // AND the value looks string-shaped. Numeric values are assumed\n // epoch already. Free-form strings on non-date-keyed properties\n // pass through (caller meant a string).\n if (looksLikeDateKey(normalizedKey) && typeof value === 'string') {\n const parsed = parseDateValue(value);\n if (parsed === null) {\n drops.push({\n originalKey: rawKey,\n verdict: 'bad_date_format',\n reason: `value ${JSON.stringify(value)} on date-keyed field ${JSON.stringify(normalizedKey)} didn't parse as ISO-8601 / epoch`,\n });\n continue;\n }\n value = parsed;\n }\n\n sanitized[normalizedKey] = value;\n }\n\n // Emit first-3-per-verdict warnings (silent past the cap).\n for (const drop of drops) {\n this.maybeWarn(workspace_id ?? null, drop);\n }\n\n return { sanitized, drops };\n }\n\n private maybeWarn(workspace_id: string | null, drop: TraitDrop): void {\n const ws = workspace_id ?? '__no_workspace__';\n let perVerdict = this.warnCounts.get(ws);\n if (!perVerdict) {\n perVerdict = new Map();\n this.warnCounts.set(ws, perVerdict);\n }\n const count = perVerdict.get(drop.verdict) ?? 0;\n if (count >= TraitGovernor.WARN_CAP) return;\n perVerdict.set(drop.verdict, count + 1);\n warnOnConsole(\n `[Aegis SDK] trait ${drop.verdict}: ${drop.reason} ` +\n `(original key: ${JSON.stringify(drop.originalKey)}). ` +\n `Backend will reject; fix the SDK call to silence this warning.`,\n );\n }\n}\n","import {\n AegisConfig,\n AegisConfigInternal,\n DEFAULT_CONFIG,\n CellEndpoint,\n} from '../types/config';\nimport {\n TrackEvent,\n IdentifyEvent,\n PageEvent,\n GroupEvent,\n AliasEvent,\n AegisEvent,\n} from '../types/events';\nimport { Plugin } from '../types/plugin';\nimport { Identity } from '../utils/identity';\nimport { SessionManager } from './session';\nimport { EventQueue } from './queue';\nimport { Transport } from './transport';\nimport { Storage } from '../utils/storage';\nimport { buildContext, isBot } from '../utils/device';\nimport { generateMessageId } from '../utils/uuid';\nimport { logger } from '../utils/logger';\nimport { PluginRegistry } from '../plugins/registry';\nimport { ConsentManager, ConsentPreferences, ConsentCategory } from '../utils/consent';\nimport { captureMetaCookies } from '../utils/meta-cookies';\nimport { parseAdClickIDs, hasAdClickIDs } from '../utils/url-parser';\nimport { EcommerceTracker } from '../ecommerce';\nimport { RateLimiter } from './rate-limiter';\nimport { NameGovernor, EventGovernanceHint, TraitGovernor } from '../governance';\n\nexport class Aegis {\n private config: AegisConfigInternal | null = null;\n private storage!: Storage;\n private identity!: Identity;\n private session: SessionManager | null = null;\n private queue: EventQueue | null = null;\n private transport: Transport | null = null;\n private plugins: PluginRegistry = new PluginRegistry();\n private initPromise: Promise<void> | null = null;\n private consent: ConsentManager | null = null;\n private _ecommerce: EcommerceTracker | null = null;\n private rateLimiter: RateLimiter | null = null;\n private nameGovernor: NameGovernor = new NameGovernor();\n // P10.5 — client-side guards for trait writes. Mirrors the BE\n // chokepoint in `record_attribute_keys` so developers see console\n // warnings about reserved-prefix / bad-key / bad-date traits at\n // dev time, BEFORE the data hits production.\n private traitGovernor: TraitGovernor = new TraitGovernor();\n private _lastPageUrl: string | null = null;\n private _popstateHandler: (() => void) | null = null;\n private _originalPushState: typeof history.pushState | null = null;\n private _originalReplaceState: typeof history.replaceState | null = null;\n\n // B1.2 — last messageId per event name. Tenants who run their own Meta\n // Pixel via GTM call `aegis.lastEventId('Purchase')` to retrieve the id\n // we generated, then pass it as `eventID` to their `fbq('track', ...)`\n // call. Meta dedups on (pixel_id, event_name, event_id) so the\n // browser-fired Pixel event and our server-side CAPI event collapse to\n // one. See docs/integrations/META_PIXEL_COEXISTENCE.md.\n private _lastEventIds: Map<string, string> = new Map();\n\n async init(\n writeKey: string,\n config?: Partial<AegisConfig>\n ): Promise<void> {\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this._init(writeKey, config);\n return this.initPromise;\n }\n\n private async _init(\n writeKey: string,\n config?: Partial<AegisConfig>\n ): Promise<void> {\n if (this.config?.initialized) {\n logger.warn('SDK already initialized');\n return;\n }\n\n if (this.shouldRespectDNT(config)) {\n logger.info('Do Not Track is enabled, SDK disabled');\n return;\n }\n\n if (isBot()) {\n logger.info('Bot detected, SDK disabled');\n return;\n }\n\n this.config = this.buildConfig(writeKey, config);\n\n if (this.config.debug) {\n logger.enable();\n }\n\n logger.info('Initializing Aegis SDK...', this.config);\n\n this.storage = new Storage({\n cookieDomain: this.config.cookie_domain,\n secureCookie: this.config.secure_cookie,\n crossDomain: this.config.cross_domain_tracking,\n });\n\n this.identity = new Identity(this.storage);\n\n this.consent = new ConsentManager(this.storage, {\n defaultConsent: this.config.default_consent,\n waitForConsent: this.config.wait_for_consent,\n });\n\n if (this.config.integrate_onetrust) {\n this.consent.integrateOneTrust();\n }\n\n if (this.config.integrate_cookiebot) {\n this.consent.integrateCookiebot();\n }\n\n if (this.config.integrate_google_consent_mode) {\n this.consent.integrateGoogleConsentMode();\n }\n\n this.session = new SessionManager(\n this.storage,\n this.config.session_timeout\n );\n\n this.captureAdClickIDsOnInit();\n\n this.transport = new Transport(\n {\n writeKey: this.config.write_key,\n apiHost: this.config.api_host,\n cellEndpoints: this.config.cell_endpoints,\n preferredRegion: this.config.preferred_region,\n autoRegionDetection: this.config.auto_region_detection,\n requestTimeout: this.config.request_timeout,\n retryFailedRequests: this.config.retry_failed_requests,\n maxRetries: this.config.max_retries,\n retryBackoffMultiplier: this.config.retry_backoff_multiplier,\n },\n this.storage\n );\n\n this.config.active_cell = this.transport.getActiveCell();\n\n this.queue = new EventQueue(\n {\n batchSize: this.config.batch_size,\n batchInterval: this.config.batch_interval,\n enableOfflineMode: this.config.enable_offline_mode,\n maxOfflineEvents: this.config.max_offline_events,\n },\n this.transport,\n this.storage\n );\n\n this.rateLimiter = new RateLimiter({\n burstCapacity: this.config.rate_limit_burst,\n refillPerSecond: this.config.rate_limit_per_second,\n onDropBatch: (count, sampleName) => this.emitRateLimitMeta(count, sampleName),\n });\n\n await this.initializePlugins();\n\n if (this.config.auto_page_view) {\n this.page();\n this.startSPATracking();\n }\n\n logger.info('Aegis SDK initialized successfully');\n }\n\n /**\n * SPA navigation tracking — monkey-patches pushState/replaceState and\n * listens for popstate to fire page() on every client-side route change.\n */\n private startSPATracking(): void {\n this._lastPageUrl = window.location.href;\n\n const onRouteChange = () => {\n // Debounce: only fire if URL actually changed\n const currentUrl = window.location.href;\n if (currentUrl === this._lastPageUrl) return;\n this._lastPageUrl = currentUrl;\n\n // Small delay to let the framework update document.title\n setTimeout(() => {\n this.page();\n }, 50);\n };\n\n // Listen for browser back/forward\n this._popstateHandler = onRouteChange;\n window.addEventListener('popstate', this._popstateHandler);\n\n // Monkey-patch pushState and replaceState\n this._originalPushState = history.pushState.bind(history);\n this._originalReplaceState = history.replaceState.bind(history);\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n this._originalPushState!(...args);\n onRouteChange();\n };\n\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n this._originalReplaceState!(...args);\n onRouteChange();\n };\n }\n\n private stopSPATracking(): void {\n if (this._popstateHandler) {\n window.removeEventListener('popstate', this._popstateHandler);\n this._popstateHandler = null;\n }\n\n if (this._originalPushState) {\n history.pushState = this._originalPushState;\n this._originalPushState = null;\n }\n\n if (this._originalReplaceState) {\n history.replaceState = this._originalReplaceState;\n this._originalReplaceState = null;\n }\n }\n\n private buildConfig(\n writeKey: string,\n config?: Partial<AegisConfig>\n ): AegisConfigInternal {\n return {\n ...DEFAULT_CONFIG,\n ...config,\n write_key: writeKey,\n initialized: true,\n } as AegisConfigInternal;\n }\n\n private shouldRespectDNT(config?: Partial<AegisConfig>): boolean {\n const respectDNT = config?.respect_dnt !== false;\n if (!respectDNT) return false;\n\n const dnt =\n navigator.doNotTrack ||\n (window as any).doNotTrack ||\n (navigator as any).msDoNotTrack;\n\n return dnt === '1' || dnt === 'yes';\n }\n\n private captureAdClickIDsOnInit(): void {\n if (!this.session) return;\n\n const adClickIDs = parseAdClickIDs();\n\n if (hasAdClickIDs(adClickIDs)) {\n this.session.setAdClickIDs(adClickIDs, window.location.href);\n logger.info('Ad click IDs captured on page load:', adClickIDs);\n }\n }\n\n private async initializePlugins(): Promise<void> {\n if (!this.config) return;\n\n for (const pluginName of this.config.plugins) {\n logger.debug(`Initializing plugin: ${pluginName}`);\n }\n\n await this.plugins.executeHook('init', this.config);\n }\n\n use(plugin: Plugin): void {\n this.plugins.register(plugin);\n\n if (this.config?.initialized && plugin.init) {\n Promise.resolve(plugin.init(this.config)).catch((error: any) => {\n logger.error(`Failed to initialize plugin \"${plugin.name}\":`, error);\n });\n }\n }\n\n track(eventName: string, properties?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n const messageId = generateMessageId();\n const event: TrackEvent = {\n type: 'track',\n event: eventName,\n properties: properties || {},\n messageId,\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session!.getSessionId(),\n workspace_id: this.config!.workspace_id || undefined,\n context: buildContext(this.config!, this.session!),\n };\n\n // Record so tenants who run their own Meta Pixel via GTM can pull the\n // event_id and pass it as `eventID` in fbq('track', ...). See B1.2.\n this._lastEventIds.set(eventName, messageId);\n\n this.captureEvent(event);\n }\n\n identify(userId: string, traits?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n // P10.5 — apply trait governance BEFORE setUserId + send. The BE\n // applies the same guards in `record_attribute_keys`, but doing it\n // client-side lets us warn the developer in console.warn and emit\n // sanitized values so what they see locally matches what gets stored.\n const wsForGovernor = this.config!.workspace_id || null;\n const { sanitized: governedTraits } = this.traitGovernor.process(traits, wsForGovernor);\n\n this.identity.setUserId(userId, governedTraits);\n\n const event: IdentifyEvent = {\n type: 'identify',\n traits: governedTraits,\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: userId,\n sessionId: this.session!.getSessionId(),\n workspace_id: this.config!.workspace_id || undefined,\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n page(name?: string, properties?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n const event: PageEvent = {\n type: 'page',\n name: name || document.title,\n properties: properties || {},\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session!.getSessionId(),\n workspace_id: this.config!.workspace_id || undefined,\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n group(groupId: string, traits?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n // P10.5 — same trait governance as identify(); group traits ride\n // the same `record_attribute_keys` BE chokepoint.\n const wsForGovernor = this.config!.workspace_id || null;\n const { sanitized: governedTraits } = this.traitGovernor.process(traits, wsForGovernor);\n\n const event: GroupEvent = {\n type: 'group',\n groupId,\n traits: governedTraits,\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session!.getSessionId(),\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n alias(newUserId: string): void {\n if (!this.assertInitialized()) return;\n\n const { previousId } = this.identity.alias(newUserId);\n\n const event: AliasEvent = {\n type: 'alias',\n previousId,\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: newUserId,\n sessionId: this.session!.getSessionId(),\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n private async captureEvent(event: AegisEvent): Promise<void> {\n if (this.config?.enable_consent_mode && this.consent) {\n if (event.type === 'track' || event.type === 'page') {\n if (!this.consent.hasConsent('analytics')) {\n logger.debug('Event blocked: analytics consent not granted');\n return;\n }\n }\n }\n\n // Event-name governance — drops novel names once the org's unique-event\n // cap is exhausted. Meta events (aegis.client.*) bypass the governor so\n // the telemetry channel stays open even under a cap-exhaustion storm.\n // See governance/name-governor.ts.\n if (event.type === 'track') {\n const trackEvent = event as TrackEvent;\n const isMetaEvent =\n typeof trackEvent.event === 'string' &&\n trackEvent.event.startsWith('aegis.client.');\n if (!isMetaEvent && !this.nameGovernor.shouldSend(trackEvent.event)) {\n return;\n }\n }\n\n if (this.rateLimiter) {\n const eventLabel =\n event.type === 'track' && (event as TrackEvent).event\n ? (event as TrackEvent).event\n : event.type;\n // Meta-events bypass the rate limiter to avoid recursion / lost telemetry.\n const isMetaEvent =\n event.type === 'track' &&\n typeof (event as TrackEvent).event === 'string' &&\n (event as TrackEvent).event.startsWith('aegis.client.');\n if (!isMetaEvent && !this.rateLimiter.tryConsume(eventLabel)) {\n return;\n }\n }\n\n // Auto-inject campaign attribution from UTM context into event properties\n // so downstream consumers (event-ingress, ClickHouse) receive campaign_id\n // without requiring manual mapping by the integrator.\n const ctx = (event as any).context;\n const props = (event as any).properties;\n if (ctx?.campaign && props && !props.campaign_id) {\n const utm = ctx.campaign;\n if (utm.campaign) props.campaign_id = utm.campaign;\n if (utm.source) props.campaign_source = utm.source;\n if (utm.medium) props.campaign_medium = utm.medium;\n if (utm.content) props.campaign_content = utm.content;\n if (utm.term) props.campaign_term = utm.term;\n }\n if (ctx?.adClickIDs && props) {\n const clicks = ctx.adClickIDs;\n const clickId = clicks.gclid || clicks.fbclid || clicks.ctwa_clid || clicks.msclkid || clicks.ttclid;\n if (clickId && !props.campaign_click_id) props.campaign_click_id = clickId;\n }\n\n // B1.2 — Auto-inject Meta companion cookies (_fbp, _fbc, fbclid) into\n // event properties so the cell-side CAPI service can pass them as\n // user_data fields to Meta. Lifts EMQ from ~6-7 (PII-only) to ≥8.0\n // without firing fbq() browser-side. fbp is self-generated if absent;\n // fbc only set when an inbound fbclid landed in the URL.\n // See libs/web-sdk/src/utils/meta-cookies.ts for the spec.\n if (props) {\n const meta = captureMetaCookies();\n if (meta.fbp && !props.fbp) props.fbp = meta.fbp;\n if (meta.fbc && !props.fbc) props.fbc = meta.fbc;\n if (meta.fbclid && !props.fbclid) props.fbclid = meta.fbclid;\n }\n\n logger.debug('Capturing event:', event);\n\n const transformedEvent = await this.plugins.executeHookChain(\n 'beforeEventCapture',\n event\n );\n\n if (!transformedEvent) {\n logger.debug('Event cancelled by plugin');\n return;\n }\n\n this.queue!.push(transformedEvent);\n this.session!.incrementEventCount();\n\n await this.plugins.executeHook('afterEventCapture', transformedEvent);\n }\n\n /**\n * Emit a coalesced meta-event reporting client-side rate-limit drops.\n * Bypasses the limiter (see captureEvent guard).\n */\n private emitRateLimitMeta(count: number, sampleEventName: string | null): void {\n if (!this.config?.initialized || !this.session || !this.identity) return;\n const event: TrackEvent = {\n type: 'track',\n event: 'aegis.client.rate_limited',\n properties: {\n dropped_count: count,\n sample_event_name: sampleEventName,\n burst_capacity: this.config.rate_limit_burst,\n refill_per_second: this.config.rate_limit_per_second,\n },\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session.getSessionId(),\n context: buildContext(this.config, this.session),\n };\n this.queue?.push(event);\n }\n\n reset(): void {\n if (!this.assertInitialized()) return;\n\n this.identity.reset();\n logger.info('User identity reset');\n }\n\n /**\n * Ingest the event-governance hint returned from `/v1/sdk/bootstrap`.\n *\n * Callers (Shopify pixel, snippet, react integration) run `bootstrap()`\n * themselves and pass the resulting `eventGovernance` field here so the\n * SDK can self-throttle novel event names before they hit the gateway.\n *\n * Passing null/undefined disables governance (Enterprise plan / outage\n * fail-open). Safe to call before `init()` — the hint is stored and\n * applied as soon as init completes.\n */\n ingestGovernanceHint(hint: EventGovernanceHint | null | undefined): void {\n this.nameGovernor.ingestHint(hint ?? null);\n logger.debug('Governance hint ingested', hint ? {\n k: hint.k,\n m: hint.m,\n remaining: hint.remaining_new_names,\n } : 'disabled');\n }\n\n /**\n * Drain the client-side drop counter and emit a meta-event. Called\n * periodically by the queue flush path so ops dashboards see novel-name\n * amplification patterns in near-real-time.\n */\n private emitGovernanceDropMeta(): void {\n if (!this.config?.initialized || !this.session || !this.identity) return;\n const report = this.nameGovernor.drainDropReport();\n if (!report) return;\n\n const event: TrackEvent = {\n type: 'track',\n event: 'aegis.client.name_governor_dropped',\n properties: {\n dropped_count: report.total,\n distinct_names: Object.keys(report.events).length,\n // Cap the payload — a runaway loop could produce thousands of names;\n // we ship the top 10 for diagnostics and the total for counting.\n sample_names: Object.entries(report.events)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([name, count]) => ({ name, count })),\n window_start: report.since,\n window_end: Date.now(),\n },\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session.getSessionId(),\n context: buildContext(this.config, this.session),\n };\n this.queue?.push(event);\n }\n\n async flush(): Promise<void> {\n if (!this.assertInitialized()) return;\n\n // Emit any coalesced governance-drop telemetry BEFORE flushing so the\n // meta event rides in the same batch as the rest.\n this.emitGovernanceDropMeta();\n await this.queue!.flush();\n }\n\n getAnonymousId(): string | null {\n if (!this.identity) return null;\n return this.identity.getAnonymousId();\n }\n\n getUserId(): string | null {\n if (!this.identity) return null;\n return this.identity.getUserId();\n }\n\n getSessionId(): string | null {\n if (!this.session) return null;\n return this.session.getSessionId();\n }\n\n /**\n * B1.2 — Tenant-Pixel coexistence handoff. Returns the messageId of the\n * most recent `track('<eventName>', ...)` call, or null if no event of\n * that name has been tracked since SDK init.\n *\n * Use this from a tenant's own Meta Pixel script (e.g. via GTM) to pass\n * the same event_id to `fbq('track', '<eventName>', payload, {eventID: id})`.\n * Meta dedups on (pixel_id, event_name, event_id) so the browser-fired\n * Pixel event and our server-side CAPI event collapse to one — preventing\n * double-counting.\n *\n * Event names are case-sensitive (\"Purchase\" ≠ \"purchase\") — Meta's dedup\n * is also case-sensitive, so be exact.\n *\n * See docs/integrations/META_PIXEL_COEXISTENCE.md.\n */\n lastEventId(eventName: string): string | null {\n return this._lastEventIds.get(eventName) ?? null;\n }\n\n debug(enable: boolean = true): void {\n if (enable) {\n logger.enable();\n } else {\n logger.disable();\n }\n\n if (this.config) {\n this.config.debug = enable;\n }\n }\n\n setCell(cellEndpoint: CellEndpoint): void {\n if (!this.config) {\n logger.warn('SDK not initialized');\n return;\n }\n\n const existingCell = this.config.cell_endpoints.find(\n (c) => c.region === cellEndpoint.region\n );\n\n if (existingCell) {\n Object.assign(existingCell, cellEndpoint);\n } else {\n this.config.cell_endpoints.push(cellEndpoint);\n }\n\n logger.info('Cell endpoint configured:', cellEndpoint);\n }\n\n getCellInfo() {\n if (!this.transport) return null;\n\n return {\n activeCell: this.transport.getActiveCell(),\n latencies: this.transport.getRegionLatencies(),\n };\n }\n\n setConsent(preferences: Partial<ConsentPreferences>): void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return;\n }\n\n this.consent.setConsent(preferences);\n logger.info('Consent preferences updated');\n }\n\n grantConsent(category?: ConsentCategory): void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return;\n }\n\n if (category) {\n this.consent.setConsent({ [category]: true });\n } else {\n this.consent.grantAll();\n }\n }\n\n denyConsent(category?: ConsentCategory): void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return;\n }\n\n if (category) {\n this.consent.setConsent({ [category]: false });\n } else {\n this.consent.denyAll();\n }\n }\n\n hasConsent(category: ConsentCategory): boolean {\n if (!this.consent) {\n return true;\n }\n\n return this.consent.hasConsent(category);\n }\n\n getConsentPreferences(): ConsentPreferences | null {\n if (!this.consent) {\n return null;\n }\n\n return this.consent.getPreferences();\n }\n\n onConsentChange(callback: (preferences: ConsentPreferences) => void): () => void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return () => {};\n }\n\n return this.consent.onChange(callback);\n }\n\n private assertInitialized(): boolean {\n if (!this.config?.initialized) {\n logger.warn('SDK not initialized. Call aegis.init() first.');\n return false;\n }\n return true;\n }\n\n get ecommerce(): EcommerceTracker {\n if (!this._ecommerce) {\n this._ecommerce = new EcommerceTracker(this);\n }\n return this._ecommerce;\n }\n\n destroy(): void {\n this.stopSPATracking();\n\n if (this.queue) {\n this.queue.destroy();\n }\n\n if (this.session) {\n this.session.destroy();\n }\n\n if (this.transport) {\n this.transport.destroy();\n }\n\n if (this.rateLimiter) {\n this.rateLimiter.destroy();\n this.rateLimiter = null;\n }\n\n this.plugins.clear();\n\n logger.info('SDK destroyed');\n }\n}\n"],"names":["k1"],"mappings":"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"}