@surbee/cipher 0.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/src/tiers.ts ADDED
@@ -0,0 +1,507 @@
1
+ /**
2
+ * Cipher Tier Configuration
3
+ *
4
+ * Defines the 5-tier accuracy system for fraud detection.
5
+ * Tiers 1-2: Fully offline, no AI cost
6
+ * Tiers 3-4: Claude Sonnet 4.5 for AI analysis
7
+ * Tier 5: Claude Opus 4.5 for maximum accuracy
8
+ */
9
+
10
+ import type { CipherTier, TierConfig, CheckId, CheckDefinition } from './types';
11
+
12
+ /**
13
+ * All available checks with their definitions
14
+ */
15
+ export const CHECKS: Record<CheckId, CheckDefinition> = {
16
+ // ============================================
17
+ // TIER 1 - Basic Behavioral (Offline)
18
+ // ============================================
19
+ rapid_completion: {
20
+ id: 'rapid_completion',
21
+ name: 'Rapid Completion',
22
+ description: 'Detects impossibly fast survey completion',
23
+ tier: 1,
24
+ category: 'behavioral',
25
+ offline: true,
26
+ },
27
+ uniform_timing: {
28
+ id: 'uniform_timing',
29
+ name: 'Uniform Timing',
30
+ description: 'Detects robotic consistent response times',
31
+ tier: 1,
32
+ category: 'behavioral',
33
+ offline: true,
34
+ },
35
+ low_interaction: {
36
+ id: 'low_interaction',
37
+ name: 'Low Interaction',
38
+ description: 'Detects minimal mouse/keyboard activity',
39
+ tier: 1,
40
+ category: 'behavioral',
41
+ offline: true,
42
+ },
43
+ straight_line_answers: {
44
+ id: 'straight_line_answers',
45
+ name: 'Straight-Lining',
46
+ description: 'Detects selecting same option repeatedly',
47
+ tier: 1,
48
+ category: 'content',
49
+ offline: true,
50
+ },
51
+ impossibly_fast: {
52
+ id: 'impossibly_fast',
53
+ name: 'Speed Reading',
54
+ description: 'Detects reading faster than humanly possible',
55
+ tier: 1,
56
+ category: 'timing',
57
+ offline: true,
58
+ },
59
+ minimal_effort: {
60
+ id: 'minimal_effort',
61
+ name: 'Minimal Effort',
62
+ description: 'Detects very short or low-quality text responses',
63
+ tier: 1,
64
+ category: 'content',
65
+ offline: true,
66
+ },
67
+
68
+ // ============================================
69
+ // TIER 2 - Device/Automation (Offline)
70
+ // ============================================
71
+ excessive_paste: {
72
+ id: 'excessive_paste',
73
+ name: 'Excessive Paste',
74
+ description: 'Detects heavy copy-paste behavior',
75
+ tier: 2,
76
+ category: 'behavioral',
77
+ offline: true,
78
+ },
79
+ pointer_spikes: {
80
+ id: 'pointer_spikes',
81
+ name: 'Pointer Velocity Spikes',
82
+ description: 'Detects unnatural mouse movement patterns',
83
+ tier: 2,
84
+ category: 'behavioral',
85
+ offline: true,
86
+ },
87
+ webdriver_detected: {
88
+ id: 'webdriver_detected',
89
+ name: 'WebDriver Detection',
90
+ description: 'Detects Selenium/automation tools',
91
+ tier: 2,
92
+ category: 'device',
93
+ offline: true,
94
+ },
95
+ automation_detected: {
96
+ id: 'automation_detected',
97
+ name: 'Automation Detection',
98
+ description: 'Detects headless browsers and bots',
99
+ tier: 2,
100
+ category: 'device',
101
+ offline: true,
102
+ },
103
+ no_plugins: {
104
+ id: 'no_plugins',
105
+ name: 'Missing Plugins',
106
+ description: 'Detects suspicious browser configurations',
107
+ tier: 2,
108
+ category: 'device',
109
+ offline: true,
110
+ },
111
+ suspicious_user_agent: {
112
+ id: 'suspicious_user_agent',
113
+ name: 'Suspicious User Agent',
114
+ description: 'Detects bot-like user agent strings',
115
+ tier: 2,
116
+ category: 'device',
117
+ offline: true,
118
+ },
119
+ device_fingerprint_mismatch: {
120
+ id: 'device_fingerprint_mismatch',
121
+ name: 'Device Mismatch',
122
+ description: 'Detects inconsistent device characteristics',
123
+ tier: 2,
124
+ category: 'device',
125
+ offline: true,
126
+ },
127
+ screen_anomaly: {
128
+ id: 'screen_anomaly',
129
+ name: 'Screen Anomaly',
130
+ description: 'Detects impossible screen dimensions',
131
+ tier: 2,
132
+ category: 'device',
133
+ offline: true,
134
+ },
135
+ suspicious_pauses: {
136
+ id: 'suspicious_pauses',
137
+ name: 'Suspicious Pauses',
138
+ description: 'Detects unusual gaps in activity',
139
+ tier: 2,
140
+ category: 'timing',
141
+ offline: true,
142
+ },
143
+
144
+ // ============================================
145
+ // TIER 3 - Enhanced Behavioral + Light AI
146
+ // ============================================
147
+ robotic_typing: {
148
+ id: 'robotic_typing',
149
+ name: 'Robotic Typing',
150
+ description: 'Detects uniform keystroke timing',
151
+ tier: 3,
152
+ category: 'behavioral',
153
+ offline: true,
154
+ },
155
+ mouse_teleporting: {
156
+ id: 'mouse_teleporting',
157
+ name: 'Mouse Teleporting',
158
+ description: 'Detects large instant mouse jumps',
159
+ tier: 3,
160
+ category: 'behavioral',
161
+ offline: true,
162
+ },
163
+ no_corrections: {
164
+ id: 'no_corrections',
165
+ name: 'No Corrections',
166
+ description: 'Detects perfect typing with no backspaces',
167
+ tier: 3,
168
+ category: 'behavioral',
169
+ offline: true,
170
+ },
171
+ excessive_tab_switching: {
172
+ id: 'excessive_tab_switching',
173
+ name: 'Tab Switching',
174
+ description: 'Detects frequent tab/window changes',
175
+ tier: 3,
176
+ category: 'content',
177
+ offline: true,
178
+ },
179
+ window_focus_loss: {
180
+ id: 'window_focus_loss',
181
+ name: 'Focus Loss',
182
+ description: 'Detects extended periods away from survey',
183
+ tier: 3,
184
+ category: 'content',
185
+ offline: true,
186
+ },
187
+ ai_content_basic: {
188
+ id: 'ai_content_basic',
189
+ name: 'AI Content (Basic)',
190
+ description: 'Light AI-generated text detection',
191
+ tier: 3,
192
+ category: 'ai',
193
+ offline: false,
194
+ },
195
+ contradiction_basic: {
196
+ id: 'contradiction_basic',
197
+ name: 'Contradiction (Basic)',
198
+ description: 'Basic response consistency check',
199
+ tier: 3,
200
+ category: 'ai',
201
+ offline: false,
202
+ },
203
+
204
+ // ============================================
205
+ // TIER 4 - Advanced Analysis
206
+ // ============================================
207
+ hover_behavior: {
208
+ id: 'hover_behavior',
209
+ name: 'Hover Patterns',
210
+ description: 'Analyzes mouse hover behavior before clicks',
211
+ tier: 4,
212
+ category: 'behavioral',
213
+ offline: true,
214
+ },
215
+ scroll_patterns: {
216
+ id: 'scroll_patterns',
217
+ name: 'Scroll Patterns',
218
+ description: 'Analyzes reading/scrolling behavior',
219
+ tier: 4,
220
+ category: 'behavioral',
221
+ offline: true,
222
+ },
223
+ mouse_acceleration: {
224
+ id: 'mouse_acceleration',
225
+ name: 'Mouse Acceleration',
226
+ description: 'Analyzes natural mouse acceleration',
227
+ tier: 4,
228
+ category: 'behavioral',
229
+ offline: true,
230
+ },
231
+ vpn_detection: {
232
+ id: 'vpn_detection',
233
+ name: 'VPN Detection',
234
+ description: 'Detects VPN/proxy usage',
235
+ tier: 4,
236
+ category: 'network',
237
+ offline: false,
238
+ },
239
+ datacenter_ip: {
240
+ id: 'datacenter_ip',
241
+ name: 'Datacenter IP',
242
+ description: 'Detects cloud/datacenter IPs',
243
+ tier: 4,
244
+ category: 'network',
245
+ offline: false,
246
+ },
247
+ plagiarism_basic: {
248
+ id: 'plagiarism_basic',
249
+ name: 'Plagiarism (Basic)',
250
+ description: 'Quick check for copied content',
251
+ tier: 4,
252
+ category: 'ai',
253
+ offline: false,
254
+ },
255
+ quality_assessment: {
256
+ id: 'quality_assessment',
257
+ name: 'Quality Assessment',
258
+ description: 'AI assessment of response quality',
259
+ tier: 4,
260
+ category: 'ai',
261
+ offline: false,
262
+ },
263
+ semantic_analysis: {
264
+ id: 'semantic_analysis',
265
+ name: 'Semantic Analysis',
266
+ description: 'AI analysis of response meaning',
267
+ tier: 4,
268
+ category: 'ai',
269
+ offline: false,
270
+ },
271
+
272
+ // ============================================
273
+ // TIER 5 - Maximum (Opus 4.5)
274
+ // ============================================
275
+ ai_content_full: {
276
+ id: 'ai_content_full',
277
+ name: 'AI Content (Full)',
278
+ description: 'Comprehensive AI-generated text detection',
279
+ tier: 5,
280
+ category: 'ai',
281
+ offline: false,
282
+ },
283
+ contradiction_full: {
284
+ id: 'contradiction_full',
285
+ name: 'Contradiction (Full)',
286
+ description: 'Deep semantic contradiction analysis',
287
+ tier: 5,
288
+ category: 'ai',
289
+ offline: false,
290
+ },
291
+ plagiarism_full: {
292
+ id: 'plagiarism_full',
293
+ name: 'Plagiarism (Full)',
294
+ description: 'Comprehensive plagiarism detection',
295
+ tier: 5,
296
+ category: 'ai',
297
+ offline: false,
298
+ },
299
+ fraud_ring_detection: {
300
+ id: 'fraud_ring_detection',
301
+ name: 'Fraud Ring',
302
+ description: 'Detects coordinated fraud attempts',
303
+ tier: 5,
304
+ category: 'ai',
305
+ offline: false,
306
+ },
307
+ answer_sharing: {
308
+ id: 'answer_sharing',
309
+ name: 'Answer Sharing',
310
+ description: 'Detects identical answers across respondents',
311
+ tier: 5,
312
+ category: 'ai',
313
+ offline: false,
314
+ },
315
+ coordinated_timing: {
316
+ id: 'coordinated_timing',
317
+ name: 'Coordinated Timing',
318
+ description: 'Detects synchronized submissions',
319
+ tier: 5,
320
+ category: 'ai',
321
+ offline: false,
322
+ },
323
+ device_sharing: {
324
+ id: 'device_sharing',
325
+ name: 'Device Sharing',
326
+ description: 'Detects same device across respondents',
327
+ tier: 5,
328
+ category: 'ai',
329
+ offline: false,
330
+ },
331
+ tor_detection: {
332
+ id: 'tor_detection',
333
+ name: 'Tor Detection',
334
+ description: 'Detects Tor exit node IPs',
335
+ tier: 5,
336
+ category: 'network',
337
+ offline: false,
338
+ },
339
+ proxy_detection: {
340
+ id: 'proxy_detection',
341
+ name: 'Proxy Detection',
342
+ description: 'Detects proxy server usage',
343
+ tier: 5,
344
+ category: 'network',
345
+ offline: false,
346
+ },
347
+ timezone_validation: {
348
+ id: 'timezone_validation',
349
+ name: 'Timezone Validation',
350
+ description: 'Validates timezone consistency',
351
+ tier: 5,
352
+ category: 'network',
353
+ offline: true,
354
+ },
355
+ baseline_deviation: {
356
+ id: 'baseline_deviation',
357
+ name: 'Baseline Deviation',
358
+ description: 'Compares against established behavioral baseline',
359
+ tier: 5,
360
+ category: 'ai',
361
+ offline: false,
362
+ },
363
+ perplexity_analysis: {
364
+ id: 'perplexity_analysis',
365
+ name: 'Perplexity Analysis',
366
+ description: 'Statistical text predictability analysis',
367
+ tier: 5,
368
+ category: 'ai',
369
+ offline: false,
370
+ },
371
+ burstiness_analysis: {
372
+ id: 'burstiness_analysis',
373
+ name: 'Burstiness Analysis',
374
+ description: 'Sentence length variation analysis',
375
+ tier: 5,
376
+ category: 'ai',
377
+ offline: false,
378
+ },
379
+ };
380
+
381
+ /**
382
+ * Tier configurations
383
+ *
384
+ * Tier 1-2: Fully offline, no API costs
385
+ * Tier 3-4: Claude Sonnet 4.5
386
+ * Tier 5: Claude Opus 4.5
387
+ */
388
+ export const TIERS: Record<CipherTier, TierConfig> = {
389
+ 1: {
390
+ name: 'Basic',
391
+ description: 'Essential fraud detection with behavioral heuristics. Free, fully offline.',
392
+ checks: {
393
+ behavioral: ['rapid_completion', 'uniform_timing', 'low_interaction'],
394
+ timing: ['impossibly_fast'],
395
+ device: [],
396
+ content: ['straight_line_answers', 'minimal_effort'],
397
+ network: [],
398
+ ai: [],
399
+ },
400
+ aiModel: null,
401
+ offline: true,
402
+ estimatedCostPerResponse: 0,
403
+ },
404
+ 2: {
405
+ name: 'Standard',
406
+ description: 'Adds device fingerprinting and automation detection. Free, fully offline.',
407
+ checks: {
408
+ behavioral: ['rapid_completion', 'uniform_timing', 'low_interaction', 'excessive_paste', 'pointer_spikes'],
409
+ timing: ['impossibly_fast', 'suspicious_pauses'],
410
+ device: ['webdriver_detected', 'automation_detected', 'no_plugins', 'suspicious_user_agent', 'device_fingerprint_mismatch', 'screen_anomaly'],
411
+ content: ['straight_line_answers', 'minimal_effort'],
412
+ network: [],
413
+ ai: [],
414
+ },
415
+ aiModel: null,
416
+ offline: true,
417
+ estimatedCostPerResponse: 0,
418
+ },
419
+ 3: {
420
+ name: 'Enhanced',
421
+ description: 'Adds Claude Sonnet 4.5 for content quality analysis. ~$0.003 per response.',
422
+ checks: {
423
+ behavioral: ['rapid_completion', 'uniform_timing', 'low_interaction', 'excessive_paste', 'pointer_spikes', 'robotic_typing', 'mouse_teleporting', 'no_corrections'],
424
+ timing: ['impossibly_fast', 'suspicious_pauses'],
425
+ device: ['webdriver_detected', 'automation_detected', 'no_plugins', 'suspicious_user_agent', 'device_fingerprint_mismatch', 'screen_anomaly'],
426
+ content: ['straight_line_answers', 'minimal_effort', 'excessive_tab_switching', 'window_focus_loss'],
427
+ network: [],
428
+ ai: ['ai_content_basic', 'contradiction_basic'],
429
+ },
430
+ aiModel: 'claude-sonnet-4-5-20250514',
431
+ offline: false,
432
+ estimatedCostPerResponse: 0.003,
433
+ },
434
+ 4: {
435
+ name: 'Advanced',
436
+ description: 'Full behavioral analysis + semantic AI. ~$0.01 per response.',
437
+ checks: {
438
+ behavioral: ['rapid_completion', 'uniform_timing', 'low_interaction', 'excessive_paste', 'pointer_spikes', 'robotic_typing', 'mouse_teleporting', 'no_corrections', 'hover_behavior', 'scroll_patterns', 'mouse_acceleration'],
439
+ timing: ['impossibly_fast', 'suspicious_pauses'],
440
+ device: ['webdriver_detected', 'automation_detected', 'no_plugins', 'suspicious_user_agent', 'device_fingerprint_mismatch', 'screen_anomaly'],
441
+ content: ['straight_line_answers', 'minimal_effort', 'excessive_tab_switching', 'window_focus_loss'],
442
+ network: ['vpn_detection', 'datacenter_ip'],
443
+ ai: ['ai_content_basic', 'contradiction_basic', 'plagiarism_basic', 'quality_assessment', 'semantic_analysis'],
444
+ },
445
+ aiModel: 'claude-sonnet-4-5-20250514',
446
+ offline: false,
447
+ estimatedCostPerResponse: 0.01,
448
+ },
449
+ 5: {
450
+ name: 'Maximum',
451
+ description: 'All 40+ checks with Claude Opus 4.5. Maximum accuracy. ~$0.05 per response.',
452
+ checks: {
453
+ behavioral: ['rapid_completion', 'uniform_timing', 'low_interaction', 'excessive_paste', 'pointer_spikes', 'robotic_typing', 'mouse_teleporting', 'no_corrections', 'hover_behavior', 'scroll_patterns', 'mouse_acceleration'],
454
+ timing: ['impossibly_fast', 'suspicious_pauses'],
455
+ device: ['webdriver_detected', 'automation_detected', 'no_plugins', 'suspicious_user_agent', 'device_fingerprint_mismatch', 'screen_anomaly'],
456
+ content: ['straight_line_answers', 'minimal_effort', 'excessive_tab_switching', 'window_focus_loss'],
457
+ network: ['vpn_detection', 'datacenter_ip', 'tor_detection', 'proxy_detection', 'timezone_validation'],
458
+ ai: ['ai_content_full', 'contradiction_full', 'plagiarism_full', 'quality_assessment', 'semantic_analysis', 'fraud_ring_detection', 'answer_sharing', 'coordinated_timing', 'device_sharing', 'baseline_deviation', 'perplexity_analysis', 'burstiness_analysis'],
459
+ },
460
+ aiModel: 'claude-opus-4-5-20250514',
461
+ offline: false,
462
+ estimatedCostPerResponse: 0.05,
463
+ },
464
+ };
465
+
466
+ /**
467
+ * Get all checks for a given tier (includes all lower tiers)
468
+ */
469
+ export function getChecksForTier(tier: CipherTier): CheckId[] {
470
+ const config = TIERS[tier];
471
+ return [
472
+ ...config.checks.behavioral,
473
+ ...config.checks.timing,
474
+ ...config.checks.device,
475
+ ...config.checks.content,
476
+ ...config.checks.network,
477
+ ...config.checks.ai,
478
+ ];
479
+ }
480
+
481
+ /**
482
+ * Get only offline checks for a tier
483
+ */
484
+ export function getOfflineChecksForTier(tier: CipherTier): CheckId[] {
485
+ return getChecksForTier(tier).filter(id => CHECKS[id].offline);
486
+ }
487
+
488
+ /**
489
+ * Get only AI checks for a tier
490
+ */
491
+ export function getAIChecksForTier(tier: CipherTier): CheckId[] {
492
+ return getChecksForTier(tier).filter(id => !CHECKS[id].offline);
493
+ }
494
+
495
+ /**
496
+ * Check if a tier requires API access
497
+ */
498
+ export function tierRequiresAPI(tier: CipherTier): boolean {
499
+ return !TIERS[tier].offline;
500
+ }
501
+
502
+ /**
503
+ * Estimate cost for a number of responses
504
+ */
505
+ export function estimateCost(tier: CipherTier, responses: number): number {
506
+ return TIERS[tier].estimatedCostPerResponse * responses;
507
+ }