@axeptio/behavior-detection 1.0.2 → 1.1.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.
- package/README.md +126 -12
- package/dist/behavior-detection.esm.min.js +1 -1
- package/dist/behavior-detection.esm.min.js.map +4 -4
- package/dist/behavior-detection.min.js +1 -1
- package/dist/behavior-detection.min.js.map +3 -3
- package/dist/cjs/index.cjs +2320 -0
- package/dist/esm/browser.js +0 -2
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/strategies/click.d.ts +8 -0
- package/dist/esm/strategies/click.js +108 -9
- package/dist/esm/strategies/environment.d.ts +39 -0
- package/dist/esm/strategies/environment.js +188 -7
- package/dist/esm/strategies/index.d.ts +4 -0
- package/dist/esm/strategies/index.js +4 -0
- package/dist/esm/strategies/mouse.d.ts +53 -1
- package/dist/esm/strategies/mouse.js +198 -2
- package/dist/esm/strategies/timing.d.ts +64 -0
- package/dist/esm/strategies/timing.js +308 -0
- package/dist/esm/strategies/visibility.d.ts +64 -0
- package/dist/esm/strategies/visibility.js +295 -0
- package/dist/index.d.ts +1 -1
- package/dist/strategies/click.d.ts +8 -0
- package/dist/strategies/environment.d.ts +39 -0
- package/dist/strategies/index.d.ts +4 -0
- package/dist/strategies/mouse.d.ts +53 -1
- package/dist/strategies/timing.d.ts +64 -0
- package/dist/strategies/visibility.d.ts +64 -0
- package/package.json +16 -15
- package/dist/cjs/behavior-detector.d.ts +0 -102
- package/dist/cjs/behavior-detector.js +0 -315
- package/dist/cjs/browser.d.ts +0 -33
- package/dist/cjs/browser.js +0 -226
- package/dist/cjs/index.d.ts +0 -38
- package/dist/cjs/index.js +0 -55
- package/dist/cjs/math-utils.d.ts +0 -84
- package/dist/cjs/math-utils.js +0 -141
- package/dist/cjs/strategies/click.d.ts +0 -39
- package/dist/cjs/strategies/click.js +0 -173
- package/dist/cjs/strategies/environment.d.ts +0 -52
- package/dist/cjs/strategies/environment.js +0 -148
- package/dist/cjs/strategies/index.d.ts +0 -18
- package/dist/cjs/strategies/index.js +0 -36
- package/dist/cjs/strategies/keyboard.d.ts +0 -43
- package/dist/cjs/strategies/keyboard.js +0 -233
- package/dist/cjs/strategies/mouse.d.ts +0 -39
- package/dist/cjs/strategies/mouse.js +0 -159
- package/dist/cjs/strategies/resize.d.ts +0 -21
- package/dist/cjs/strategies/resize.js +0 -97
- package/dist/cjs/strategies/scroll.d.ts +0 -37
- package/dist/cjs/strategies/scroll.js +0 -149
- package/dist/cjs/strategies/tap.d.ts +0 -38
- package/dist/cjs/strategies/tap.js +0 -214
- package/dist/cjs/strategy.d.ts +0 -107
- package/dist/cjs/strategy.js +0 -33
- package/dist/cjs/types.d.ts +0 -168
- package/dist/cjs/types.js +0 -26
- package/dist/esm/browser-iife.d.ts +0 -5
- package/dist/esm/browser-iife.js +0 -157
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["esm/behavior-detector.js", "esm/strategy.js", "esm/math-utils.js", "esm/strategies/mouse.js", "esm/strategies/scroll.js", "esm/strategies/click.js", "esm/strategies/tap.js", "esm/strategies/keyboard.js", "esm/strategies/environment.js", "esm/strategies/resize.js", "esm/types.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * Main class for behavior detection\n * Uses modular strategy pattern for tree-shakeable, autonomous detection modules\n */\nexport class BehaviorDetector {\n constructor(tickOptions) {\n // Strategy mode\n this.strategies = new Map();\n this.isTracking = false;\n this.isPausedByVisibility = false;\n this.tickInterval = null;\n this.tickIntervalMs = 1000; // Default: 1 second\n this.pauseOnHidden = true;\n this.visibilityChangeHandler = null;\n // Confidence tracking\n this.confidenceScore = 0;\n this.CONFIDENCE_TARGET = 1.0; // Target confidence for reliable classification\n this.CONFIDENCE_DECAY = 0.95; // Per event decay to prevent infinite growth\n if (tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.interval) {\n this.tickIntervalMs = tickOptions.interval;\n }\n if ((tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.pauseOnHidden) !== undefined) {\n this.pauseOnHidden = tickOptions.pauseOnHidden;\n }\n }\n /**\n * Add a detection strategy\n */\n addStrategy(strategy, weight) {\n const config = {\n strategy,\n weight: weight !== null && weight !== void 0 ? weight : strategy.defaultWeight,\n enabled: true,\n };\n this.strategies.set(strategy.name, config);\n // Set up event callback for confidence tracking\n if (strategy.setEventCallback) {\n strategy.setEventCallback((event) => {\n this.onStrategyEvent(event, config.weight);\n });\n }\n // If already tracking, start this strategy immediately\n if (this.isTracking) {\n strategy.start();\n }\n return this;\n }\n /**\n * Handle event from strategy - update confidence\n */\n onStrategyEvent(event, strategyWeight) {\n // Apply decay to existing confidence to prevent infinite growth\n this.confidenceScore *= this.CONFIDENCE_DECAY;\n // Add weighted contribution from this event\n // eventWeight (0-1) * strategyWeight (e.g. 0.3 for mouse) = contribution\n const contribution = event.weight * strategyWeight;\n this.confidenceScore = Math.min(this.CONFIDENCE_TARGET, this.confidenceScore + contribution);\n }\n /**\n * Remove a detection strategy\n */\n removeStrategy(name) {\n const config = this.strategies.get(name);\n if (config) {\n if (this.isTracking) {\n config.strategy.stop();\n }\n this.strategies.delete(name);\n }\n return this;\n }\n /**\n * Enable/disable a strategy\n */\n setStrategyEnabled(name, enabled) {\n const config = this.strategies.get(name);\n if (config) {\n config.enabled = enabled;\n // If tracking and being disabled, stop it\n if (!enabled && this.isTracking) {\n config.strategy.stop();\n }\n // If tracking and being enabled, start it\n if (enabled && this.isTracking) {\n config.strategy.start();\n }\n }\n return this;\n }\n /**\n * Get all registered strategies\n */\n getStrategies() {\n return this.strategies;\n }\n /**\n * Start tracking\n */\n start() {\n if (this.isTracking)\n return;\n this.isTracking = true;\n // Set up visibility change listener\n if (this.pauseOnHidden && typeof document !== 'undefined') {\n this.visibilityChangeHandler = this.handleVisibilityChange.bind(this);\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n // Check initial visibility state\n if (document.hidden) {\n this.isPausedByVisibility = true;\n return; // Don't start strategies if already hidden\n }\n }\n // Start all enabled strategies\n for (const [_, config] of this.strategies) {\n if (config.enabled) {\n config.strategy.start();\n }\n }\n // Start tick mechanism\n this.startTick();\n }\n /**\n * Stop tracking\n */\n stop() {\n if (!this.isTracking)\n return;\n this.isTracking = false;\n this.isPausedByVisibility = false;\n // Remove visibility change listener\n if (this.visibilityChangeHandler && typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n // Stop all strategies\n for (const [_, config] of this.strategies) {\n config.strategy.stop();\n }\n // Stop tick\n this.stopTick();\n }\n /**\n * Reset all data\n */\n reset() {\n this.confidenceScore = 0;\n for (const [_, config] of this.strategies) {\n config.strategy.reset();\n }\n }\n /**\n * Calculate human likelihood score\n */\n async score(options = {}) {\n const breakdown = this.calculateStrategyScore();\n const result = {\n score: breakdown.overall,\n };\n if (options.breakdown) {\n result.breakdown = breakdown;\n }\n // Note: auditTrail not available in strategy mode\n // Each strategy manages its own data independently\n return result;\n }\n /**\n * Check if currently tracking\n */\n isActive() {\n return this.isTracking;\n }\n /**\n * Check if currently paused due to tab visibility\n */\n isPaused() {\n return this.isPausedByVisibility;\n }\n /**\n * Get event count from all strategies\n */\n getEventCount() {\n var _a, _b;\n const counts = {};\n for (const [name, config] of this.strategies) {\n const debug = (_b = (_a = config.strategy).getDebugInfo) === null || _b === void 0 ? void 0 : _b.call(_a);\n if ((debug === null || debug === void 0 ? void 0 : debug.eventCount) !== undefined) {\n counts[name] = debug.eventCount;\n }\n }\n return counts;\n }\n /**\n * Get debug info from all strategies\n */\n getStrategyDebugInfo() {\n const debug = {};\n for (const [name, config] of this.strategies) {\n if (config.strategy.getDebugInfo) {\n debug[name] = config.strategy.getDebugInfo();\n }\n }\n return debug;\n }\n /**\n * Get current confidence score (0-1)\n * Represents how much interaction data we've collected\n * Higher confidence = more reliable classification\n */\n getConfidence() {\n return Math.min(1, this.confidenceScore);\n }\n /**\n * Check if confidence is above threshold for reliable classification\n * @param threshold - Minimum confidence (0-1), default 0.3\n */\n hasConfidentData(threshold = 0.3) {\n return this.getConfidence() >= threshold;\n }\n /**\n * Cleanup resources\n */\n destroy() {\n this.stop();\n this.strategies.clear();\n }\n /**\n * Handle visibility change events\n */\n handleVisibilityChange() {\n if (!this.isTracking)\n return;\n if (document.hidden) {\n // Tab became hidden - pause detection\n if (!this.isPausedByVisibility) {\n this.isPausedByVisibility = true;\n // Stop all strategies\n for (const [_, config] of this.strategies) {\n if (config.enabled) {\n config.strategy.stop();\n }\n }\n // Stop tick\n this.stopTick();\n }\n }\n else {\n // Tab became visible - resume detection\n if (this.isPausedByVisibility) {\n this.isPausedByVisibility = false;\n // Restart all enabled strategies\n for (const [_, config] of this.strategies) {\n if (config.enabled) {\n config.strategy.start();\n }\n }\n // Restart tick\n this.startTick();\n }\n }\n }\n /**\n * Start tick mechanism for strategies\n */\n startTick() {\n if (this.tickInterval !== null)\n return;\n this.tickInterval = window.setInterval(() => {\n const now = Date.now();\n for (const [_, config] of this.strategies) {\n if (config.enabled && config.strategy.onTick) {\n config.strategy.onTick(now);\n }\n }\n }, this.tickIntervalMs);\n }\n /**\n * Stop tick mechanism\n */\n stopTick() {\n if (this.tickInterval !== null) {\n clearInterval(this.tickInterval);\n this.tickInterval = null;\n }\n }\n /**\n * Calculate score using strategies\n */\n calculateStrategyScore() {\n const factors = {};\n const weights = {};\n let totalWeight = 0;\n let weightedSum = 0;\n for (const [name, config] of this.strategies) {\n if (!config.enabled)\n continue;\n const score = config.strategy.score();\n factors[name] = score;\n weights[name] = config.weight;\n if (score !== undefined && score !== null) {\n totalWeight += config.weight;\n weightedSum += score * config.weight;\n }\n }\n const overall = totalWeight > 0 ? weightedSum / totalWeight : 0.5;\n return {\n overall: Math.max(0, Math.min(1, overall)),\n factors,\n weights,\n };\n }\n}\n", "/**\n * Detection Strategy Interface\n * Each strategy is a fully autonomous module responsible for:\n * - Registering its own event listeners\n * - Managing its own state and events\n * - Responding to lifecycle events (start/stop)\n * - Optionally receiving tick updates for polling-based detection\n */\n/**\n * Base class for detection strategies\n * Handles event callback pattern to avoid repetition\n */\nexport class BaseStrategy {\n constructor() {\n this.eventCallback = null;\n }\n setEventCallback(callback) {\n this.eventCallback = callback;\n }\n notifyEvent(weight) {\n if (this.eventCallback) {\n this.eventCallback({\n strategy: this.name,\n weight,\n timestamp: Date.now()\n });\n }\n }\n}\n", "/**\n * Mathematical utility functions for continuous scoring\n * Replaces magic number if-else chains with smooth mathematical functions\n */\n/**\n * Sigmoid function - Maps any value to [0, 1] with smooth S-curve\n * @param x - Input value\n * @param midpoint - Value that maps to 0.5\n * @param steepness - How steep the curve is (higher = steeper)\n */\nexport function sigmoid(x, midpoint = 0, steepness = 1) {\n return 1 / (1 + Math.exp(-steepness * (x - midpoint)));\n}\n/**\n * Inverse sigmoid - High values map to low scores\n */\nexport function inverseSigmoid(x, midpoint = 0, steepness = 1) {\n return 1 - sigmoid(x, midpoint, steepness);\n}\n/**\n * Gaussian (bell curve) - Peak at ideal value, falls off on both sides\n * @param x - Input value\n * @param ideal - Optimal value (peak of curve)\n * @param width - How wide the acceptable range is\n */\nexport function gaussian(x, ideal = 0, width = 1) {\n const exponent = -Math.pow(x - ideal, 2) / (2 * width * width);\n return Math.exp(exponent);\n}\n/**\n * Exponential decay - High values get penalized exponentially\n */\nexport function exponentialDecay(x, decayRate = 0.1) {\n return Math.exp(-decayRate * x);\n}\n/**\n * Normalize value to [0, 1] range\n */\nexport function normalize(value, min = 0, max = 1) {\n if (max === min)\n return 0.5;\n return Math.max(0, Math.min(1, (value - min) / (max - min)));\n}\n/**\n * Clamp value to [0, 1]\n */\nexport function clamp01(value) {\n return Math.max(0, Math.min(1, value));\n}\n/**\n * Calculate statistical metrics for an array of numbers\n * @param values - Array of numerical values\n * @returns Statistical metrics (mean, variance, stdDev, cv)\n */\nexport function calculateStatistics(values) {\n if (values.length === 0) {\n return { mean: 0, variance: 0, stdDev: 0, cv: 0 };\n }\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / values.length;\n const stdDev = Math.sqrt(variance);\n const cv = mean > 0 ? stdDev / mean : 0;\n return { mean, variance, stdDev, cv };\n}\n/**\n * Analyze timing intervals for bot-like patterns\n * Returns raw analysis data without scoring - caller decides heuristics\n *\n * @param intervals - Array of time intervals (ms)\n * @returns Analysis of interval patterns including stats and uniqueness\n */\nexport function analyzeIntervals(intervals) {\n if (intervals.length < 2)\n return undefined;\n // Check for identical intervals (round to 10ms to account for floating point)\n const uniqueCount = new Set(intervals.map(i => Math.round(i / 10))).size;\n const allIdentical = uniqueCount === 1;\n // Calculate statistics\n const statistics = calculateStatistics(intervals);\n return {\n statistics,\n uniqueCount,\n allIdentical,\n };\n}\n/**\n * Score coefficient of variation\n * Maps CV to human-likeness score using Gaussian\n * Ideal CV is around 0.4-0.5 (moderate variation)\n */\nexport function scoreCoefficientOfVariation(cv) {\n // Too low (<0.1) = bot-like (too consistent)\n // Too high (>1.5) = random noise\n // Ideal = 0.4-0.6 (natural human variation)\n if (cv < 0.05)\n return 0.1; // Almost zero variation - definitely bot\n if (cv > 2.0)\n return 0.3; // Too random\n // Gaussian centered at 0.45 with width of 0.35\n return gaussian(cv, 0.45, 0.35);\n}\n/**\n * Score entropy - Higher is better (more random = more human)\n * Uses sigmoid to smoothly map entropy to score\n */\nexport function scoreEntropy(normalizedEntropy) {\n // Entropy of 0.7+ is very human\n // Entropy < 0.3 is very bot-like\n return sigmoid(normalizedEntropy, 0.5, 8); // Steep curve at midpoint 0.5\n}\n/**\n * Score autocorrelation - Lower is better (less periodic = more human)\n */\nexport function scoreAutocorrelation(autocorr) {\n // Low autocorrelation (<0.2) is natural\n // High autocorrelation (>0.6) is periodic/bot-like\n return inverseSigmoid(autocorr, 0.4, 10);\n}\n/**\n * Score jerk - Lower is better (smoother = more human)\n */\nexport function scoreJerk(avgJerk) {\n // Human jerk typically < 0.01\n // Bot jerk often > 0.1\n // Use inverse sigmoid\n return inverseSigmoid(avgJerk, 0.05, 50);\n}\n", "/**\n * Mouse Movement Detection Strategy\n * Autonomous module that manages its own mouse event listeners and state\n * Tracks distance and angle to detect unnatural jumps and sharp turns\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { calculateStatistics, gaussian } from '../math-utils.js';\nexport class MouseStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'mouse';\n this.defaultWeight = 0.30;\n this.distanceSeries = [];\n this.angleSeries = [];\n this.lastPosition = null;\n this.lastAngle = 0;\n this.cumulativeAngle = 0;\n this.rollingWindowMs = 5000;\n this.listener = null;\n this.leaveListener = null;\n this.isActive = false;\n this.screenDiagonal = 1;\n if ((options === null || options === void 0 ? void 0 : options.rollingWindow) !== undefined)\n this.rollingWindowMs = options.rollingWindow;\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Calculate screen diagonal for normalization (distance relative to screen size)\n const width = window.innerWidth;\n const height = window.innerHeight;\n this.screenDiagonal = Math.sqrt(width * width + height * height);\n this.listener = (e) => {\n const mouseEvent = e;\n const now = Date.now();\n const currentPos = { x: mouseEvent.clientX, y: mouseEvent.clientY };\n // Calculate distance and angle from previous position\n if (this.lastPosition) {\n const dx = currentPos.x - this.lastPosition.x;\n const dy = currentPos.y - this.lastPosition.y;\n const pixelDistance = Math.sqrt(dx * dx + dy * dy);\n // Normalize distance to screen diagonal (0-1 range)\n // A full diagonal movement = 1.0, a 10px movement on 2000px screen = 0.005\n const normalizedDistance = pixelDistance / this.screenDiagonal;\n // Only record if movement is meaningful (> 0.001 = ~2px on 2000px screen)\n if (normalizedDistance > 0.001) {\n const rawAngle = Math.atan2(dy, dx); // -PI to PI\n // Unwrap angle to avoid discontinuities (e.g., circles)\n let angleDiff = rawAngle - this.lastAngle;\n // Normalize difference to -PI to PI\n while (angleDiff > Math.PI)\n angleDiff -= 2 * Math.PI;\n while (angleDiff < -Math.PI)\n angleDiff += 2 * Math.PI;\n this.cumulativeAngle += angleDiff;\n this.lastAngle = rawAngle;\n // Store normalized distance (not raw pixels)\n this.distanceSeries.push({ value: normalizedDistance, timestamp: now });\n this.angleSeries.push({ value: this.cumulativeAngle, timestamp: now });\n // Notify detector for confidence tracking\n this.notifyEvent(Math.min(1, normalizedDistance * 100));\n }\n // Apply rolling window efficiently: remove old events from start\n // Since events are chronological, we only check from the beginning\n const cutoff = now - this.rollingWindowMs;\n while (this.distanceSeries.length > 0 && this.distanceSeries[0].timestamp < cutoff) {\n this.distanceSeries.shift();\n this.angleSeries.shift(); // Keep both arrays in sync\n }\n }\n this.lastPosition = currentPos;\n };\n document.addEventListener('mousemove', this.listener, { passive: true });\n // Clear data when mouse leaves the window (discontinuous tracking)\n this.leaveListener = () => {\n this.distanceSeries = [];\n this.angleSeries = [];\n this.lastPosition = null;\n this.lastAngle = 0;\n this.cumulativeAngle = 0;\n };\n document.addEventListener('mouseleave', this.leaveListener, { passive: true });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.listener) {\n document.removeEventListener('mousemove', this.listener);\n this.listener = null;\n }\n if (this.leaveListener) {\n document.removeEventListener('mouseleave', this.leaveListener);\n this.leaveListener = null;\n }\n }\n reset() {\n this.distanceSeries = [];\n this.angleSeries = [];\n this.lastPosition = null;\n this.lastAngle = 0;\n this.cumulativeAngle = 0;\n }\n score() {\n if (this.distanceSeries.length < 10)\n return undefined;\n // Mouse-specific pattern detection (optimized for normalized continuous data)\n // Generic smoothness detector is calibrated for discrete events, not continuous movement\n return this.detectMousePatterns();\n }\n /**\n * Mouse-specific pattern detection\n * Detects bot-like patterns: constant velocity, linear paths\n */\n detectMousePatterns() {\n if (this.distanceSeries.length < 10)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. VELOCITY CONSISTENCY - Bots often move at constant speed\n const distances = this.distanceSeries.map(p => p.value);\n if (distances.length >= 3) {\n const stats = calculateStatistics(distances);\n // Real human movement has high variation (CV ~0.8-1.2)\n // page.mouse.move() with steps has lower CV (~0.4-0.6)\n // Narrower gaussian to be strict\n score += gaussian(stats.cv, 0.9, 0.35);\n factors++;\n }\n // 2. DIRECTION CHANGES - Bots often have too few or too many sharp turns\n const angles = this.angleSeries.map(p => p.value);\n if (angles.length >= 3) {\n const angleChanges = [];\n for (let i = 1; i < angles.length; i++) {\n angleChanges.push(Math.abs(angles[i] - angles[i - 1]));\n }\n const avgChange = angleChanges.reduce((a, b) => a + b, 0) / angleChanges.length;\n // Real humans have moderate but varied direction changes\n // page.mouse.move() linear interpolation has very small, consistent changes\n score += gaussian(avgChange, 0.15, 0.12);\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.distanceSeries.length,\n rollingWindow: this.rollingWindowMs,\n isActive: this.isActive,\n distanceSeries: this.distanceSeries,\n angleSeries: this.angleSeries,\n };\n }\n}\n", "/**\n * Scroll Behavior Detection Strategy\n * Autonomous module managing scroll event listeners\n * Tracks normalized scroll distance and velocity patterns\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { calculateStatistics, gaussian, inverseSigmoid } from '../math-utils.js';\nexport class ScrollStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'scroll';\n this.defaultWeight = 0.15;\n this.distanceSeries = [];\n this.velocitySeries = [];\n this.lastScrollY = null;\n this.lastTimestamp = 0;\n this.rollingWindowMs = 5000;\n this.documentHeight = 1;\n this.listener = null;\n this.isActive = false;\n if ((options === null || options === void 0 ? void 0 : options.rollingWindow) !== undefined)\n this.rollingWindowMs = options.rollingWindow;\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Calculate document height for normalization\n this.documentHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, 1);\n this.listener = (_e) => {\n const scrollY = window.scrollY;\n const now = Date.now();\n // Always update last position on first event\n if (this.lastScrollY === null) {\n this.lastScrollY = scrollY;\n this.lastTimestamp = now;\n return;\n }\n const pixelDelta = scrollY - this.lastScrollY;\n const deltaTime = now - this.lastTimestamp;\n // Skip if no actual scroll happened\n if (pixelDelta === 0) {\n return;\n }\n // Normalize scroll distance to document height (0-1 range)\n const normalizedDistance = Math.abs(pixelDelta) / this.documentHeight;\n // Record all scroll movements (no threshold - let pattern detection decide)\n if (deltaTime > 0) {\n const velocity = normalizedDistance / deltaTime; // normalized units per ms\n // Store as time series\n this.distanceSeries.push({ value: normalizedDistance, timestamp: now });\n this.velocitySeries.push({ value: velocity, timestamp: now });\n // Notify detector for confidence tracking\n this.notifyEvent(Math.min(1, normalizedDistance * 10));\n // Apply rolling window efficiently\n const cutoff = now - this.rollingWindowMs;\n while (this.distanceSeries.length > 0 && this.distanceSeries[0].timestamp < cutoff) {\n this.distanceSeries.shift();\n this.velocitySeries.shift();\n }\n }\n this.lastScrollY = scrollY;\n this.lastTimestamp = now;\n };\n // Listen on window for scroll events (document scrolling)\n window.addEventListener('scroll', this.listener, { passive: true });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.listener) {\n window.removeEventListener('scroll', this.listener);\n this.listener = null;\n }\n }\n reset() {\n this.distanceSeries = [];\n this.velocitySeries = [];\n this.lastScrollY = null;\n this.lastTimestamp = 0;\n }\n score() {\n if (this.distanceSeries.length < 2)\n return undefined;\n // Scroll-specific pattern detection\n return this.detectScrollPatterns();\n }\n /**\n * Scroll-specific pattern detection\n * Detects bot-like patterns: constant deltas, instant jumps, too smooth\n */\n detectScrollPatterns() {\n if (this.distanceSeries.length < 2)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. IDENTICAL DELTAS - Smoking gun for bots\n const distances = this.distanceSeries.map(p => p.value);\n if (distances.length >= 2) {\n // Check if all distances are identical (tolerance for floating point)\n const uniqueDistances = new Set(distances.map(d => Math.round(d * 1000))).size;\n if (uniqueDistances === 1) {\n // All scroll amounts identical = definite bot\n return 0.05;\n }\n }\n // 2. DISTANCE CONSISTENCY - Bots often scroll same amount repeatedly\n if (distances.length >= 2) {\n const stats = calculateStatistics(distances);\n // Real humans have high CV (>0.8) due to natural scroll acceleration/deceleration\n // Simple automation has lower CV even with varied amounts\n // Gaussian centered high with narrow width - be strict\n score += gaussian(stats.cv, 1.0, 0.4);\n factors++;\n }\n // 3. VELOCITY VARIATION - Humans have highly variable scroll speeds\n const velocities = this.velocitySeries.map(p => p.value);\n if (velocities.length >= 2) {\n const stats = calculateStatistics(velocities);\n // Human velocity is very chaotic (acceleration/deceleration)\n // Automation has more consistent velocity even with delays\n score += gaussian(stats.cv, 1.2, 0.5);\n factors++;\n }\n // 4. INSTANT JUMPS - Detect programmatic scrollTo\n const instantJumps = distances.filter(d => d > 0.1).length; // >10% of document in one event\n if (distances.length > 0) {\n const jumpRatio = instantJumps / distances.length;\n // Penalize high jump ratio (programmatic scrollTo)\n score += inverseSigmoid(jumpRatio, 0.3, 15);\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.distanceSeries.length,\n rollingWindow: this.rollingWindowMs,\n isActive: this.isActive,\n distanceSeries: this.distanceSeries,\n velocitySeries: this.velocitySeries,\n };\n }\n}\n", "/**\n * Click Behavior Detection Strategy\n * Monitors specific elements for click positioning patterns\n */\nimport { BaseStrategy } from '../strategy.js';\nexport class ClickStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'click';\n this.defaultWeight = 0.30;\n this.events = [];\n this.targetSelectors = ['button', 'a', 'input[type=\"submit\"]', '[role=\"button\"]'];\n this.lastMousePosition = null;\n this.mouseListener = null;\n this.clickListeners = new Map();\n this.isActive = false;\n if (options === null || options === void 0 ? void 0 : options.targetSelectors) {\n this.targetSelectors = options.targetSelectors;\n }\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Track mouse position globally\n this.mouseListener = (e) => {\n const mouseEvent = e;\n this.lastMousePosition = {\n x: mouseEvent.clientX,\n y: mouseEvent.clientY,\n };\n };\n document.addEventListener('mousemove', this.mouseListener, { passive: true });\n // Find all matching elements and attach listeners\n this.attachClickListeners();\n }\n /**\n * Add a new target selector at runtime\n */\n addTarget(selector) {\n if (!this.targetSelectors.includes(selector)) {\n this.targetSelectors.push(selector);\n // Attach listeners if already active\n if (this.isActive) {\n this.attachClickListenersForSelector(selector);\n }\n }\n }\n attachClickListeners() {\n this.targetSelectors.forEach(selector => {\n this.attachClickListenersForSelector(selector);\n });\n }\n attachClickListenersForSelector(selector) {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (this.clickListeners.has(element))\n return; // Already attached\n const listener = (e) => {\n var _a, _b;\n const clickEvent = e;\n const rect = element.getBoundingClientRect();\n // Check if element is in viewport\n const inViewport = (rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= window.innerHeight &&\n rect.right <= window.innerWidth);\n // Analyze click position\n let position;\n if (!this.lastMousePosition) {\n position = 'no-mouse-data'; // Bot - no mouse movement\n }\n else {\n const mx = this.lastMousePosition.x;\n const my = this.lastMousePosition.y;\n // Check if mouse was over element\n const overElement = (mx >= rect.left &&\n mx <= rect.right &&\n my >= rect.top &&\n my <= rect.bottom);\n if (!overElement) {\n position = 'outside'; // Bot - mouse not over target\n }\n else {\n // Check if dead center (suspicious)\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const distanceFromCenter = Math.sqrt((mx - centerX) ** 2 + (my - centerY) ** 2);\n // Dead center = within 2px of center\n if (distanceFromCenter < 2) {\n position = 'dead-center'; // Suspicious - too perfect\n }\n else {\n position = 'over-element'; // Human - somewhere on the button\n }\n }\n }\n this.events.push({\n clickX: clickEvent.clientX,\n clickY: clickEvent.clientY,\n mouseX: (_a = this.lastMousePosition) === null || _a === void 0 ? void 0 : _a.x,\n mouseY: (_b = this.lastMousePosition) === null || _b === void 0 ? void 0 : _b.y,\n rect,\n inViewport,\n position,\n timestamp: Date.now(),\n });\n // Notify detector - clicks are high-value events\n this.notifyEvent(1.0);\n };\n element.addEventListener('click', listener);\n this.clickListeners.set(element, listener);\n });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n // Remove mouse listener\n if (this.mouseListener) {\n document.removeEventListener('mousemove', this.mouseListener);\n this.mouseListener = null;\n }\n // Remove all click listeners\n this.clickListeners.forEach((listener, element) => {\n element.removeEventListener('click', listener);\n });\n this.clickListeners.clear();\n }\n reset() {\n this.events = [];\n this.lastMousePosition = null;\n }\n score() {\n if (this.events.length === 0)\n return undefined;\n let totalScore = 0;\n for (const click of this.events) {\n switch (click.position) {\n case 'no-mouse-data':\n totalScore += 0.0; // Bot - no mouse movement\n break;\n case 'outside':\n totalScore += 0.0; // Bot - mouse not over target\n break;\n case 'dead-center':\n totalScore += 0.5; // Suspicious - too perfect\n break;\n case 'over-element':\n totalScore += 1.0; // Human - natural click\n break;\n }\n }\n return totalScore / this.events.length;\n }\n getDebugInfo() {\n return {\n eventCount: this.events.length,\n positions: {\n noMouseData: this.events.filter(e => e.position === 'no-mouse-data').length,\n outside: this.events.filter(e => e.position === 'outside').length,\n deadCenter: this.events.filter(e => e.position === 'dead-center').length,\n overElement: this.events.filter(e => e.position === 'over-element').length,\n },\n inViewport: this.events.filter(e => e.inViewport).length,\n trackedElements: this.clickListeners.size,\n };\n }\n}\n", "/**\n * Tap Behavior Detection Strategy (Mobile)\n * Monitors touch interactions on specific elements\n * Analyzes tap duration, precision, movement, and timing patterns\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { analyzeIntervals, scoreCoefficientOfVariation, gaussian } from '../math-utils.js';\nexport class TapStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'tap';\n this.defaultWeight = 0.35;\n this.events = [];\n this.targetSelectors = ['button', 'a', 'input[type=\"submit\"]', '[role=\"button\"]'];\n this.touchStartListeners = new Map();\n this.touchEndListeners = new Map();\n this.activeTouches = new Map();\n this.isActive = false;\n if (options === null || options === void 0 ? void 0 : options.targetSelectors) {\n this.targetSelectors = options.targetSelectors;\n }\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n this.attachTouchListeners();\n }\n addTarget(selector) {\n if (!this.targetSelectors.includes(selector)) {\n this.targetSelectors.push(selector);\n if (this.isActive) {\n this.attachTouchListenersForSelector(selector);\n }\n }\n }\n attachTouchListeners() {\n this.targetSelectors.forEach(selector => {\n this.attachTouchListenersForSelector(selector);\n });\n }\n attachTouchListenersForSelector(selector) {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (this.touchStartListeners.has(element))\n return;\n const startListener = (e) => {\n const touchEvent = e;\n // Only track first touch (ignore multi-touch)\n if (touchEvent.touches.length !== 1)\n return;\n const touch = touchEvent.touches[0];\n this.activeTouches.set(touch.identifier, {\n x: touch.clientX,\n y: touch.clientY,\n timestamp: Date.now(),\n element,\n });\n };\n const endListener = (e) => {\n const touchEvent = e;\n if (touchEvent.changedTouches.length !== 1)\n return;\n const touch = touchEvent.changedTouches[0];\n const startData = this.activeTouches.get(touch.identifier);\n if (!startData || startData.element !== element)\n return;\n const now = Date.now();\n const duration = now - startData.timestamp;\n const dx = touch.clientX - startData.x;\n const dy = touch.clientY - startData.y;\n const movement = Math.sqrt(dx * dx + dy * dy);\n const rect = element.getBoundingClientRect();\n const inViewport = (rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= window.innerHeight &&\n rect.right <= window.innerWidth);\n // Analyze tap position\n const tx = touch.clientX;\n const ty = touch.clientY;\n const overElement = (tx >= rect.left &&\n tx <= rect.right &&\n ty >= rect.top &&\n ty <= rect.bottom);\n let position;\n if (!overElement) {\n position = 'outside';\n }\n else {\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const distanceFromCenter = Math.sqrt((tx - centerX) ** 2 + (ty - centerY) ** 2);\n // Dead center = within 2px\n position = distanceFromCenter < 2 ? 'dead-center' : 'over-element';\n }\n this.events.push({\n x: tx,\n y: ty,\n rect,\n inViewport,\n position,\n duration,\n movement,\n timestamp: now,\n });\n // Notify detector - taps are high-value events\n this.notifyEvent(1.0);\n this.activeTouches.delete(touch.identifier);\n };\n element.addEventListener('touchstart', startListener, { passive: true });\n element.addEventListener('touchend', endListener, { passive: true });\n this.touchStartListeners.set(element, startListener);\n this.touchEndListeners.set(element, endListener);\n });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n this.touchStartListeners.forEach((listener, element) => {\n element.removeEventListener('touchstart', listener);\n });\n this.touchStartListeners.clear();\n this.touchEndListeners.forEach((listener, element) => {\n element.removeEventListener('touchend', listener);\n });\n this.touchEndListeners.clear();\n this.activeTouches.clear();\n }\n reset() {\n this.events = [];\n this.activeTouches.clear();\n }\n score() {\n if (this.events.length === 0)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. Position accuracy\n let positionScore = 0;\n for (const tap of this.events) {\n switch (tap.position) {\n case 'outside':\n positionScore += 0.0; // Bot\n break;\n case 'dead-center':\n positionScore += 0.5; // Suspicious\n break;\n case 'over-element':\n positionScore += 1.0; // Human\n break;\n }\n }\n score += positionScore / this.events.length;\n factors++;\n // 2. Tap duration variation - Humans have natural variation (50-150ms typical)\n const durations = this.events.map(e => e.duration);\n if (durations.length >= 2) {\n const durationAnalysis = analyzeIntervals(durations);\n if (durationAnalysis) {\n const { statistics, allIdentical } = durationAnalysis;\n // All identical = bot\n if (allIdentical) {\n return 0.05;\n }\n // Human tap durations have moderate CV (~0.3-0.5)\n score += scoreCoefficientOfVariation(statistics.cv);\n factors++;\n // Ideal duration: 70-120ms\n score += gaussian(statistics.mean, 95, 40);\n factors++;\n }\n }\n // 3. Tap movement - Real fingers move slightly (1-5px), bots are often 0px\n const movements = this.events.map(e => e.movement);\n if (movements.length > 0) {\n const avgMovement = movements.reduce((a, b) => a + b, 0) / movements.length;\n // Some movement is natural (1-5px), too much is a swipe, zero is suspicious\n score += gaussian(avgMovement, 2, 3);\n factors++;\n }\n // 4. Tap interval timing - Time between taps should vary naturally\n if (this.events.length >= 3) {\n const intervals = [];\n for (let i = 1; i < this.events.length; i++) {\n intervals.push(this.events[i].timestamp - this.events[i - 1].timestamp);\n }\n const intervalAnalysis = analyzeIntervals(intervals);\n if (intervalAnalysis && !intervalAnalysis.allIdentical) {\n score += scoreCoefficientOfVariation(intervalAnalysis.statistics.cv);\n factors++;\n }\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.events.length,\n positions: {\n outside: this.events.filter(e => e.position === 'outside').length,\n deadCenter: this.events.filter(e => e.position === 'dead-center').length,\n overElement: this.events.filter(e => e.position === 'over-element').length,\n },\n durations: this.events.map(e => e.duration),\n movements: this.events.map(e => e.movement),\n inViewport: this.events.filter(e => e.inViewport).length,\n trackedElements: this.touchStartListeners.size,\n };\n }\n}\n", "/**\n * Keyboard Timing Detection Strategy\n * Monitors typing in specific input fields\n * Analyzes keydown/keyup timing and micro-variations\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { analyzeIntervals, scoreCoefficientOfVariation } from '../math-utils.js';\nexport class KeyboardStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'keyboard';\n this.defaultWeight = 0.10;\n this.events = [];\n this.targetSelectors = ['input[type=\"text\"]', 'input[type=\"email\"]', 'textarea'];\n this.focusedElement = null;\n this.focusedElementSelector = '';\n this.lastEventTimestamp = 0;\n this.sessionPauseThreshold = 1000;\n this.downListener = null;\n this.upListener = null;\n this.focusListeners = new Map();\n this.blurListeners = new Map();\n this.isActive = false;\n if (options === null || options === void 0 ? void 0 : options.targetSelectors) {\n this.targetSelectors = options.targetSelectors;\n }\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Attach focus/blur listeners to all matching elements\n this.attachFocusListeners();\n // Key event listeners (only track when an input is focused)\n this.downListener = (e) => {\n if (!this.focusedElement)\n return; // No input focused\n const now = Date.now();\n const keyEvent = e;\n // Clear events if pause > 1s (new typing session)\n if (this.lastEventTimestamp > 0 && now - this.lastEventTimestamp > this.sessionPauseThreshold) {\n this.events = [];\n }\n this.events.push({\n key: keyEvent.key,\n type: 'down',\n timestamp: now,\n targetElement: this.focusedElementSelector,\n });\n // Notify detector - keystrokes are valuable events\n this.notifyEvent(0.8);\n this.lastEventTimestamp = now;\n };\n this.upListener = (e) => {\n if (!this.focusedElement)\n return; // No input focused\n const now = Date.now();\n const keyEvent = e;\n // Clear events if pause > 1s (new typing session)\n if (this.lastEventTimestamp > 0 && now - this.lastEventTimestamp > this.sessionPauseThreshold) {\n this.events = [];\n }\n this.events.push({\n key: keyEvent.key,\n type: 'up',\n timestamp: now,\n targetElement: this.focusedElementSelector,\n });\n this.lastEventTimestamp = now;\n };\n document.addEventListener('keydown', this.downListener);\n document.addEventListener('keyup', this.upListener);\n }\n /**\n * Add a new target selector at runtime\n */\n addTarget(selector) {\n if (!this.targetSelectors.includes(selector)) {\n this.targetSelectors.push(selector);\n if (this.isActive) {\n this.attachFocusListenersForSelector(selector);\n }\n }\n }\n attachFocusListeners() {\n this.targetSelectors.forEach(selector => {\n this.attachFocusListenersForSelector(selector);\n });\n }\n attachFocusListenersForSelector(selector) {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (this.focusListeners.has(element))\n return; // Already attached\n const focusListener = () => {\n this.focusedElement = element;\n this.focusedElementSelector = selector;\n };\n const blurListener = () => {\n this.focusedElement = null;\n this.focusedElementSelector = '';\n };\n element.addEventListener('focus', focusListener);\n element.addEventListener('blur', blurListener);\n this.focusListeners.set(element, focusListener);\n this.blurListeners.set(element, blurListener);\n });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.downListener) {\n document.removeEventListener('keydown', this.downListener);\n this.downListener = null;\n }\n if (this.upListener) {\n document.removeEventListener('keyup', this.upListener);\n this.upListener = null;\n }\n // Remove focus/blur listeners\n this.focusListeners.forEach((listener, element) => {\n element.removeEventListener('focus', listener);\n });\n this.focusListeners.clear();\n this.blurListeners.forEach((listener, element) => {\n element.removeEventListener('blur', listener);\n });\n this.blurListeners.clear();\n this.focusedElement = null;\n }\n reset() {\n this.events = [];\n this.focusedElement = null;\n this.focusedElementSelector = '';\n this.lastEventTimestamp = 0;\n }\n score() {\n if (this.events.length < 6)\n return undefined; // Need at least 3 key pairs\n const downEvents = this.events.filter(e => e.type === 'down');\n if (downEvents.length < 3)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. Analyze keystroke intervals (time between keydown events)\n const keystrokeIntervals = [];\n for (let i = 1; i < downEvents.length; i++) {\n keystrokeIntervals.push(downEvents[i].timestamp - downEvents[i - 1].timestamp);\n }\n const keystrokeAnalysis = analyzeIntervals(keystrokeIntervals);\n if (keystrokeAnalysis) {\n const { statistics, allIdentical } = keystrokeAnalysis;\n // Keyboard-specific heuristics for keystroke timing\n if (allIdentical) {\n return 0.1; // All identical - bot!\n }\n const keystrokeScore = scoreCoefficientOfVariation(statistics.cv);\n score += keystrokeScore;\n factors++;\n // Early return if bot detected\n if (keystrokeScore <= 0.1)\n return keystrokeScore;\n }\n // 2. Analyze press durations (keydown-to-keyup duration)\n const pressDurations = [];\n for (let i = 0; i < this.events.length - 1; i++) {\n if (this.events[i].type === 'down' && this.events[i + 1].type === 'up' &&\n this.events[i].key === this.events[i + 1].key) {\n pressDurations.push(this.events[i + 1].timestamp - this.events[i].timestamp);\n }\n }\n const pressDurationAnalysis = analyzeIntervals(pressDurations);\n if (pressDurationAnalysis) {\n const { statistics, allIdentical } = pressDurationAnalysis;\n // Keyboard-specific heuristics for press duration\n if (allIdentical) {\n return 0.1; // All identical - bot!\n }\n // Check for suspiciously fast key releases (bots often have <5ms press duration)\n if (statistics.mean < 5) {\n score += 0.1; // Too fast = bot (instant release)\n factors++;\n }\n else {\n const pressDurationScore = scoreCoefficientOfVariation(statistics.cv);\n score += pressDurationScore;\n factors++;\n // Early return if bot detected\n if (pressDurationScore <= 0.1)\n return pressDurationScore;\n }\n }\n // 3. Bonus for backspace usage (human error correction)\n const backspaceCount = this.events.filter(e => e.key === 'Backspace').length;\n if (backspaceCount > 0) {\n // Natural human behavior - making corrections\n const backspaceRatio = backspaceCount / downEvents.length;\n if (backspaceRatio > 0.05 && backspaceRatio < 0.3) {\n score += 1.0; // Reasonable error correction\n factors++;\n }\n else if (backspaceRatio > 0) {\n score += 0.8; // Some backspaces\n factors++;\n }\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n // Calculate press durations for visualization\n const pressDurations = [];\n for (let i = 0; i < this.events.length - 1; i++) {\n if (this.events[i].type === 'down' && this.events[i + 1].type === 'up' &&\n this.events[i].key === this.events[i + 1].key) {\n pressDurations.push(this.events[i + 1].timestamp - this.events[i].timestamp);\n }\n }\n return {\n eventCount: this.events.length,\n downEvents: this.events.filter(e => e.type === 'down').length,\n upEvents: this.events.filter(e => e.type === 'up').length,\n backspaceCount: this.events.filter(e => e.key === 'Backspace').length,\n pressDurations, // For graphing\n focusedElement: this.focusedElementSelector,\n trackedElements: this.focusListeners.size,\n };\n }\n}\n", "/**\n * Environment Fingerprinting Strategy\n * Captures browser environment on initialization and tick updates\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { inverseSigmoid, gaussian } from '../math-utils.js';\nexport class EnvironmentStrategy extends BaseStrategy {\n constructor() {\n super(...arguments);\n this.name = 'environment';\n this.defaultWeight = 0.08;\n this.data = null;\n }\n start() {\n this.captureEnvironment();\n }\n stop() {\n // Environment data persists\n }\n reset() {\n this.data = null;\n }\n onTick(_timestamp) {\n // Re-capture environment periodically to detect changes\n this.captureEnvironment();\n }\n score() {\n if (!this.data)\n return undefined;\n const env = this.data;\n let score = 0;\n let factors = 0;\n // Suspicious indicators\n score += env.suspiciousDimensions ? 0.1 : 1.0;\n score += env.suspiciousRatio ? 0.2 : 1.0;\n score += env.featureInconsistency ? 0.3 : 1.0;\n factors += 3;\n // Browser features\n const featureCount = [\n env.hasWebGL,\n env.hasLocalStorage,\n env.hasSessionStorage,\n env.hasIndexedDB,\n ].filter(Boolean).length;\n score += featureCount / 4;\n factors++;\n // Plugins\n score += inverseSigmoid(env.plugins, -2, -0.5);\n score += (env.plugins > 0 ? 1.0 : 0.1);\n factors += 2;\n // Device\n score += gaussian(env.devicePixelRatio, 2, 1.5);\n score += (env.colorDepth === 24 || env.colorDepth === 32) ? 1.0 : 0.4;\n factors += 2;\n return factors > 0 ? score / factors : undefined;\n }\n isMobileDevice() {\n // Multiple checks for mobile detection\n const hasTouchScreen = navigator.maxTouchPoints > 0 || 'ontouchstart' in window;\n const mobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n const smallScreen = window.innerWidth < 768 && window.innerHeight < 1024;\n return (hasTouchScreen && smallScreen) || mobileUA;\n }\n captureEnvironment() {\n try {\n // WebGL detection\n let hasWebGL = false;\n try {\n const canvas = document.createElement('canvas');\n hasWebGL = !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));\n }\n catch (e) {\n hasWebGL = false;\n }\n // WebRTC detection\n const hasWebRTC = !!(window.RTCPeerConnection ||\n window.mozRTCPeerConnection ||\n window.webkitRTCPeerConnection);\n // Mobile detection\n const isMobile = this.isMobileDevice();\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const screenWidth = window.screen.width;\n const screenHeight = window.screen.height;\n // Suspicious dimensions\n const suspiciousDimensions = (windowWidth === 800 && windowHeight === 600) ||\n (windowWidth === 1024 && windowHeight === 768) ||\n (windowWidth === 1280 && windowHeight === 720) ||\n (screenWidth === 800 && screenHeight === 600);\n // Suspicious ratio\n const windowScreenRatio = (windowWidth * windowHeight) / (screenWidth * screenHeight);\n const suspiciousRatio = windowScreenRatio === 1.0 ||\n windowScreenRatio < 0.1 ||\n windowScreenRatio > 1.0;\n // Feature inconsistency\n const hasStorage = typeof localStorage !== 'undefined' && typeof sessionStorage !== 'undefined';\n const featureInconsistency = (navigator.plugins.length === 0 && navigator.mimeTypes.length === 0) ||\n !hasWebGL ||\n !hasStorage;\n this.data = {\n screenWidth,\n screenHeight,\n windowWidth,\n windowHeight,\n devicePixelRatio: window.devicePixelRatio,\n colorDepth: window.screen.colorDepth,\n userAgent: navigator.userAgent,\n platform: navigator.platform,\n language: navigator.language,\n languages: navigator.languages ? Array.from(navigator.languages) : [navigator.language],\n hardwareConcurrency: navigator.hardwareConcurrency,\n maxTouchPoints: navigator.maxTouchPoints || 0,\n vendor: navigator.vendor,\n hasWebGL,\n hasWebRTC,\n hasLocalStorage: typeof localStorage !== 'undefined',\n hasSessionStorage: typeof sessionStorage !== 'undefined',\n hasIndexedDB: 'indexedDB' in window,\n plugins: navigator.plugins.length,\n mimeTypes: navigator.mimeTypes.length,\n suspiciousRatio,\n suspiciousDimensions,\n featureInconsistency,\n isMobile,\n timestamp: Date.now(),\n };\n }\n catch (error) {\n console.warn('Failed to capture environment:', error);\n }\n }\n getDebugInfo() {\n return this.data;\n }\n /**\n * Check if current device is mobile\n * Returns true if mobile, false otherwise\n * Returns null if environment hasn't been captured yet\n */\n isMobile() {\n var _a, _b;\n return (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.isMobile) !== null && _b !== void 0 ? _b : null;\n }\n}\n", "/**\n * Resize Behavior Detection Strategy\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { inverseSigmoid, sigmoid } from '../math-utils.js';\nexport class ResizeStrategy extends BaseStrategy {\n constructor() {\n super(...arguments);\n this.name = 'resize';\n this.defaultWeight = 0.02;\n this.events = [];\n this.listener = null;\n this.isActive = false;\n this.lastMousePosition = null;\n this.mouseListener = null;\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Track mouse for resize detection\n this.mouseListener = (e) => {\n const mouseEvent = e;\n this.lastMousePosition = {\n x: mouseEvent.clientX,\n y: mouseEvent.clientY,\n };\n };\n document.addEventListener('mousemove', this.mouseListener, { passive: true });\n // Track resizes\n this.listener = () => {\n var _a, _b;\n const mouseX = (_a = this.lastMousePosition) === null || _a === void 0 ? void 0 : _a.x;\n const mouseY = (_b = this.lastMousePosition) === null || _b === void 0 ? void 0 : _b.y;\n let mouseNearEdge = false;\n if (mouseX !== undefined && mouseY !== undefined) {\n const edgeThreshold = 50;\n mouseNearEdge = (mouseX < edgeThreshold ||\n mouseX > window.innerWidth - edgeThreshold ||\n mouseY < edgeThreshold ||\n mouseY > window.innerHeight - edgeThreshold);\n }\n this.events.push({\n width: window.innerWidth,\n height: window.innerHeight,\n mouseX,\n mouseY,\n mouseNearEdge,\n timestamp: Date.now(),\n });\n };\n window.addEventListener('resize', this.listener);\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.listener) {\n window.removeEventListener('resize', this.listener);\n this.listener = null;\n }\n if (this.mouseListener) {\n document.removeEventListener('mousemove', this.mouseListener);\n this.mouseListener = null;\n }\n }\n reset() {\n this.events = [];\n }\n score() {\n if (this.events.length === 0)\n return undefined;\n let score = 0;\n let factors = 0;\n // Frequency\n score += inverseSigmoid(this.events.length, 5, 0.5);\n factors++;\n // Mouse near edge\n const withMouse = this.events.filter(e => e.mouseX !== undefined);\n if (withMouse.length > 0) {\n const nearEdge = withMouse.filter(e => e.mouseNearEdge).length;\n score += sigmoid(nearEdge / withMouse.length, 0.5, 8);\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.events.length,\n withMouseData: this.events.filter(e => e.mouseX !== undefined).length,\n };\n }\n}\n", "export const DEFAULT_SETTINGS = {\n sampleRates: {\n mouseMove: 0.1, // Track 10% of mouse moves\n scroll: 1.0, // Track ALL scrolls - critical for detection\n keypress: 1.0, // Track all keypresses\n },\n rollingWindows: {\n mouseMove: 30000,\n scroll: 30000,\n },\n weights: {\n mouseMovement: 0.30, // Increased - continuous behavioral signal\n clickAccuracy: 0.30, // Increased - critical behavioral signal\n scrollBehavior: 0.15, // Unchanged\n keyboardTiming: 0.10, // Slightly reduced\n tabActivity: 0.05, // Unchanged\n resizeBehavior: 0.02, // Reduced - less reliable\n environmentFingerprint: 0.08, // Reduced - static signal, one-time check\n },\n customScorers: {},\n clickMouseHistoryWindow: 1000,\n useWebWorker: false, // Will implement Web Worker support in phase 2\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["BehaviorDetector", "tickOptions", "strategy", "weight", "config", "event", "strategyWeight", "contribution", "name", "enabled", "_", "options", "breakdown", "result", "_a", "_b", "counts", "debug", "threshold", "now", "factors", "weights", "totalWeight", "weightedSum", "score", "overall", "BaseStrategy", "callback", "weight", "sigmoid", "x", "midpoint", "steepness", "inverseSigmoid", "gaussian", "ideal", "width", "exponent", "calculateStatistics", "values", "mean", "a", "b", "variance", "sum", "v", "stdDev", "cv", "analyzeIntervals", "intervals", "uniqueCount", "i", "allIdentical", "scoreCoefficientOfVariation", "gaussian", "MouseStrategy", "BaseStrategy", "options", "width", "height", "e", "mouseEvent", "now", "currentPos", "dx", "dy", "normalizedDistance", "rawAngle", "angleDiff", "cutoff", "score", "factors", "distances", "p", "stats", "calculateStatistics", "gaussian", "angles", "angleChanges", "i", "avgChange", "b", "ScrollStrategy", "BaseStrategy", "options", "_e", "scrollY", "now", "pixelDelta", "deltaTime", "normalizedDistance", "velocity", "cutoff", "score", "factors", "distances", "p", "d", "stats", "calculateStatistics", "gaussian", "velocities", "instantJumps", "jumpRatio", "inverseSigmoid", "ClickStrategy", "BaseStrategy", "options", "
|
|
3
|
+
"sources": ["esm/behavior-detector.js", "esm/strategy.js", "esm/math-utils.js", "esm/strategies/mouse.js", "esm/strategies/scroll.js", "esm/strategies/click.js", "esm/strategies/tap.js", "esm/strategies/keyboard.js", "esm/strategies/environment.js", "esm/strategies/resize.js", "esm/strategies/timing.js", "esm/strategies/visibility.js", "esm/types.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * Main class for behavior detection\n * Uses modular strategy pattern for tree-shakeable, autonomous detection modules\n */\nexport class BehaviorDetector {\n constructor(tickOptions) {\n // Strategy mode\n this.strategies = new Map();\n this.isTracking = false;\n this.isPausedByVisibility = false;\n this.tickInterval = null;\n this.tickIntervalMs = 1000; // Default: 1 second\n this.pauseOnHidden = true;\n this.visibilityChangeHandler = null;\n // Confidence tracking\n this.confidenceScore = 0;\n this.CONFIDENCE_TARGET = 1.0; // Target confidence for reliable classification\n this.CONFIDENCE_DECAY = 0.95; // Per event decay to prevent infinite growth\n if (tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.interval) {\n this.tickIntervalMs = tickOptions.interval;\n }\n if ((tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.pauseOnHidden) !== undefined) {\n this.pauseOnHidden = tickOptions.pauseOnHidden;\n }\n }\n /**\n * Add a detection strategy\n */\n addStrategy(strategy, weight) {\n const config = {\n strategy,\n weight: weight !== null && weight !== void 0 ? weight : strategy.defaultWeight,\n enabled: true,\n };\n this.strategies.set(strategy.name, config);\n // Set up event callback for confidence tracking\n if (strategy.setEventCallback) {\n strategy.setEventCallback((event) => {\n this.onStrategyEvent(event, config.weight);\n });\n }\n // If already tracking, start this strategy immediately\n if (this.isTracking) {\n strategy.start();\n }\n return this;\n }\n /**\n * Handle event from strategy - update confidence\n */\n onStrategyEvent(event, strategyWeight) {\n // Apply decay to existing confidence to prevent infinite growth\n this.confidenceScore *= this.CONFIDENCE_DECAY;\n // Add weighted contribution from this event\n // eventWeight (0-1) * strategyWeight (e.g. 0.3 for mouse) = contribution\n const contribution = event.weight * strategyWeight;\n this.confidenceScore = Math.min(this.CONFIDENCE_TARGET, this.confidenceScore + contribution);\n }\n /**\n * Remove a detection strategy\n */\n removeStrategy(name) {\n const config = this.strategies.get(name);\n if (config) {\n if (this.isTracking) {\n config.strategy.stop();\n }\n this.strategies.delete(name);\n }\n return this;\n }\n /**\n * Enable/disable a strategy\n */\n setStrategyEnabled(name, enabled) {\n const config = this.strategies.get(name);\n if (config) {\n config.enabled = enabled;\n // If tracking and being disabled, stop it\n if (!enabled && this.isTracking) {\n config.strategy.stop();\n }\n // If tracking and being enabled, start it\n if (enabled && this.isTracking) {\n config.strategy.start();\n }\n }\n return this;\n }\n /**\n * Get all registered strategies\n */\n getStrategies() {\n return this.strategies;\n }\n /**\n * Start tracking\n */\n start() {\n if (this.isTracking)\n return;\n this.isTracking = true;\n // Set up visibility change listener\n if (this.pauseOnHidden && typeof document !== 'undefined') {\n this.visibilityChangeHandler = this.handleVisibilityChange.bind(this);\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n // Check initial visibility state\n if (document.hidden) {\n this.isPausedByVisibility = true;\n return; // Don't start strategies if already hidden\n }\n }\n // Start all enabled strategies\n for (const [_, config] of this.strategies) {\n if (config.enabled) {\n config.strategy.start();\n }\n }\n // Start tick mechanism\n this.startTick();\n }\n /**\n * Stop tracking\n */\n stop() {\n if (!this.isTracking)\n return;\n this.isTracking = false;\n this.isPausedByVisibility = false;\n // Remove visibility change listener\n if (this.visibilityChangeHandler && typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n // Stop all strategies\n for (const [_, config] of this.strategies) {\n config.strategy.stop();\n }\n // Stop tick\n this.stopTick();\n }\n /**\n * Reset all data\n */\n reset() {\n this.confidenceScore = 0;\n for (const [_, config] of this.strategies) {\n config.strategy.reset();\n }\n }\n /**\n * Calculate human likelihood score\n */\n async score(options = {}) {\n const breakdown = this.calculateStrategyScore();\n const result = {\n score: breakdown.overall,\n };\n if (options.breakdown) {\n result.breakdown = breakdown;\n }\n // Note: auditTrail not available in strategy mode\n // Each strategy manages its own data independently\n return result;\n }\n /**\n * Check if currently tracking\n */\n isActive() {\n return this.isTracking;\n }\n /**\n * Check if currently paused due to tab visibility\n */\n isPaused() {\n return this.isPausedByVisibility;\n }\n /**\n * Get event count from all strategies\n */\n getEventCount() {\n var _a, _b;\n const counts = {};\n for (const [name, config] of this.strategies) {\n const debug = (_b = (_a = config.strategy).getDebugInfo) === null || _b === void 0 ? void 0 : _b.call(_a);\n if ((debug === null || debug === void 0 ? void 0 : debug.eventCount) !== undefined) {\n counts[name] = debug.eventCount;\n }\n }\n return counts;\n }\n /**\n * Get debug info from all strategies\n */\n getStrategyDebugInfo() {\n const debug = {};\n for (const [name, config] of this.strategies) {\n if (config.strategy.getDebugInfo) {\n debug[name] = config.strategy.getDebugInfo();\n }\n }\n return debug;\n }\n /**\n * Get current confidence score (0-1)\n * Represents how much interaction data we've collected\n * Higher confidence = more reliable classification\n */\n getConfidence() {\n return Math.min(1, this.confidenceScore);\n }\n /**\n * Check if confidence is above threshold for reliable classification\n * @param threshold - Minimum confidence (0-1), default 0.3\n */\n hasConfidentData(threshold = 0.3) {\n return this.getConfidence() >= threshold;\n }\n /**\n * Cleanup resources\n */\n destroy() {\n this.stop();\n this.strategies.clear();\n }\n /**\n * Handle visibility change events\n */\n handleVisibilityChange() {\n if (!this.isTracking)\n return;\n if (document.hidden) {\n // Tab became hidden - pause detection\n if (!this.isPausedByVisibility) {\n this.isPausedByVisibility = true;\n // Stop all strategies\n for (const [_, config] of this.strategies) {\n if (config.enabled) {\n config.strategy.stop();\n }\n }\n // Stop tick\n this.stopTick();\n }\n }\n else {\n // Tab became visible - resume detection\n if (this.isPausedByVisibility) {\n this.isPausedByVisibility = false;\n // Restart all enabled strategies\n for (const [_, config] of this.strategies) {\n if (config.enabled) {\n config.strategy.start();\n }\n }\n // Restart tick\n this.startTick();\n }\n }\n }\n /**\n * Start tick mechanism for strategies\n */\n startTick() {\n if (this.tickInterval !== null)\n return;\n this.tickInterval = window.setInterval(() => {\n const now = Date.now();\n for (const [_, config] of this.strategies) {\n if (config.enabled && config.strategy.onTick) {\n config.strategy.onTick(now);\n }\n }\n }, this.tickIntervalMs);\n }\n /**\n * Stop tick mechanism\n */\n stopTick() {\n if (this.tickInterval !== null) {\n clearInterval(this.tickInterval);\n this.tickInterval = null;\n }\n }\n /**\n * Calculate score using strategies\n */\n calculateStrategyScore() {\n const factors = {};\n const weights = {};\n let totalWeight = 0;\n let weightedSum = 0;\n for (const [name, config] of this.strategies) {\n if (!config.enabled)\n continue;\n const score = config.strategy.score();\n factors[name] = score;\n weights[name] = config.weight;\n if (score !== undefined && score !== null) {\n totalWeight += config.weight;\n weightedSum += score * config.weight;\n }\n }\n const overall = totalWeight > 0 ? weightedSum / totalWeight : 0.5;\n return {\n overall: Math.max(0, Math.min(1, overall)),\n factors,\n weights,\n };\n }\n}\n", "/**\n * Detection Strategy Interface\n * Each strategy is a fully autonomous module responsible for:\n * - Registering its own event listeners\n * - Managing its own state and events\n * - Responding to lifecycle events (start/stop)\n * - Optionally receiving tick updates for polling-based detection\n */\n/**\n * Base class for detection strategies\n * Handles event callback pattern to avoid repetition\n */\nexport class BaseStrategy {\n constructor() {\n this.eventCallback = null;\n }\n setEventCallback(callback) {\n this.eventCallback = callback;\n }\n notifyEvent(weight) {\n if (this.eventCallback) {\n this.eventCallback({\n strategy: this.name,\n weight,\n timestamp: Date.now()\n });\n }\n }\n}\n", "/**\n * Mathematical utility functions for continuous scoring\n * Replaces magic number if-else chains with smooth mathematical functions\n */\n/**\n * Sigmoid function - Maps any value to [0, 1] with smooth S-curve\n * @param x - Input value\n * @param midpoint - Value that maps to 0.5\n * @param steepness - How steep the curve is (higher = steeper)\n */\nexport function sigmoid(x, midpoint = 0, steepness = 1) {\n return 1 / (1 + Math.exp(-steepness * (x - midpoint)));\n}\n/**\n * Inverse sigmoid - High values map to low scores\n */\nexport function inverseSigmoid(x, midpoint = 0, steepness = 1) {\n return 1 - sigmoid(x, midpoint, steepness);\n}\n/**\n * Gaussian (bell curve) - Peak at ideal value, falls off on both sides\n * @param x - Input value\n * @param ideal - Optimal value (peak of curve)\n * @param width - How wide the acceptable range is\n */\nexport function gaussian(x, ideal = 0, width = 1) {\n const exponent = -Math.pow(x - ideal, 2) / (2 * width * width);\n return Math.exp(exponent);\n}\n/**\n * Exponential decay - High values get penalized exponentially\n */\nexport function exponentialDecay(x, decayRate = 0.1) {\n return Math.exp(-decayRate * x);\n}\n/**\n * Normalize value to [0, 1] range\n */\nexport function normalize(value, min = 0, max = 1) {\n if (max === min)\n return 0.5;\n return Math.max(0, Math.min(1, (value - min) / (max - min)));\n}\n/**\n * Clamp value to [0, 1]\n */\nexport function clamp01(value) {\n return Math.max(0, Math.min(1, value));\n}\n/**\n * Calculate statistical metrics for an array of numbers\n * @param values - Array of numerical values\n * @returns Statistical metrics (mean, variance, stdDev, cv)\n */\nexport function calculateStatistics(values) {\n if (values.length === 0) {\n return { mean: 0, variance: 0, stdDev: 0, cv: 0 };\n }\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / values.length;\n const stdDev = Math.sqrt(variance);\n const cv = mean > 0 ? stdDev / mean : 0;\n return { mean, variance, stdDev, cv };\n}\n/**\n * Analyze timing intervals for bot-like patterns\n * Returns raw analysis data without scoring - caller decides heuristics\n *\n * @param intervals - Array of time intervals (ms)\n * @returns Analysis of interval patterns including stats and uniqueness\n */\nexport function analyzeIntervals(intervals) {\n if (intervals.length < 2)\n return undefined;\n // Check for identical intervals (round to 10ms to account for floating point)\n const uniqueCount = new Set(intervals.map(i => Math.round(i / 10))).size;\n const allIdentical = uniqueCount === 1;\n // Calculate statistics\n const statistics = calculateStatistics(intervals);\n return {\n statistics,\n uniqueCount,\n allIdentical,\n };\n}\n/**\n * Score coefficient of variation\n * Maps CV to human-likeness score using Gaussian\n * Ideal CV is around 0.4-0.5 (moderate variation)\n */\nexport function scoreCoefficientOfVariation(cv) {\n // Too low (<0.1) = bot-like (too consistent)\n // Too high (>1.5) = random noise\n // Ideal = 0.4-0.6 (natural human variation)\n if (cv < 0.05)\n return 0.1; // Almost zero variation - definitely bot\n if (cv > 2.0)\n return 0.3; // Too random\n // Gaussian centered at 0.45 with width of 0.35\n return gaussian(cv, 0.45, 0.35);\n}\n/**\n * Score entropy - Higher is better (more random = more human)\n * Uses sigmoid to smoothly map entropy to score\n */\nexport function scoreEntropy(normalizedEntropy) {\n // Entropy of 0.7+ is very human\n // Entropy < 0.3 is very bot-like\n return sigmoid(normalizedEntropy, 0.5, 8); // Steep curve at midpoint 0.5\n}\n/**\n * Score autocorrelation - Lower is better (less periodic = more human)\n */\nexport function scoreAutocorrelation(autocorr) {\n // Low autocorrelation (<0.2) is natural\n // High autocorrelation (>0.6) is periodic/bot-like\n return inverseSigmoid(autocorr, 0.4, 10);\n}\n/**\n * Score jerk - Lower is better (smoother = more human)\n */\nexport function scoreJerk(avgJerk) {\n // Human jerk typically < 0.01\n // Bot jerk often > 0.1\n // Use inverse sigmoid\n return inverseSigmoid(avgJerk, 0.05, 50);\n}\n", "/**\n * Mouse Movement Detection Strategy\n * Autonomous module that manages its own mouse event listeners and state\n * Tracks distance and angle to detect unnatural jumps and sharp turns\n *\n * Enhanced detection:\n * - Pre-click stillness (micro-movements before clicks)\n * - Entry point analysis (where mouse enters viewport)\n * - Velocity consistency\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { calculateStatistics, gaussian } from '../math-utils.js';\nexport class MouseStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'mouse';\n this.defaultWeight = 0.30;\n this.distanceSeries = [];\n this.angleSeries = [];\n this.lastPosition = null;\n this.lastAngle = 0;\n this.cumulativeAngle = 0;\n this.rollingWindowMs = 5000;\n this.listener = null;\n this.leaveListener = null;\n this.enterListener = null;\n this.isActive = false;\n this.screenDiagonal = 1;\n /** Entry points tracking */\n this.entryPoints = [];\n /** Micro-movements in last 500ms (for stillness detection) */\n this.microMovements = [];\n /** Stillness window in ms */\n this.STILLNESS_WINDOW = 500;\n if ((options === null || options === void 0 ? void 0 : options.rollingWindow) !== undefined)\n this.rollingWindowMs = options.rollingWindow;\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Calculate screen diagonal for normalization (distance relative to screen size)\n const width = window.innerWidth;\n const height = window.innerHeight;\n this.screenDiagonal = Math.sqrt(width * width + height * height);\n this.listener = (e) => {\n const mouseEvent = e;\n const now = Date.now();\n const currentPos = { x: mouseEvent.clientX, y: mouseEvent.clientY, timestamp: now };\n // Calculate distance and angle from previous position\n if (this.lastPosition) {\n const dx = currentPos.x - this.lastPosition.x;\n const dy = currentPos.y - this.lastPosition.y;\n const pixelDistance = Math.sqrt(dx * dx + dy * dy);\n // Track micro-movements (1-5px) for stillness detection\n if (pixelDistance >= 1 && pixelDistance <= 5) {\n this.microMovements.push({ dx, dy, timestamp: now });\n // Clean up old micro-movements (shift from front, more efficient than filter)\n const cutoffMicro = now - this.STILLNESS_WINDOW;\n while (this.microMovements.length > 0 && this.microMovements[0].timestamp < cutoffMicro) {\n this.microMovements.shift();\n }\n }\n // Normalize distance to screen diagonal (0-1 range)\n // A full diagonal movement = 1.0, a 10px movement on 2000px screen = 0.005\n const normalizedDistance = pixelDistance / this.screenDiagonal;\n // Only record if movement is meaningful (> 0.001 = ~2px on 2000px screen)\n if (normalizedDistance > 0.001) {\n const rawAngle = Math.atan2(dy, dx); // -PI to PI\n // Unwrap angle to avoid discontinuities (e.g., circles)\n let angleDiff = rawAngle - this.lastAngle;\n // Normalize difference to -PI to PI\n while (angleDiff > Math.PI)\n angleDiff -= 2 * Math.PI;\n while (angleDiff < -Math.PI)\n angleDiff += 2 * Math.PI;\n this.cumulativeAngle += angleDiff;\n this.lastAngle = rawAngle;\n // Store normalized distance (not raw pixels)\n this.distanceSeries.push({ value: normalizedDistance, timestamp: now });\n this.angleSeries.push({ value: this.cumulativeAngle, timestamp: now });\n // Notify detector for confidence tracking\n this.notifyEvent(Math.min(1, normalizedDistance * 100));\n }\n // Apply rolling window efficiently: remove old events from start\n // Since events are chronological, we only check from the beginning\n const cutoff = now - this.rollingWindowMs;\n while (this.distanceSeries.length > 0 && this.distanceSeries[0].timestamp < cutoff) {\n this.distanceSeries.shift();\n this.angleSeries.shift(); // Keep both arrays in sync\n }\n }\n this.lastPosition = currentPos;\n };\n document.addEventListener('mousemove', this.listener, { passive: true });\n // Track mouse entry points into viewport\n this.enterListener = (e) => {\n const mouseEvent = e;\n const now = Date.now();\n const x = mouseEvent.clientX;\n const y = mouseEvent.clientY;\n const width = window.innerWidth;\n const height = window.innerHeight;\n // Calculate edge distances\n const distTop = y;\n const distBottom = height - y;\n const distLeft = x;\n const distRight = width - x;\n const minEdgeDist = Math.min(distTop, distBottom, distLeft, distRight);\n // Determine entry edge\n let entryEdge;\n const edgeThreshold = 50; // pixels from edge to count as edge entry\n if (minEdgeDist < edgeThreshold) {\n if (distTop <= minEdgeDist)\n entryEdge = 'top';\n else if (distBottom <= minEdgeDist)\n entryEdge = 'bottom';\n else if (distLeft <= minEdgeDist)\n entryEdge = 'left';\n else\n entryEdge = 'right';\n }\n else if (x > width * 0.35 && x < width * 0.65 &&\n y > height * 0.35 && y < height * 0.65) {\n entryEdge = 'center'; // Suspicious - bots often start at center\n }\n else if ((distTop < edgeThreshold * 2 && distLeft < edgeThreshold * 2) ||\n (distTop < edgeThreshold * 2 && distRight < edgeThreshold * 2) ||\n (distBottom < edgeThreshold * 2 && distLeft < edgeThreshold * 2) ||\n (distBottom < edgeThreshold * 2 && distRight < edgeThreshold * 2)) {\n entryEdge = 'corner';\n }\n else {\n // Entry from middle of an edge, normal\n if (distTop < distBottom && distTop < distLeft && distTop < distRight)\n entryEdge = 'top';\n else if (distBottom < distLeft && distBottom < distRight)\n entryEdge = 'bottom';\n else if (distLeft < distRight)\n entryEdge = 'left';\n else\n entryEdge = 'right';\n }\n this.entryPoints.push({\n x,\n y,\n timestamp: now,\n edgeDistance: minEdgeDist,\n entryEdge,\n });\n // Keep only last 20 entry points (shift is more memory efficient than slice)\n if (this.entryPoints.length > 20) {\n this.entryPoints.shift();\n }\n };\n document.addEventListener('mouseenter', this.enterListener, { passive: true });\n // Clear data when mouse leaves the window (discontinuous tracking)\n this.leaveListener = () => {\n this.distanceSeries = [];\n this.angleSeries = [];\n this.lastPosition = null;\n this.lastAngle = 0;\n this.cumulativeAngle = 0;\n this.microMovements = [];\n };\n document.addEventListener('mouseleave', this.leaveListener, { passive: true });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.listener) {\n document.removeEventListener('mousemove', this.listener);\n this.listener = null;\n }\n if (this.leaveListener) {\n document.removeEventListener('mouseleave', this.leaveListener);\n this.leaveListener = null;\n }\n if (this.enterListener) {\n document.removeEventListener('mouseenter', this.enterListener);\n this.enterListener = null;\n }\n }\n reset() {\n this.distanceSeries = [];\n this.angleSeries = [];\n this.lastPosition = null;\n this.lastAngle = 0;\n this.cumulativeAngle = 0;\n this.entryPoints = [];\n this.microMovements = [];\n }\n score() {\n if (this.distanceSeries.length < 10)\n return undefined;\n // Mouse-specific pattern detection (optimized for normalized continuous data)\n // Generic smoothness detector is calibrated for discrete events, not continuous movement\n return this.detectMousePatterns();\n }\n /**\n * Mouse-specific pattern detection\n * Detects bot-like patterns: constant velocity, linear paths, suspicious entry points\n */\n detectMousePatterns() {\n if (this.distanceSeries.length < 10)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. VELOCITY CONSISTENCY - Bots often move at constant speed\n const distances = this.distanceSeries.map(p => p.value);\n if (distances.length >= 3) {\n const stats = calculateStatistics(distances);\n // Real human movement has high variation (CV ~0.8-1.2)\n // page.mouse.move() with steps has lower CV (~0.4-0.6)\n // Narrower gaussian to be strict\n score += gaussian(stats.cv, 0.9, 0.35);\n factors++;\n }\n // 2. DIRECTION CHANGES - Bots often have too few or too many sharp turns\n const angles = this.angleSeries.map(p => p.value);\n if (angles.length >= 3) {\n const angleChanges = [];\n for (let i = 1; i < angles.length; i++) {\n angleChanges.push(Math.abs(angles[i] - angles[i - 1]));\n }\n const avgChange = angleChanges.reduce((a, b) => a + b, 0) / angleChanges.length;\n // Real humans have moderate but varied direction changes\n // page.mouse.move() linear interpolation has very small, consistent changes\n score += gaussian(avgChange, 0.15, 0.12);\n factors++;\n }\n // 3. ENTRY POINT ANALYSIS - Where does mouse enter the viewport?\n const entryScore = this.scoreEntryPoints();\n if (entryScore !== undefined) {\n score += entryScore;\n factors++;\n }\n // 4. MICRO-MOVEMENT PRESENCE - Humans have tremors, bots don't\n const microScore = this.scoreMicroMovements();\n if (microScore !== undefined) {\n score += microScore;\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n /**\n * Score based on viewport entry points\n * Humans enter from edges with momentum; bots often start at (0,0) or center\n */\n scoreEntryPoints() {\n if (this.entryPoints.length < 2)\n return undefined;\n let suspiciousCount = 0;\n let centerCount = 0;\n let cornerCount = 0;\n let originCount = 0;\n for (const entry of this.entryPoints) {\n // Check for (0,0) or near-origin entries (very suspicious)\n if (entry.x < 5 && entry.y < 5) {\n originCount++;\n suspiciousCount++;\n }\n else if (entry.entryEdge === 'center') {\n centerCount++;\n suspiciousCount++;\n }\n else if (entry.entryEdge === 'corner') {\n cornerCount++;\n // Corners are slightly suspicious but not as bad as center\n if (entry.edgeDistance < 10)\n suspiciousCount++;\n }\n }\n const total = this.entryPoints.length;\n const suspiciousRatio = suspiciousCount / total;\n // High ratio of origin entries = definitely bot\n if (originCount >= 2 || originCount / total >= 0.5)\n return 0.1;\n // High ratio of center entries = likely bot\n if (centerCount / total >= 0.5)\n return 0.2;\n // Mix of suspicious entries\n if (suspiciousRatio >= 0.7)\n return 0.3;\n if (suspiciousRatio >= 0.5)\n return 0.5;\n if (suspiciousRatio >= 0.3)\n return 0.7;\n // Mostly edge entries = human\n return 1.0;\n }\n /**\n * Score based on micro-movements (tremor detection)\n * Humans have natural hand tremor causing 1-5px jitter\n * Bots have perfect stillness or no micro-movements\n */\n scoreMicroMovements() {\n // Need some movement data first\n if (this.distanceSeries.length < 20)\n return undefined;\n const microCount = this.microMovements.length;\n // Calculate expected micro-movements based on tracking duration\n // Humans should have ~5-20 micro-movements per second when cursor is active\n const oldestEvent = this.distanceSeries[0];\n const newestEvent = this.distanceSeries[this.distanceSeries.length - 1];\n const durationMs = newestEvent.timestamp - oldestEvent.timestamp;\n if (durationMs < 1000)\n return undefined; // Need at least 1 second of data\n // Micro-movements per second\n const microPerSecond = (microCount / durationMs) * 1000;\n // No micro-movements at all = very suspicious\n if (microCount === 0)\n return 0.3;\n // Very few micro-movements = somewhat suspicious\n if (microPerSecond < 1)\n return 0.5;\n // Some micro-movements = more human-like\n if (microPerSecond < 5)\n return 0.7;\n // Good amount of micro-movements = human\n if (microPerSecond >= 5 && microPerSecond <= 30)\n return 1.0;\n // Excessive micro-movements (> 30/sec) might be artificial noise\n return 0.8;\n }\n /**\n * Get micro-movement count for external use (e.g., by ClickStrategy)\n */\n getMicroMovementCount() {\n return this.microMovements.length;\n }\n /**\n * Get last position for external use\n */\n getLastPosition() {\n return this.lastPosition ? { x: this.lastPosition.x, y: this.lastPosition.y } : null;\n }\n getDebugInfo() {\n return {\n eventCount: this.distanceSeries.length,\n rollingWindow: this.rollingWindowMs,\n isActive: this.isActive,\n distanceSeries: this.distanceSeries,\n angleSeries: this.angleSeries,\n entryPoints: this.entryPoints,\n microMovementCount: this.microMovements.length,\n lastPosition: this.lastPosition,\n };\n }\n}\n", "/**\n * Scroll Behavior Detection Strategy\n * Autonomous module managing scroll event listeners\n * Tracks normalized scroll distance and velocity patterns\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { calculateStatistics, gaussian, inverseSigmoid } from '../math-utils.js';\nexport class ScrollStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'scroll';\n this.defaultWeight = 0.15;\n this.distanceSeries = [];\n this.velocitySeries = [];\n this.lastScrollY = null;\n this.lastTimestamp = 0;\n this.rollingWindowMs = 5000;\n this.documentHeight = 1;\n this.listener = null;\n this.isActive = false;\n if ((options === null || options === void 0 ? void 0 : options.rollingWindow) !== undefined)\n this.rollingWindowMs = options.rollingWindow;\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Calculate document height for normalization\n this.documentHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, 1);\n this.listener = (_e) => {\n const scrollY = window.scrollY;\n const now = Date.now();\n // Always update last position on first event\n if (this.lastScrollY === null) {\n this.lastScrollY = scrollY;\n this.lastTimestamp = now;\n return;\n }\n const pixelDelta = scrollY - this.lastScrollY;\n const deltaTime = now - this.lastTimestamp;\n // Skip if no actual scroll happened\n if (pixelDelta === 0) {\n return;\n }\n // Normalize scroll distance to document height (0-1 range)\n const normalizedDistance = Math.abs(pixelDelta) / this.documentHeight;\n // Record all scroll movements (no threshold - let pattern detection decide)\n if (deltaTime > 0) {\n const velocity = normalizedDistance / deltaTime; // normalized units per ms\n // Store as time series\n this.distanceSeries.push({ value: normalizedDistance, timestamp: now });\n this.velocitySeries.push({ value: velocity, timestamp: now });\n // Notify detector for confidence tracking\n this.notifyEvent(Math.min(1, normalizedDistance * 10));\n // Apply rolling window efficiently\n const cutoff = now - this.rollingWindowMs;\n while (this.distanceSeries.length > 0 && this.distanceSeries[0].timestamp < cutoff) {\n this.distanceSeries.shift();\n this.velocitySeries.shift();\n }\n }\n this.lastScrollY = scrollY;\n this.lastTimestamp = now;\n };\n // Listen on window for scroll events (document scrolling)\n window.addEventListener('scroll', this.listener, { passive: true });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.listener) {\n window.removeEventListener('scroll', this.listener);\n this.listener = null;\n }\n }\n reset() {\n this.distanceSeries = [];\n this.velocitySeries = [];\n this.lastScrollY = null;\n this.lastTimestamp = 0;\n }\n score() {\n if (this.distanceSeries.length < 2)\n return undefined;\n // Scroll-specific pattern detection\n return this.detectScrollPatterns();\n }\n /**\n * Scroll-specific pattern detection\n * Detects bot-like patterns: constant deltas, instant jumps, too smooth\n */\n detectScrollPatterns() {\n if (this.distanceSeries.length < 2)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. IDENTICAL DELTAS - Smoking gun for bots\n const distances = this.distanceSeries.map(p => p.value);\n if (distances.length >= 2) {\n // Check if all distances are identical (tolerance for floating point)\n const uniqueDistances = new Set(distances.map(d => Math.round(d * 1000))).size;\n if (uniqueDistances === 1) {\n // All scroll amounts identical = definite bot\n return 0.05;\n }\n }\n // 2. DISTANCE CONSISTENCY - Bots often scroll same amount repeatedly\n if (distances.length >= 2) {\n const stats = calculateStatistics(distances);\n // Real humans have high CV (>0.8) due to natural scroll acceleration/deceleration\n // Simple automation has lower CV even with varied amounts\n // Gaussian centered high with narrow width - be strict\n score += gaussian(stats.cv, 1.0, 0.4);\n factors++;\n }\n // 3. VELOCITY VARIATION - Humans have highly variable scroll speeds\n const velocities = this.velocitySeries.map(p => p.value);\n if (velocities.length >= 2) {\n const stats = calculateStatistics(velocities);\n // Human velocity is very chaotic (acceleration/deceleration)\n // Automation has more consistent velocity even with delays\n score += gaussian(stats.cv, 1.2, 0.5);\n factors++;\n }\n // 4. INSTANT JUMPS - Detect programmatic scrollTo\n const instantJumps = distances.filter(d => d > 0.1).length; // >10% of document in one event\n if (distances.length > 0) {\n const jumpRatio = instantJumps / distances.length;\n // Penalize high jump ratio (programmatic scrollTo)\n score += inverseSigmoid(jumpRatio, 0.3, 15);\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.distanceSeries.length,\n rollingWindow: this.rollingWindowMs,\n isActive: this.isActive,\n distanceSeries: this.distanceSeries,\n velocitySeries: this.velocitySeries,\n };\n }\n}\n", "/**\n * Click Behavior Detection Strategy\n * Monitors specific elements for click positioning patterns\n *\n * Enhanced detection:\n * - Click-mouse position delta (bots using .click() have mismatched positions)\n * - Pre-click mouse trajectory analysis\n * - Time between last mousemove and click\n */\nimport { BaseStrategy } from '../strategy.js';\nexport class ClickStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'click';\n this.defaultWeight = 0.30;\n this.events = [];\n this.targetSelectors = ['button', 'a', 'input[type=\"submit\"]', '[role=\"button\"]'];\n this.lastMousePosition = null;\n this.mouseListener = null;\n this.clickListeners = new Map();\n this.isActive = false;\n if (options === null || options === void 0 ? void 0 : options.targetSelectors) {\n this.targetSelectors = options.targetSelectors;\n }\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Track mouse position globally with timestamp\n this.mouseListener = (e) => {\n const mouseEvent = e;\n this.lastMousePosition = {\n x: mouseEvent.clientX,\n y: mouseEvent.clientY,\n timestamp: Date.now(),\n };\n };\n document.addEventListener('mousemove', this.mouseListener, { passive: true });\n // Find all matching elements and attach listeners\n this.attachClickListeners();\n }\n /**\n * Add a new target selector at runtime\n */\n addTarget(selector) {\n if (!this.targetSelectors.includes(selector)) {\n this.targetSelectors.push(selector);\n // Attach listeners if already active\n if (this.isActive) {\n this.attachClickListenersForSelector(selector);\n }\n }\n }\n attachClickListeners() {\n this.targetSelectors.forEach(selector => {\n this.attachClickListenersForSelector(selector);\n });\n }\n attachClickListenersForSelector(selector) {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (this.clickListeners.has(element))\n return; // Already attached\n const listener = (e) => {\n var _a, _b;\n const clickEvent = e;\n const now = Date.now();\n const rect = element.getBoundingClientRect();\n // Check if element is in viewport\n const inViewport = (rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= window.innerHeight &&\n rect.right <= window.innerWidth);\n // Calculate mouse-click position delta\n // Bots using element.click() have click event coordinates different from mouse position\n let mouseClickDelta = 0;\n let timeSinceMouseMove = -1;\n if (this.lastMousePosition) {\n const dx = clickEvent.clientX - this.lastMousePosition.x;\n const dy = clickEvent.clientY - this.lastMousePosition.y;\n mouseClickDelta = Math.sqrt(dx * dx + dy * dy);\n timeSinceMouseMove = now - this.lastMousePosition.timestamp;\n }\n // Analyze click position\n let position;\n if (!this.lastMousePosition) {\n position = 'no-mouse-data'; // Bot - no mouse movement\n }\n else {\n const mx = this.lastMousePosition.x;\n const my = this.lastMousePosition.y;\n // Check if mouse was over element\n const overElement = (mx >= rect.left &&\n mx <= rect.right &&\n my >= rect.top &&\n my <= rect.bottom);\n if (!overElement) {\n position = 'outside'; // Bot - mouse not over target\n }\n else {\n // Check if dead center (suspicious)\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const distanceFromCenter = Math.sqrt((mx - centerX) ** 2 + (my - centerY) ** 2);\n // Dead center = within 2px of center\n if (distanceFromCenter < 2) {\n position = 'dead-center'; // Suspicious - too perfect\n }\n else {\n position = 'over-element'; // Human - somewhere on the button\n }\n }\n }\n this.events.push({\n clickX: clickEvent.clientX,\n clickY: clickEvent.clientY,\n mouseX: (_a = this.lastMousePosition) === null || _a === void 0 ? void 0 : _a.x,\n mouseY: (_b = this.lastMousePosition) === null || _b === void 0 ? void 0 : _b.y,\n rect,\n inViewport,\n position,\n timestamp: now,\n mouseClickDelta,\n timeSinceMouseMove,\n isTrusted: clickEvent.isTrusted,\n });\n // Notify detector - clicks are high-value events\n this.notifyEvent(1.0);\n };\n element.addEventListener('click', listener);\n this.clickListeners.set(element, listener);\n });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n // Remove mouse listener\n if (this.mouseListener) {\n document.removeEventListener('mousemove', this.mouseListener);\n this.mouseListener = null;\n }\n // Remove all click listeners\n this.clickListeners.forEach((listener, element) => {\n element.removeEventListener('click', listener);\n });\n this.clickListeners.clear();\n }\n reset() {\n this.events = [];\n this.lastMousePosition = null;\n }\n score() {\n const eventCount = this.events.length;\n if (eventCount === 0)\n return undefined;\n // Pre-compute counts in a single pass\n let positionScore = 0;\n let clicksWithDelta = 0;\n let mismatchCount = 0;\n let clicksWithTiming = 0;\n let suspiciousTimingCount = 0;\n let untrustedCount = 0;\n for (const click of this.events) {\n // Position scoring\n switch (click.position) {\n case 'no-mouse-data':\n positionScore += 0.0;\n break;\n case 'outside':\n positionScore += 0.0;\n break;\n case 'dead-center':\n positionScore += 0.5;\n break;\n case 'over-element':\n positionScore += 1.0;\n break;\n }\n // Delta scoring\n if (click.mouseClickDelta >= 0) {\n clicksWithDelta++;\n if (click.mouseClickDelta > 5)\n mismatchCount++;\n }\n // Timing scoring\n if (click.timeSinceMouseMove >= 0) {\n clicksWithTiming++;\n if (click.timeSinceMouseMove < 10 || click.timeSinceMouseMove > 2000) {\n suspiciousTimingCount++;\n }\n }\n // Trusted scoring\n if (!click.isTrusted)\n untrustedCount++;\n }\n let score = 0;\n let factors = 0;\n // 1. Position-based scoring\n score += positionScore / eventCount;\n factors++;\n // 2. Mouse-click delta scoring\n if (clicksWithDelta >= 2) {\n const mismatchRatio = mismatchCount / clicksWithDelta;\n let deltaScore;\n if (mismatchRatio >= 0.8)\n deltaScore = 0.1;\n else if (mismatchRatio >= 0.5)\n deltaScore = 0.3;\n else if (mismatchRatio >= 0.3)\n deltaScore = 0.5;\n else if (mismatchRatio > 0)\n deltaScore = 0.7;\n else\n deltaScore = 1.0;\n score += deltaScore;\n factors++;\n }\n // 3. Mouse-to-click timing\n if (clicksWithTiming >= 2) {\n const suspiciousRatio = suspiciousTimingCount / clicksWithTiming;\n let timingScore;\n if (suspiciousRatio >= 0.8)\n timingScore = 0.2;\n else if (suspiciousRatio >= 0.5)\n timingScore = 0.4;\n else if (suspiciousRatio >= 0.3)\n timingScore = 0.6;\n else if (suspiciousRatio > 0)\n timingScore = 0.8;\n else\n timingScore = 1.0;\n score += timingScore;\n factors++;\n }\n // 4. Trusted event scoring\n if (eventCount >= 2) {\n const untrustedRatio = untrustedCount / eventCount;\n let trustedScore;\n if (untrustedRatio >= 0.5)\n trustedScore = 0.1;\n else if (untrustedRatio > 0)\n trustedScore = 0.3;\n else\n trustedScore = 1.0;\n score += trustedScore;\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.events.length,\n positions: {\n noMouseData: this.events.filter(e => e.position === 'no-mouse-data').length,\n outside: this.events.filter(e => e.position === 'outside').length,\n deadCenter: this.events.filter(e => e.position === 'dead-center').length,\n overElement: this.events.filter(e => e.position === 'over-element').length,\n },\n inViewport: this.events.filter(e => e.inViewport).length,\n trackedElements: this.clickListeners.size,\n mouseClickDeltas: this.events.map(e => e.mouseClickDelta),\n timeSinceMouseMoves: this.events.map(e => e.timeSinceMouseMove),\n untrustedClicks: this.events.filter(e => !e.isTrusted).length,\n };\n }\n}\n", "/**\n * Tap Behavior Detection Strategy (Mobile)\n * Monitors touch interactions on specific elements\n * Analyzes tap duration, precision, movement, and timing patterns\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { analyzeIntervals, scoreCoefficientOfVariation, gaussian } from '../math-utils.js';\nexport class TapStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'tap';\n this.defaultWeight = 0.35;\n this.events = [];\n this.targetSelectors = ['button', 'a', 'input[type=\"submit\"]', '[role=\"button\"]'];\n this.touchStartListeners = new Map();\n this.touchEndListeners = new Map();\n this.activeTouches = new Map();\n this.isActive = false;\n if (options === null || options === void 0 ? void 0 : options.targetSelectors) {\n this.targetSelectors = options.targetSelectors;\n }\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n this.attachTouchListeners();\n }\n addTarget(selector) {\n if (!this.targetSelectors.includes(selector)) {\n this.targetSelectors.push(selector);\n if (this.isActive) {\n this.attachTouchListenersForSelector(selector);\n }\n }\n }\n attachTouchListeners() {\n this.targetSelectors.forEach(selector => {\n this.attachTouchListenersForSelector(selector);\n });\n }\n attachTouchListenersForSelector(selector) {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (this.touchStartListeners.has(element))\n return;\n const startListener = (e) => {\n const touchEvent = e;\n // Only track first touch (ignore multi-touch)\n if (touchEvent.touches.length !== 1)\n return;\n const touch = touchEvent.touches[0];\n this.activeTouches.set(touch.identifier, {\n x: touch.clientX,\n y: touch.clientY,\n timestamp: Date.now(),\n element,\n });\n };\n const endListener = (e) => {\n const touchEvent = e;\n if (touchEvent.changedTouches.length !== 1)\n return;\n const touch = touchEvent.changedTouches[0];\n const startData = this.activeTouches.get(touch.identifier);\n if (!startData || startData.element !== element)\n return;\n const now = Date.now();\n const duration = now - startData.timestamp;\n const dx = touch.clientX - startData.x;\n const dy = touch.clientY - startData.y;\n const movement = Math.sqrt(dx * dx + dy * dy);\n const rect = element.getBoundingClientRect();\n const inViewport = (rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= window.innerHeight &&\n rect.right <= window.innerWidth);\n // Analyze tap position\n const tx = touch.clientX;\n const ty = touch.clientY;\n const overElement = (tx >= rect.left &&\n tx <= rect.right &&\n ty >= rect.top &&\n ty <= rect.bottom);\n let position;\n if (!overElement) {\n position = 'outside';\n }\n else {\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const distanceFromCenter = Math.sqrt((tx - centerX) ** 2 + (ty - centerY) ** 2);\n // Dead center = within 2px\n position = distanceFromCenter < 2 ? 'dead-center' : 'over-element';\n }\n this.events.push({\n x: tx,\n y: ty,\n rect,\n inViewport,\n position,\n duration,\n movement,\n timestamp: now,\n });\n // Notify detector - taps are high-value events\n this.notifyEvent(1.0);\n this.activeTouches.delete(touch.identifier);\n };\n element.addEventListener('touchstart', startListener, { passive: true });\n element.addEventListener('touchend', endListener, { passive: true });\n this.touchStartListeners.set(element, startListener);\n this.touchEndListeners.set(element, endListener);\n });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n this.touchStartListeners.forEach((listener, element) => {\n element.removeEventListener('touchstart', listener);\n });\n this.touchStartListeners.clear();\n this.touchEndListeners.forEach((listener, element) => {\n element.removeEventListener('touchend', listener);\n });\n this.touchEndListeners.clear();\n this.activeTouches.clear();\n }\n reset() {\n this.events = [];\n this.activeTouches.clear();\n }\n score() {\n if (this.events.length === 0)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. Position accuracy\n let positionScore = 0;\n for (const tap of this.events) {\n switch (tap.position) {\n case 'outside':\n positionScore += 0.0; // Bot\n break;\n case 'dead-center':\n positionScore += 0.5; // Suspicious\n break;\n case 'over-element':\n positionScore += 1.0; // Human\n break;\n }\n }\n score += positionScore / this.events.length;\n factors++;\n // 2. Tap duration variation - Humans have natural variation (50-150ms typical)\n const durations = this.events.map(e => e.duration);\n if (durations.length >= 2) {\n const durationAnalysis = analyzeIntervals(durations);\n if (durationAnalysis) {\n const { statistics, allIdentical } = durationAnalysis;\n // All identical = bot\n if (allIdentical) {\n return 0.05;\n }\n // Human tap durations have moderate CV (~0.3-0.5)\n score += scoreCoefficientOfVariation(statistics.cv);\n factors++;\n // Ideal duration: 70-120ms\n score += gaussian(statistics.mean, 95, 40);\n factors++;\n }\n }\n // 3. Tap movement - Real fingers move slightly (1-5px), bots are often 0px\n const movements = this.events.map(e => e.movement);\n if (movements.length > 0) {\n const avgMovement = movements.reduce((a, b) => a + b, 0) / movements.length;\n // Some movement is natural (1-5px), too much is a swipe, zero is suspicious\n score += gaussian(avgMovement, 2, 3);\n factors++;\n }\n // 4. Tap interval timing - Time between taps should vary naturally\n if (this.events.length >= 3) {\n const intervals = [];\n for (let i = 1; i < this.events.length; i++) {\n intervals.push(this.events[i].timestamp - this.events[i - 1].timestamp);\n }\n const intervalAnalysis = analyzeIntervals(intervals);\n if (intervalAnalysis && !intervalAnalysis.allIdentical) {\n score += scoreCoefficientOfVariation(intervalAnalysis.statistics.cv);\n factors++;\n }\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.events.length,\n positions: {\n outside: this.events.filter(e => e.position === 'outside').length,\n deadCenter: this.events.filter(e => e.position === 'dead-center').length,\n overElement: this.events.filter(e => e.position === 'over-element').length,\n },\n durations: this.events.map(e => e.duration),\n movements: this.events.map(e => e.movement),\n inViewport: this.events.filter(e => e.inViewport).length,\n trackedElements: this.touchStartListeners.size,\n };\n }\n}\n", "/**\n * Keyboard Timing Detection Strategy\n * Monitors typing in specific input fields\n * Analyzes keydown/keyup timing and micro-variations\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { analyzeIntervals, scoreCoefficientOfVariation } from '../math-utils.js';\nexport class KeyboardStrategy extends BaseStrategy {\n constructor(options) {\n super();\n this.name = 'keyboard';\n this.defaultWeight = 0.10;\n this.events = [];\n this.targetSelectors = ['input[type=\"text\"]', 'input[type=\"email\"]', 'textarea'];\n this.focusedElement = null;\n this.focusedElementSelector = '';\n this.lastEventTimestamp = 0;\n this.sessionPauseThreshold = 1000;\n this.downListener = null;\n this.upListener = null;\n this.focusListeners = new Map();\n this.blurListeners = new Map();\n this.isActive = false;\n if (options === null || options === void 0 ? void 0 : options.targetSelectors) {\n this.targetSelectors = options.targetSelectors;\n }\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Attach focus/blur listeners to all matching elements\n this.attachFocusListeners();\n // Key event listeners (only track when an input is focused)\n this.downListener = (e) => {\n if (!this.focusedElement)\n return; // No input focused\n const now = Date.now();\n const keyEvent = e;\n // Clear events if pause > 1s (new typing session)\n if (this.lastEventTimestamp > 0 && now - this.lastEventTimestamp > this.sessionPauseThreshold) {\n this.events = [];\n }\n this.events.push({\n key: keyEvent.key,\n type: 'down',\n timestamp: now,\n targetElement: this.focusedElementSelector,\n });\n // Notify detector - keystrokes are valuable events\n this.notifyEvent(0.8);\n this.lastEventTimestamp = now;\n };\n this.upListener = (e) => {\n if (!this.focusedElement)\n return; // No input focused\n const now = Date.now();\n const keyEvent = e;\n // Clear events if pause > 1s (new typing session)\n if (this.lastEventTimestamp > 0 && now - this.lastEventTimestamp > this.sessionPauseThreshold) {\n this.events = [];\n }\n this.events.push({\n key: keyEvent.key,\n type: 'up',\n timestamp: now,\n targetElement: this.focusedElementSelector,\n });\n this.lastEventTimestamp = now;\n };\n document.addEventListener('keydown', this.downListener);\n document.addEventListener('keyup', this.upListener);\n }\n /**\n * Add a new target selector at runtime\n */\n addTarget(selector) {\n if (!this.targetSelectors.includes(selector)) {\n this.targetSelectors.push(selector);\n if (this.isActive) {\n this.attachFocusListenersForSelector(selector);\n }\n }\n }\n attachFocusListeners() {\n this.targetSelectors.forEach(selector => {\n this.attachFocusListenersForSelector(selector);\n });\n }\n attachFocusListenersForSelector(selector) {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (this.focusListeners.has(element))\n return; // Already attached\n const focusListener = () => {\n this.focusedElement = element;\n this.focusedElementSelector = selector;\n };\n const blurListener = () => {\n this.focusedElement = null;\n this.focusedElementSelector = '';\n };\n element.addEventListener('focus', focusListener);\n element.addEventListener('blur', blurListener);\n this.focusListeners.set(element, focusListener);\n this.blurListeners.set(element, blurListener);\n });\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.downListener) {\n document.removeEventListener('keydown', this.downListener);\n this.downListener = null;\n }\n if (this.upListener) {\n document.removeEventListener('keyup', this.upListener);\n this.upListener = null;\n }\n // Remove focus/blur listeners\n this.focusListeners.forEach((listener, element) => {\n element.removeEventListener('focus', listener);\n });\n this.focusListeners.clear();\n this.blurListeners.forEach((listener, element) => {\n element.removeEventListener('blur', listener);\n });\n this.blurListeners.clear();\n this.focusedElement = null;\n }\n reset() {\n this.events = [];\n this.focusedElement = null;\n this.focusedElementSelector = '';\n this.lastEventTimestamp = 0;\n }\n score() {\n if (this.events.length < 6)\n return undefined; // Need at least 3 key pairs\n const downEvents = this.events.filter(e => e.type === 'down');\n if (downEvents.length < 3)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. Analyze keystroke intervals (time between keydown events)\n const keystrokeIntervals = [];\n for (let i = 1; i < downEvents.length; i++) {\n keystrokeIntervals.push(downEvents[i].timestamp - downEvents[i - 1].timestamp);\n }\n const keystrokeAnalysis = analyzeIntervals(keystrokeIntervals);\n if (keystrokeAnalysis) {\n const { statistics, allIdentical } = keystrokeAnalysis;\n // Keyboard-specific heuristics for keystroke timing\n if (allIdentical) {\n return 0.1; // All identical - bot!\n }\n const keystrokeScore = scoreCoefficientOfVariation(statistics.cv);\n score += keystrokeScore;\n factors++;\n // Early return if bot detected\n if (keystrokeScore <= 0.1)\n return keystrokeScore;\n }\n // 2. Analyze press durations (keydown-to-keyup duration)\n const pressDurations = [];\n for (let i = 0; i < this.events.length - 1; i++) {\n if (this.events[i].type === 'down' && this.events[i + 1].type === 'up' &&\n this.events[i].key === this.events[i + 1].key) {\n pressDurations.push(this.events[i + 1].timestamp - this.events[i].timestamp);\n }\n }\n const pressDurationAnalysis = analyzeIntervals(pressDurations);\n if (pressDurationAnalysis) {\n const { statistics, allIdentical } = pressDurationAnalysis;\n // Keyboard-specific heuristics for press duration\n if (allIdentical) {\n return 0.1; // All identical - bot!\n }\n // Check for suspiciously fast key releases (bots often have <5ms press duration)\n if (statistics.mean < 5) {\n score += 0.1; // Too fast = bot (instant release)\n factors++;\n }\n else {\n const pressDurationScore = scoreCoefficientOfVariation(statistics.cv);\n score += pressDurationScore;\n factors++;\n // Early return if bot detected\n if (pressDurationScore <= 0.1)\n return pressDurationScore;\n }\n }\n // 3. Bonus for backspace usage (human error correction)\n const backspaceCount = this.events.filter(e => e.key === 'Backspace').length;\n if (backspaceCount > 0) {\n // Natural human behavior - making corrections\n const backspaceRatio = backspaceCount / downEvents.length;\n if (backspaceRatio > 0.05 && backspaceRatio < 0.3) {\n score += 1.0; // Reasonable error correction\n factors++;\n }\n else if (backspaceRatio > 0) {\n score += 0.8; // Some backspaces\n factors++;\n }\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n // Calculate press durations for visualization\n const pressDurations = [];\n for (let i = 0; i < this.events.length - 1; i++) {\n if (this.events[i].type === 'down' && this.events[i + 1].type === 'up' &&\n this.events[i].key === this.events[i + 1].key) {\n pressDurations.push(this.events[i + 1].timestamp - this.events[i].timestamp);\n }\n }\n return {\n eventCount: this.events.length,\n downEvents: this.events.filter(e => e.type === 'down').length,\n upEvents: this.events.filter(e => e.type === 'up').length,\n backspaceCount: this.events.filter(e => e.key === 'Backspace').length,\n pressDurations, // For graphing\n focusedElement: this.focusedElementSelector,\n trackedElements: this.focusListeners.size,\n };\n }\n}\n", "/**\n * Environment Fingerprinting Strategy\n * Captures browser environment on initialization and tick updates\n * Includes critical automation/bot detection signals\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { inverseSigmoid, gaussian } from '../math-utils.js';\n/**\n * Automation framework globals that indicate bot activity\n * These are injected by various testing/automation frameworks\n */\nconst AUTOMATION_GLOBALS = [\n '__nightmare',\n '_phantom',\n 'callPhantom',\n '__selenium_evaluate',\n '__webdriver_evaluate',\n '__driver_evaluate',\n '__webdriver_script_function',\n '__lastWatirAlert',\n '__lastWatirConfirm',\n '__lastWatirPrompt',\n '_Selenium_IDE_Recorder',\n 'domAutomation',\n 'domAutomationController',\n 'webdriver',\n '_webdriver_script_fn',\n '__webdriver_script_func',\n '__fxdriver_evaluate',\n '__fxdriver_unwrapped',\n '__selenium_unwrapped',\n];\nexport class EnvironmentStrategy extends BaseStrategy {\n constructor() {\n super(...arguments);\n this.name = 'environment';\n this.defaultWeight = 0.08;\n this.data = null;\n }\n start() {\n this.captureEnvironment();\n }\n stop() {\n // Environment data persists\n }\n reset() {\n this.data = null;\n }\n onTick(_timestamp) {\n // Re-capture environment periodically to detect changes\n this.captureEnvironment();\n }\n score() {\n if (!this.data)\n return undefined;\n const env = this.data;\n const auto = env.automation;\n // ============================================\n // IMMEDIATE DISQUALIFICATION - HIGH CONFIDENCE BOT SIGNALS\n // ============================================\n // P0: navigator.webdriver === true (HIGHEST PRIORITY)\n // This is the most reliable automation indicator\n if (auto.isWebdriver) {\n return 0.05;\n }\n // P0: Automation framework globals detected\n if (auto.hasAutomationGlobals) {\n return 0.1;\n }\n // P0: CDP injection detected (Chrome DevTools Protocol)\n if (auto.hasCDPInjection) {\n return 0.1;\n }\n // P2: Headless browser detection\n // Multiple headless indicators = very likely bot\n const headlessIndicatorCount = [\n auto.hasHeadlessUA,\n auto.hasChromelessRuntime,\n auto.hasSoftwareRenderer,\n ].filter(Boolean).length;\n if (headlessIndicatorCount >= 2) {\n return 0.15;\n }\n // Single strong headless indicator\n if (auto.hasHeadlessUA) {\n return 0.2;\n }\n // ============================================\n // WEIGHTED SCORING FOR OTHER SIGNALS\n // ============================================\n let score = 0;\n let factors = 0;\n // Suspicious indicators\n score += env.suspiciousDimensions ? 0.1 : 1.0;\n score += env.suspiciousRatio ? 0.2 : 1.0;\n score += env.featureInconsistency ? 0.3 : 1.0;\n factors += 3;\n // Browser features\n const featureCount = [\n env.hasWebGL,\n env.hasLocalStorage,\n env.hasSessionStorage,\n env.hasIndexedDB,\n ].filter(Boolean).length;\n score += featureCount / 4;\n factors++;\n // Plugins (only suspicious on desktop)\n if (!env.isMobile) {\n score += inverseSigmoid(env.plugins, -2, -0.5);\n score += (env.plugins > 0 ? 1.0 : 0.1);\n factors += 2;\n // No plugins on desktop Chrome = suspicious (but not conclusive)\n if (auto.hasNoPlugins && env.vendor.includes('Google')) {\n score += 0.3;\n factors++;\n }\n }\n // Chromeless runtime (window.chrome but no chrome.runtime)\n if (auto.hasChromelessRuntime) {\n score += 0.3;\n factors++;\n }\n // Software renderer (SwiftShader)\n if (auto.hasSoftwareRenderer) {\n score += 0.4;\n factors++;\n }\n // Device\n score += gaussian(env.devicePixelRatio, 2, 1.5);\n score += (env.colorDepth === 24 || env.colorDepth === 32) ? 1.0 : 0.4;\n factors += 2;\n return factors > 0 ? score / factors : undefined;\n }\n isMobileDevice() {\n // Multiple checks for mobile detection\n const hasTouchScreen = navigator.maxTouchPoints > 0 || 'ontouchstart' in window;\n const mobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n const smallScreen = window.innerWidth < 768 && window.innerHeight < 1024;\n return (hasTouchScreen && smallScreen) || mobileUA;\n }\n /**\n * Detect automation indicators\n */\n detectAutomation() {\n const isMobile = this.isMobileDevice();\n // 1. navigator.webdriver - HIGHEST PRIORITY\n const isWebdriver = navigator.webdriver === true;\n // 2. Headless UA detection\n const ua = navigator.userAgent;\n const hasHeadlessUA = /HeadlessChrome|Headless/i.test(ua);\n // 3. Chrome without runtime (headless Chrome indicator)\n const win = window;\n const hasChromelessRuntime = !!(win.chrome &&\n typeof win.chrome === 'object' &&\n !win.chrome.runtime);\n // 4. Automation framework globals\n const detectedGlobals = [];\n for (const global of AUTOMATION_GLOBALS) {\n if (global in win) {\n detectedGlobals.push(global);\n }\n }\n const hasAutomationGlobals = detectedGlobals.length > 0;\n // 5. CDP (Chrome DevTools Protocol) injection detection\n // CDP injects properties matching pattern: cdc_ or __cdc_\n const detectedCDPKeys = [];\n try {\n for (const key of Object.keys(win)) {\n if (/^cdc_|^__cdc_/.test(key)) {\n detectedCDPKeys.push(key);\n }\n }\n }\n catch (_a) {\n // Some environments throw on Object.keys(window)\n }\n const hasCDPInjection = detectedCDPKeys.length > 0;\n // 6. No plugins on desktop (suspicious)\n const hasNoPlugins = !isMobile && navigator.plugins.length === 0;\n // 7. Software renderer detection (SwiftShader, ANGLE without GPU)\n let hasSoftwareRenderer = false;\n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n if (gl) {\n const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n if (debugInfo) {\n const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);\n // SwiftShader = headless Chrome software renderer\n // ANGLE without real GPU = suspicious\n hasSoftwareRenderer = /SwiftShader|Software|LLVMpipe/i.test(renderer);\n // Store for debugging\n this._webglRenderer = renderer;\n }\n }\n }\n catch (_b) {\n // WebGL not available\n }\n return {\n isWebdriver,\n hasHeadlessUA,\n hasChromelessRuntime,\n hasSoftwareRenderer,\n hasNoPlugins,\n hasAutomationGlobals,\n detectedGlobals,\n hasCDPInjection,\n detectedCDPKeys,\n };\n }\n captureEnvironment() {\n try {\n // WebGL detection\n let hasWebGL = false;\n let webglRenderer;\n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n hasWebGL = !!gl;\n if (gl) {\n const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n if (debugInfo) {\n webglRenderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);\n }\n }\n }\n catch (e) {\n hasWebGL = false;\n }\n // WebRTC detection\n const hasWebRTC = !!(window.RTCPeerConnection ||\n window.mozRTCPeerConnection ||\n window.webkitRTCPeerConnection);\n // Mobile detection\n const isMobile = this.isMobileDevice();\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const screenWidth = window.screen.width;\n const screenHeight = window.screen.height;\n // Suspicious dimensions\n const suspiciousDimensions = (windowWidth === 800 && windowHeight === 600) ||\n (windowWidth === 1024 && windowHeight === 768) ||\n (windowWidth === 1280 && windowHeight === 720) ||\n (screenWidth === 800 && screenHeight === 600);\n // Suspicious ratio\n const windowScreenRatio = (windowWidth * windowHeight) / (screenWidth * screenHeight);\n const suspiciousRatio = windowScreenRatio === 1.0 ||\n windowScreenRatio < 0.1 ||\n windowScreenRatio > 1.0;\n // Feature inconsistency\n const hasStorage = typeof localStorage !== 'undefined' && typeof sessionStorage !== 'undefined';\n const featureInconsistency = (navigator.plugins.length === 0 && navigator.mimeTypes.length === 0) ||\n !hasWebGL ||\n !hasStorage;\n // Detect automation indicators\n const automation = this.detectAutomation();\n this.data = {\n screenWidth,\n screenHeight,\n windowWidth,\n windowHeight,\n devicePixelRatio: window.devicePixelRatio,\n colorDepth: window.screen.colorDepth,\n userAgent: navigator.userAgent,\n platform: navigator.platform,\n language: navigator.language,\n languages: navigator.languages ? Array.from(navigator.languages) : [navigator.language],\n hardwareConcurrency: navigator.hardwareConcurrency,\n maxTouchPoints: navigator.maxTouchPoints || 0,\n vendor: navigator.vendor,\n hasWebGL,\n hasWebRTC,\n hasLocalStorage: typeof localStorage !== 'undefined',\n hasSessionStorage: typeof sessionStorage !== 'undefined',\n hasIndexedDB: 'indexedDB' in window,\n plugins: navigator.plugins.length,\n mimeTypes: navigator.mimeTypes.length,\n suspiciousRatio,\n suspiciousDimensions,\n featureInconsistency,\n isMobile,\n timestamp: Date.now(),\n automation,\n webglRenderer,\n };\n }\n catch (_a) {\n // Silent fail - environment capture is best effort\n }\n }\n getDebugInfo() {\n return this.data;\n }\n /**\n * Check if current device is mobile\n * Returns true if mobile, false otherwise\n * Returns null if environment hasn't been captured yet\n */\n isMobile() {\n var _a, _b;\n return (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.isMobile) !== null && _b !== void 0 ? _b : null;\n }\n /**\n * Get automation detection results\n * Returns null if environment hasn't been captured yet\n */\n getAutomationIndicators() {\n var _a, _b;\n return (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.automation) !== null && _b !== void 0 ? _b : null;\n }\n /**\n * Quick check if any strong automation indicator is present\n * Returns true if likely a bot, false if likely human, null if not checked yet\n */\n isLikelyBot() {\n if (!this.data)\n return null;\n const auto = this.data.automation;\n return (auto.isWebdriver ||\n auto.hasAutomationGlobals ||\n auto.hasCDPInjection ||\n auto.hasHeadlessUA);\n }\n}\n", "/**\n * Resize Behavior Detection Strategy\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { inverseSigmoid, sigmoid } from '../math-utils.js';\nexport class ResizeStrategy extends BaseStrategy {\n constructor() {\n super(...arguments);\n this.name = 'resize';\n this.defaultWeight = 0.02;\n this.events = [];\n this.listener = null;\n this.isActive = false;\n this.lastMousePosition = null;\n this.mouseListener = null;\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Track mouse for resize detection\n this.mouseListener = (e) => {\n const mouseEvent = e;\n this.lastMousePosition = {\n x: mouseEvent.clientX,\n y: mouseEvent.clientY,\n };\n };\n document.addEventListener('mousemove', this.mouseListener, { passive: true });\n // Track resizes\n this.listener = () => {\n var _a, _b;\n const mouseX = (_a = this.lastMousePosition) === null || _a === void 0 ? void 0 : _a.x;\n const mouseY = (_b = this.lastMousePosition) === null || _b === void 0 ? void 0 : _b.y;\n let mouseNearEdge = false;\n if (mouseX !== undefined && mouseY !== undefined) {\n const edgeThreshold = 50;\n mouseNearEdge = (mouseX < edgeThreshold ||\n mouseX > window.innerWidth - edgeThreshold ||\n mouseY < edgeThreshold ||\n mouseY > window.innerHeight - edgeThreshold);\n }\n this.events.push({\n width: window.innerWidth,\n height: window.innerHeight,\n mouseX,\n mouseY,\n mouseNearEdge,\n timestamp: Date.now(),\n });\n };\n window.addEventListener('resize', this.listener);\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.listener) {\n window.removeEventListener('resize', this.listener);\n this.listener = null;\n }\n if (this.mouseListener) {\n document.removeEventListener('mousemove', this.mouseListener);\n this.mouseListener = null;\n }\n }\n reset() {\n this.events = [];\n }\n score() {\n if (this.events.length === 0)\n return undefined;\n let score = 0;\n let factors = 0;\n // Frequency\n score += inverseSigmoid(this.events.length, 5, 0.5);\n factors++;\n // Mouse near edge\n const withMouse = this.events.filter(e => e.mouseX !== undefined);\n if (withMouse.length > 0) {\n const nearEdge = withMouse.filter(e => e.mouseNearEdge).length;\n score += sigmoid(nearEdge / withMouse.length, 0.5, 8);\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n getDebugInfo() {\n return {\n eventCount: this.events.length,\n withMouseData: this.events.filter(e => e.mouseX !== undefined).length,\n };\n }\n}\n", "/**\n * Timing Analysis Strategy\n * Detects bot-like timing patterns in user interactions\n *\n * Key detection signals:\n * - Pre-action stillness (humans have micro-movements before clicking)\n * - Action timing patterns (machine-precise intervals)\n * - Inactivity patterns (bursts after long silence, no idle variance)\n * - Actions while tab is hidden (bots ignore visibility)\n */\nimport { BaseStrategy } from '../strategy.js';\nimport { calculateStatistics } from '../math-utils.js';\nexport class TimingStrategy extends BaseStrategy {\n constructor() {\n super(...arguments);\n this.name = 'timing';\n this.defaultWeight = 0.15;\n this.actions = [];\n this.mouseStillness = {\n position: null,\n lastMoveTime: 0,\n microMovementCount: 0,\n };\n this.microMovements = [];\n this.isActive = false;\n this.mouseListener = null;\n this.clickListener = null;\n this.keydownListener = null;\n this.scrollListener = null;\n /** Time window to consider for pre-action stillness (ms) */\n this.STILLNESS_WINDOW = 500;\n /** Minimum distance to count as meaningful movement (px) */\n this.MICRO_MOVEMENT_THRESHOLD = 1;\n /** Maximum micro-movement to count (jitter vs intentional) (px) */\n this.MAX_MICRO_MOVEMENT = 5;\n /** Machine-precision threshold (intervals within this are suspicious) */\n this.MACHINE_PRECISION_THRESHOLD = 5; // 5ms\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Track mouse movement for stillness detection\n this.mouseListener = (e) => {\n const mouseEvent = e;\n const now = Date.now();\n const currentPos = { x: mouseEvent.clientX, y: mouseEvent.clientY };\n if (this.mouseStillness.position) {\n const dx = currentPos.x - this.mouseStillness.position.x;\n const dy = currentPos.y - this.mouseStillness.position.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n // Track micro-movements (1-5px range)\n if (distance >= this.MICRO_MOVEMENT_THRESHOLD && distance <= this.MAX_MICRO_MOVEMENT) {\n this.microMovements.push({ timestamp: now, distance });\n }\n // Any meaningful movement updates the last move time\n if (distance >= this.MICRO_MOVEMENT_THRESHOLD) {\n this.mouseStillness.lastMoveTime = now;\n }\n }\n this.mouseStillness.position = currentPos;\n // Clean up old micro-movements (keep only last STILLNESS_WINDOW)\n const cutoff = now - this.STILLNESS_WINDOW;\n this.microMovements = this.microMovements.filter(m => m.timestamp >= cutoff);\n };\n // Track clicks with timing context\n this.clickListener = (e) => {\n this.recordAction('click', e);\n };\n // Track keydown with timing context\n this.keydownListener = () => {\n this.recordAction('keydown');\n };\n // Track scroll with timing context\n this.scrollListener = () => {\n this.recordAction('scroll');\n };\n document.addEventListener('mousemove', this.mouseListener, { passive: true });\n document.addEventListener('click', this.clickListener, { passive: true });\n document.addEventListener('keydown', this.keydownListener, { passive: true });\n document.addEventListener('scroll', this.scrollListener, { passive: true });\n }\n recordAction(type, _event) {\n const now = Date.now();\n // Calculate time since last mouse movement\n const timeSinceMouseMove = this.mouseStillness.lastMoveTime > 0\n ? now - this.mouseStillness.lastMoveTime\n : -1;\n // Count micro-movements in stillness window (already filtered in mouse listener)\n this.mouseStillness.microMovementCount = this.microMovements.length;\n this.actions.push({\n type,\n timestamp: now,\n timeSinceMouseMove,\n wasHidden: document.hidden,\n });\n // Notify detector\n this.notifyEvent(0.7);\n // Keep only last 100 actions for memory efficiency (shift is O(n) but rare)\n if (this.actions.length > 100) {\n this.actions.shift();\n }\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.mouseListener) {\n document.removeEventListener('mousemove', this.mouseListener);\n this.mouseListener = null;\n }\n if (this.clickListener) {\n document.removeEventListener('click', this.clickListener);\n this.clickListener = null;\n }\n if (this.keydownListener) {\n document.removeEventListener('keydown', this.keydownListener);\n this.keydownListener = null;\n }\n if (this.scrollListener) {\n document.removeEventListener('scroll', this.scrollListener);\n this.scrollListener = null;\n }\n }\n reset() {\n this.actions = [];\n this.microMovements = [];\n this.mouseStillness = {\n position: null,\n lastMoveTime: 0,\n microMovementCount: 0,\n };\n }\n score() {\n const actionCount = this.actions.length;\n if (actionCount < 3)\n return undefined;\n let score = 0;\n let factors = 0;\n // Cache filtered arrays to avoid repeated iteration\n const clicks = [];\n const clicksWithMouse = [];\n let hiddenCount = 0;\n for (const action of this.actions) {\n if (action.type === 'click') {\n clicks.push(action);\n if (action.timeSinceMouseMove >= 0) {\n clicksWithMouse.push(action);\n }\n }\n if (action.wasHidden)\n hiddenCount++;\n }\n // 1. Pre-action stillness detection\n if (clicks.length >= 2) {\n const stillnessScore = this.scorePreActionStillness(clicks);\n if (stillnessScore !== undefined) {\n score += stillnessScore;\n factors++;\n }\n }\n // 2. Mouse-to-action delay analysis\n if (clicksWithMouse.length >= 3) {\n const mouseToClickScore = this.scoreMouseToClickDelayFromCache(clicksWithMouse);\n if (mouseToClickScore !== undefined) {\n score += mouseToClickScore;\n factors++;\n }\n }\n // 3. Action interval patterns\n if (actionCount >= 5) {\n const intervalScore = this.scoreActionIntervals();\n if (intervalScore !== undefined) {\n score += intervalScore;\n factors++;\n }\n }\n // 4. Hidden document actions\n const hiddenScore = this.scoreHiddenActionsFromCount(hiddenCount, actionCount);\n score += hiddenScore;\n factors++;\n return factors > 0 ? score / factors : undefined;\n }\n /**\n * Score based on pre-action stillness\n * Humans have micro-movements before clicking; bots are perfectly still\n */\n scorePreActionStillness(clicks) {\n // Look at clicks with mouse data\n const clicksWithMouseData = clicks.filter(c => c.timeSinceMouseMove >= 0);\n if (clicksWithMouseData.length < 2)\n return undefined;\n // Count clicks with zero pre-action movement (100-500ms window)\n const perfectlyStillClicks = clicksWithMouseData.filter(c => {\n // Time since mouse move in the suspicious range (100-500ms of perfect stillness)\n return c.timeSinceMouseMove >= 100 && c.timeSinceMouseMove <= 500 &&\n this.mouseStillness.microMovementCount === 0;\n }).length;\n const stillRatio = perfectlyStillClicks / clicksWithMouseData.length;\n // High ratio of perfectly still clicks = likely bot\n // 0% still = very human (1.0)\n // 50%+ still = suspicious (0.3)\n // 100% still = very bot-like (0.1)\n if (stillRatio >= 0.9)\n return 0.1;\n if (stillRatio >= 0.7)\n return 0.3;\n if (stillRatio >= 0.5)\n return 0.5;\n if (stillRatio >= 0.3)\n return 0.7;\n return 1.0;\n }\n /**\n * Score mouse-to-click delay patterns (using pre-filtered cache)\n */\n scoreMouseToClickDelayFromCache(clicksWithMouse) {\n const delays = clicksWithMouse.map(c => c.timeSinceMouseMove);\n const stats = calculateStatistics(delays);\n // Suspiciously fast clicks (< 10ms average)\n if (stats.mean < 10)\n return 0.1;\n // Suspiciously consistent delays (CV < 0.2)\n if (stats.cv < 0.2 && clicksWithMouse.length >= 5)\n return 0.2;\n // Normal human range (50-300ms with variation)\n if (stats.mean >= 50 && stats.mean <= 300 && stats.cv >= 0.3)\n return 1.0;\n // Somewhat suspicious\n if (stats.cv < 0.4)\n return 0.6;\n return 0.8;\n }\n /**\n * Score action intervals for machine-like precision\n * Detects exact intervals: 100ms, 500ms, 1000ms\n */\n scoreActionIntervals() {\n if (this.actions.length < 5)\n return undefined;\n const intervals = [];\n for (let i = 1; i < this.actions.length; i++) {\n intervals.push(this.actions[i].timestamp - this.actions[i - 1].timestamp);\n }\n // Check for machine-precise intervals (multiples of common values)\n const machineIntervals = [100, 200, 250, 500, 1000];\n let preciseCount = 0;\n for (const interval of intervals) {\n for (const machineInterval of machineIntervals) {\n // Check if interval is within threshold of machine interval or its multiples\n const remainder = interval % machineInterval;\n if (remainder < this.MACHINE_PRECISION_THRESHOLD ||\n (machineInterval - remainder) < this.MACHINE_PRECISION_THRESHOLD) {\n preciseCount++;\n break;\n }\n }\n }\n const preciseRatio = preciseCount / intervals.length;\n // High ratio of machine-precise intervals = bot\n if (preciseRatio >= 0.8)\n return 0.1;\n if (preciseRatio >= 0.6)\n return 0.3;\n if (preciseRatio >= 0.4)\n return 0.5;\n // Also check coefficient of variation (should be high for humans)\n const stats = calculateStatistics(intervals);\n if (stats.cv < 0.15)\n return 0.2; // Too consistent\n return 1.0;\n }\n /**\n * Score based on actions while document was hidden (using pre-computed count)\n */\n scoreHiddenActionsFromCount(hiddenCount, totalCount) {\n if (hiddenCount === 0)\n return 1.0; // Perfect - no hidden actions\n const hiddenRatio = hiddenCount / totalCount;\n // Any hidden actions are suspicious\n if (hiddenRatio > 0.5)\n return 0.1; // Major bot indicator\n if (hiddenRatio > 0.2)\n return 0.3;\n if (hiddenRatio > 0)\n return 0.5;\n return 1.0;\n }\n getDebugInfo() {\n const clicks = this.actions.filter(a => a.type === 'click');\n const intervals = [];\n for (let i = 1; i < this.actions.length; i++) {\n intervals.push(this.actions[i].timestamp - this.actions[i - 1].timestamp);\n }\n return {\n actionCount: this.actions.length,\n clickCount: clicks.length,\n keydownCount: this.actions.filter(a => a.type === 'keydown').length,\n scrollCount: this.actions.filter(a => a.type === 'scroll').length,\n hiddenActionCount: this.actions.filter(a => a.wasHidden).length,\n microMovementCount: this.microMovements.length,\n intervals: intervals.slice(-20), // Last 20 intervals\n lastStillnessDuration: this.mouseStillness.lastMoveTime > 0\n ? Date.now() - this.mouseStillness.lastMoveTime\n : null,\n };\n }\n}\n", "/**\n * Visibility Strategy\n * Detects bot-like behavior based on tab visibility and focus patterns\n *\n * Key detection signals:\n * - Actions while document.hidden === true (bots ignore visibility)\n * - No pause when tab loses focus\n * - Activity resumes too quickly after tab regains focus\n * - Focus patterns: humans focus inputs before typing\n */\nimport { BaseStrategy } from '../strategy.js';\nexport class VisibilityStrategy extends BaseStrategy {\n constructor() {\n super(...arguments);\n this.name = 'visibility';\n this.defaultWeight = 0.10;\n this.events = [];\n this.focusTypingPairs = [];\n this.actionsWhileHidden = 0;\n this.lastVisibilityChange = null;\n this.resumeDelays = [];\n this.isActive = false;\n // Listeners\n this.visibilityListener = null;\n this.focusListener = null;\n this.blurListener = null;\n this.clickListener = null;\n this.keydownListener = null;\n this.inputFocusListener = null;\n // State\n this.lastFocusedInput = null;\n this.hasTypedInFocusedInput = false;\n this.lastActionTime = 0;\n this.preHideActionTime = 0;\n }\n start() {\n if (this.isActive)\n return;\n this.isActive = true;\n // Track visibility changes\n this.visibilityListener = () => {\n const now = Date.now();\n const wasHidden = document.hidden;\n // Track time between visibility changes\n if (this.lastVisibilityChange && !wasHidden) {\n // Tab just became visible again\n // Check if there was activity right before becoming visible\n // Humans need time to refocus after tab switch\n if (this.lastActionTime > 0 && this.preHideActionTime > 0) {\n const timeSinceLastAction = now - this.lastActionTime;\n // If action was very recent (< 50ms), suspicious\n if (timeSinceLastAction < 50) {\n this.actionsWhileHidden++;\n }\n }\n // Track resume delay (time until first action after visibility)\n // Will be calculated when next action occurs\n this.lastVisibilityChange = { hidden: false, timestamp: now };\n }\n else if (wasHidden) {\n // Tab just became hidden - record pre-hide action time\n this.preHideActionTime = this.lastActionTime;\n this.lastVisibilityChange = { hidden: true, timestamp: now };\n }\n this.events.push({\n type: 'visibility_change',\n timestamp: now,\n wasHidden,\n });\n };\n // Track window focus\n this.focusListener = () => {\n this.events.push({\n type: 'focus_change',\n timestamp: Date.now(),\n wasHidden: document.hidden,\n wasFocused: true,\n });\n };\n this.blurListener = () => {\n this.events.push({\n type: 'focus_change',\n timestamp: Date.now(),\n wasHidden: document.hidden,\n wasFocused: false,\n });\n };\n // Track actions while hidden\n this.clickListener = (e) => {\n this.recordAction('click', e);\n };\n this.keydownListener = (e) => {\n this.recordAction('keydown', e);\n // Track focus-to-keypress timing\n if (this.lastFocusedInput && !this.hasTypedInFocusedInput) {\n const now = Date.now();\n const delay = now - this.lastFocusedInput.timestamp;\n this.focusTypingPairs.push({\n focusTime: this.lastFocusedInput.timestamp,\n firstKeypressTime: now,\n delay,\n element: this.lastFocusedInput.element,\n });\n this.hasTypedInFocusedInput = true;\n }\n };\n // Track input focus for focus-typing analysis\n this.inputFocusListener = (e) => {\n const target = e.target;\n if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')) {\n this.lastFocusedInput = {\n element: target.tagName.toLowerCase(),\n timestamp: Date.now(),\n };\n this.hasTypedInFocusedInput = false;\n }\n };\n document.addEventListener('visibilitychange', this.visibilityListener);\n window.addEventListener('focus', this.focusListener);\n window.addEventListener('blur', this.blurListener);\n document.addEventListener('click', this.clickListener, { passive: true });\n document.addEventListener('keydown', this.keydownListener, { passive: true });\n document.addEventListener('focusin', this.inputFocusListener, { passive: true });\n }\n recordAction(_type, _event) {\n const now = Date.now();\n this.lastActionTime = now;\n // Check if action occurred while document was hidden\n if (document.hidden) {\n this.actionsWhileHidden++;\n this.events.push({\n type: 'action_while_hidden',\n timestamp: now,\n wasHidden: true,\n });\n // Notify detector - this is a strong bot signal\n this.notifyEvent(1.0);\n }\n // Track resume delay after visibility change\n if (this.lastVisibilityChange && !this.lastVisibilityChange.hidden) {\n const resumeDelay = now - this.lastVisibilityChange.timestamp;\n // Only count if this is the first action after becoming visible\n // and the delay is reasonable (< 10 seconds)\n if (resumeDelay > 0 && resumeDelay < 10000 && this.resumeDelays.length < 20) {\n // Check if we haven't already recorded a delay for this visibility change\n const lastRecordedDelay = this.resumeDelays[this.resumeDelays.length - 1];\n if (lastRecordedDelay === undefined || Math.abs(resumeDelay - lastRecordedDelay) > 100) {\n this.resumeDelays.push(resumeDelay);\n }\n }\n }\n }\n stop() {\n if (!this.isActive)\n return;\n this.isActive = false;\n if (this.visibilityListener) {\n document.removeEventListener('visibilitychange', this.visibilityListener);\n this.visibilityListener = null;\n }\n if (this.focusListener) {\n window.removeEventListener('focus', this.focusListener);\n this.focusListener = null;\n }\n if (this.blurListener) {\n window.removeEventListener('blur', this.blurListener);\n this.blurListener = null;\n }\n if (this.clickListener) {\n document.removeEventListener('click', this.clickListener);\n this.clickListener = null;\n }\n if (this.keydownListener) {\n document.removeEventListener('keydown', this.keydownListener);\n this.keydownListener = null;\n }\n if (this.inputFocusListener) {\n document.removeEventListener('focusin', this.inputFocusListener);\n this.inputFocusListener = null;\n }\n }\n reset() {\n this.events = [];\n this.focusTypingPairs = [];\n this.actionsWhileHidden = 0;\n this.lastVisibilityChange = null;\n this.resumeDelays = [];\n this.lastFocusedInput = null;\n this.hasTypedInFocusedInput = false;\n this.lastActionTime = 0;\n this.preHideActionTime = 0;\n }\n score() {\n // Need some visibility events to score\n if (this.events.length < 2)\n return undefined;\n let score = 0;\n let factors = 0;\n // 1. Actions while hidden (strongest signal)\n const hiddenActionScore = this.scoreHiddenActions();\n if (hiddenActionScore !== undefined) {\n score += hiddenActionScore;\n factors++;\n }\n // 2. Resume delay analysis\n const resumeScore = this.scoreResumeDelays();\n if (resumeScore !== undefined) {\n score += resumeScore;\n factors++;\n }\n // 3. Focus-typing pattern\n const focusTypingScore = this.scoreFocusTyping();\n if (focusTypingScore !== undefined) {\n score += focusTypingScore;\n factors++;\n }\n return factors > 0 ? score / factors : undefined;\n }\n /**\n * Score based on actions while document was hidden\n * Humans can't interact with hidden tabs; bots can\n */\n scoreHiddenActions() {\n if (this.actionsWhileHidden === 0)\n return 1.0; // Perfect\n // Any action while hidden is highly suspicious\n if (this.actionsWhileHidden >= 5)\n return 0.1;\n if (this.actionsWhileHidden >= 3)\n return 0.2;\n if (this.actionsWhileHidden >= 1)\n return 0.3;\n return 1.0;\n }\n /**\n * Score based on how quickly activity resumes after tab becomes visible\n * Humans need time to refocus (100-500ms minimum)\n * Bots often resume instantly (< 50ms)\n */\n scoreResumeDelays() {\n if (this.resumeDelays.length < 2)\n return undefined;\n // Count suspiciously fast resumes (< 50ms)\n const fastResumeCount = this.resumeDelays.filter(d => d < 50).length;\n const fastResumeRatio = fastResumeCount / this.resumeDelays.length;\n if (fastResumeRatio >= 0.8)\n return 0.1;\n if (fastResumeRatio >= 0.5)\n return 0.3;\n if (fastResumeRatio >= 0.3)\n return 0.5;\n if (fastResumeRatio > 0)\n return 0.7;\n return 1.0;\n }\n /**\n * Score based on focus-to-keypress timing\n * Humans focus inputs before typing (natural delay 100-500ms)\n * Bots often type without focusing or with instant delay\n */\n scoreFocusTyping() {\n if (this.focusTypingPairs.length < 2)\n return undefined;\n let suspiciousCount = 0;\n for (const pair of this.focusTypingPairs) {\n // Instant typing after focus (< 20ms) is suspicious\n if (pair.delay < 20) {\n suspiciousCount++;\n }\n }\n const suspiciousRatio = suspiciousCount / this.focusTypingPairs.length;\n if (suspiciousRatio >= 0.8)\n return 0.2;\n if (suspiciousRatio >= 0.5)\n return 0.4;\n if (suspiciousRatio >= 0.3)\n return 0.6;\n if (suspiciousRatio > 0)\n return 0.8;\n return 1.0;\n }\n getDebugInfo() {\n return {\n eventCount: this.events.length,\n actionsWhileHidden: this.actionsWhileHidden,\n visibilityChanges: this.events.filter(e => e.type === 'visibility_change').length,\n focusChanges: this.events.filter(e => e.type === 'focus_change').length,\n resumeDelays: this.resumeDelays,\n focusTypingPairs: this.focusTypingPairs.map(p => ({\n delay: p.delay,\n element: p.element,\n })),\n };\n }\n}\n", "export const DEFAULT_SETTINGS = {\n sampleRates: {\n mouseMove: 0.1, // Track 10% of mouse moves\n scroll: 1.0, // Track ALL scrolls - critical for detection\n keypress: 1.0, // Track all keypresses\n },\n rollingWindows: {\n mouseMove: 30000,\n scroll: 30000,\n },\n weights: {\n mouseMovement: 0.30, // Increased - continuous behavioral signal\n clickAccuracy: 0.30, // Increased - critical behavioral signal\n scrollBehavior: 0.15, // Unchanged\n keyboardTiming: 0.10, // Slightly reduced\n tabActivity: 0.05, // Unchanged\n resizeBehavior: 0.02, // Reduced - less reliable\n environmentFingerprint: 0.08, // Reduced - static signal, one-time check\n },\n customScorers: {},\n clickMouseHistoryWindow: 1000,\n useWebWorker: false, // Will implement Web Worker support in phase 2\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["BehaviorDetector", "tickOptions", "strategy", "weight", "config", "event", "strategyWeight", "contribution", "name", "enabled", "_", "options", "breakdown", "result", "_a", "_b", "counts", "debug", "threshold", "now", "factors", "weights", "totalWeight", "weightedSum", "score", "overall", "BaseStrategy", "callback", "weight", "sigmoid", "x", "midpoint", "steepness", "inverseSigmoid", "gaussian", "ideal", "width", "exponent", "calculateStatistics", "values", "mean", "a", "b", "variance", "sum", "v", "stdDev", "cv", "analyzeIntervals", "intervals", "uniqueCount", "i", "allIdentical", "scoreCoefficientOfVariation", "gaussian", "MouseStrategy", "BaseStrategy", "options", "width", "height", "e", "mouseEvent", "now", "currentPos", "dx", "dy", "pixelDistance", "cutoffMicro", "normalizedDistance", "rawAngle", "angleDiff", "cutoff", "x", "y", "distTop", "distBottom", "distLeft", "distRight", "minEdgeDist", "entryEdge", "edgeThreshold", "score", "factors", "distances", "p", "stats", "calculateStatistics", "gaussian", "angles", "angleChanges", "i", "avgChange", "a", "b", "entryScore", "microScore", "suspiciousCount", "centerCount", "cornerCount", "originCount", "entry", "total", "suspiciousRatio", "microCount", "oldestEvent", "durationMs", "microPerSecond", "ScrollStrategy", "BaseStrategy", "options", "_e", "scrollY", "now", "pixelDelta", "deltaTime", "normalizedDistance", "velocity", "cutoff", "score", "factors", "distances", "p", "d", "stats", "calculateStatistics", "gaussian", "velocities", "instantJumps", "jumpRatio", "inverseSigmoid", "ClickStrategy", "BaseStrategy", "options", "mouseEvent", "selector", "element", "listener", "e", "_a", "_b", "clickEvent", "now", "rect", "inViewport", "mouseClickDelta", "timeSinceMouseMove", "dx", "dy", "position", "mx", "my", "centerX", "centerY", "eventCount", "positionScore", "clicksWithDelta", "mismatchCount", "clicksWithTiming", "suspiciousTimingCount", "untrustedCount", "click", "score", "factors", "mismatchRatio", "deltaScore", "suspiciousRatio", "timingScore", "untrustedRatio", "trustedScore", "TapStrategy", "BaseStrategy", "options", "selector", "element", "startListener", "e", "touchEvent", "touch", "endListener", "startData", "now", "duration", "dx", "dy", "movement", "rect", "inViewport", "tx", "ty", "overElement", "position", "centerX", "centerY", "listener", "score", "factors", "positionScore", "tap", "durations", "durationAnalysis", "analyzeIntervals", "statistics", "allIdentical", "scoreCoefficientOfVariation", "gaussian", "movements", "avgMovement", "b", "intervals", "i", "intervalAnalysis", "KeyboardStrategy", "BaseStrategy", "options", "now", "keyEvent", "selector", "element", "focusListener", "blurListener", "listener", "downEvents", "e", "score", "factors", "keystrokeIntervals", "i", "keystrokeAnalysis", "analyzeIntervals", "statistics", "allIdentical", "keystrokeScore", "scoreCoefficientOfVariation", "pressDurations", "pressDurationAnalysis", "pressDurationScore", "backspaceCount", "backspaceRatio", "AUTOMATION_GLOBALS", "EnvironmentStrategy", "BaseStrategy", "_timestamp", "env", "auto", "score", "factors", "featureCount", "inverseSigmoid", "gaussian", "hasTouchScreen", "mobileUA", "smallScreen", "isMobile", "isWebdriver", "ua", "hasHeadlessUA", "win", "hasChromelessRuntime", "detectedGlobals", "global", "hasAutomationGlobals", "detectedCDPKeys", "key", "hasCDPInjection", "hasNoPlugins", "hasSoftwareRenderer", "canvas", "gl", "debugInfo", "renderer", "hasWebGL", "webglRenderer", "hasWebRTC", "windowWidth", "windowHeight", "screenWidth", "screenHeight", "suspiciousDimensions", "windowScreenRatio", "suspiciousRatio", "hasStorage", "featureInconsistency", "automation", "_a", "_b", "ResizeStrategy", "BaseStrategy", "mouseEvent", "_a", "_b", "mouseX", "mouseY", "mouseNearEdge", "score", "factors", "inverseSigmoid", "withMouse", "e", "nearEdge", "sigmoid", "TimingStrategy", "BaseStrategy", "mouseEvent", "now", "currentPos", "dx", "dy", "distance", "cutoff", "m", "type", "_event", "timeSinceMouseMove", "actionCount", "score", "factors", "clicks", "clicksWithMouse", "hiddenCount", "action", "stillnessScore", "mouseToClickScore", "intervalScore", "hiddenScore", "clicksWithMouseData", "c", "stillRatio", "delays", "stats", "calculateStatistics", "intervals", "i", "machineIntervals", "preciseCount", "interval", "machineInterval", "remainder", "preciseRatio", "totalCount", "hiddenRatio", "a", "VisibilityStrategy", "BaseStrategy", "now", "wasHidden", "delay", "target", "_type", "_event", "resumeDelay", "lastRecordedDelay", "score", "factors", "hiddenActionScore", "resumeScore", "focusTypingScore", "fastResumeRatio", "d", "suspiciousCount", "pair", "suspiciousRatio", "p", "DEFAULT_SETTINGS"]
|
|
7
7
|
}
|