verification-layer 0.17.0 → 0.20.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.
Files changed (89) hide show
  1. package/README.md +182 -9
  2. package/dist/ai/cache.d.ts +15 -0
  3. package/dist/ai/cache.d.ts.map +1 -0
  4. package/dist/ai/cache.js +75 -0
  5. package/dist/ai/cache.js.map +1 -0
  6. package/dist/ai/client.d.ts +11 -0
  7. package/dist/ai/client.d.ts.map +1 -0
  8. package/dist/ai/client.js +27 -0
  9. package/dist/ai/client.js.map +1 -0
  10. package/dist/ai/config.d.ts +29 -0
  11. package/dist/ai/config.d.ts.map +1 -0
  12. package/dist/ai/config.js +29 -0
  13. package/dist/ai/config.js.map +1 -0
  14. package/dist/ai/cost-tracker.d.ts +23 -0
  15. package/dist/ai/cost-tracker.d.ts.map +1 -0
  16. package/dist/ai/cost-tracker.js +55 -0
  17. package/dist/ai/cost-tracker.js.map +1 -0
  18. package/dist/ai/index.d.ts +16 -0
  19. package/dist/ai/index.d.ts.map +1 -0
  20. package/dist/ai/index.js +13 -0
  21. package/dist/ai/index.js.map +1 -0
  22. package/dist/ai/rate-limiter.d.ts +16 -0
  23. package/dist/ai/rate-limiter.d.ts.map +1 -0
  24. package/dist/ai/rate-limiter.js +51 -0
  25. package/dist/ai/rate-limiter.js.map +1 -0
  26. package/dist/ai/rules/index.d.ts +11 -0
  27. package/dist/ai/rules/index.d.ts.map +1 -0
  28. package/dist/ai/rules/index.js +57 -0
  29. package/dist/ai/rules/index.js.map +1 -0
  30. package/dist/ai/rules/prompts/audit-logging.d.ts +7 -0
  31. package/dist/ai/rules/prompts/audit-logging.d.ts.map +1 -0
  32. package/dist/ai/rules/prompts/audit-logging.js +65 -0
  33. package/dist/ai/rules/prompts/audit-logging.js.map +1 -0
  34. package/dist/ai/rules/prompts/data-retention.d.ts +7 -0
  35. package/dist/ai/rules/prompts/data-retention.d.ts.map +1 -0
  36. package/dist/ai/rules/prompts/data-retention.js +60 -0
  37. package/dist/ai/rules/prompts/data-retention.js.map +1 -0
  38. package/dist/ai/rules/prompts/minimum-access.d.ts +7 -0
  39. package/dist/ai/rules/prompts/minimum-access.d.ts.map +1 -0
  40. package/dist/ai/rules/prompts/minimum-access.js +53 -0
  41. package/dist/ai/rules/prompts/minimum-access.js.map +1 -0
  42. package/dist/ai/rules/prompts/phi-encryption.d.ts +7 -0
  43. package/dist/ai/rules/prompts/phi-encryption.d.ts.map +1 -0
  44. package/dist/ai/rules/prompts/phi-encryption.js +60 -0
  45. package/dist/ai/rules/prompts/phi-encryption.js.map +1 -0
  46. package/dist/ai/rules/prompts/rbac-check.d.ts +7 -0
  47. package/dist/ai/rules/prompts/rbac-check.d.ts.map +1 -0
  48. package/dist/ai/rules/prompts/rbac-check.js +61 -0
  49. package/dist/ai/rules/prompts/rbac-check.js.map +1 -0
  50. package/dist/ai/rules/prompts/session-management.d.ts +7 -0
  51. package/dist/ai/rules/prompts/session-management.d.ts.map +1 -0
  52. package/dist/ai/rules/prompts/session-management.js +62 -0
  53. package/dist/ai/rules/prompts/session-management.js.map +1 -0
  54. package/dist/ai/rules/rule-runner.d.ts +36 -0
  55. package/dist/ai/rules/rule-runner.d.ts.map +1 -0
  56. package/dist/ai/rules/rule-runner.js +117 -0
  57. package/dist/ai/rules/rule-runner.js.map +1 -0
  58. package/dist/ai/rules/triage.d.ts +11 -0
  59. package/dist/ai/rules/triage.d.ts.map +1 -0
  60. package/dist/ai/rules/triage.js +107 -0
  61. package/dist/ai/rules/triage.js.map +1 -0
  62. package/dist/ai/rules/types.d.ts +33 -0
  63. package/dist/ai/rules/types.d.ts.map +1 -0
  64. package/dist/ai/rules/types.js +5 -0
  65. package/dist/ai/rules/types.js.map +1 -0
  66. package/dist/ai/sanitizer.d.ts +21 -0
  67. package/dist/ai/sanitizer.d.ts.map +1 -0
  68. package/dist/ai/sanitizer.js +81 -0
  69. package/dist/ai/sanitizer.js.map +1 -0
  70. package/dist/ai/scanner.d.ts +31 -0
  71. package/dist/ai/scanner.d.ts.map +1 -0
  72. package/dist/ai/scanner.js +93 -0
  73. package/dist/ai/scanner.js.map +1 -0
  74. package/dist/cli.js +200 -0
  75. package/dist/cli.js.map +1 -1
  76. package/dist/scan.d.ts.map +1 -1
  77. package/dist/scan.js +35 -1
  78. package/dist/scan.js.map +1 -1
  79. package/dist/scanners/skills/index.d.ts +7 -0
  80. package/dist/scanners/skills/index.d.ts.map +1 -0
  81. package/dist/scanners/skills/index.js +159 -0
  82. package/dist/scanners/skills/index.js.map +1 -0
  83. package/dist/scanners/skills/patterns.d.ts +20 -0
  84. package/dist/scanners/skills/patterns.d.ts.map +1 -0
  85. package/dist/scanners/skills/patterns.js +215 -0
  86. package/dist/scanners/skills/patterns.js.map +1 -0
  87. package/dist/types.d.ts +7 -0
  88. package/dist/types.d.ts.map +1 -1
  89. package/package.json +2 -1
package/README.md CHANGED
@@ -15,6 +15,8 @@ vlayer is a CLI tool that scans your codebase for HIPAA compliance issues. It's
15
15
 
16
16
  **Key capabilities:**
17
17
  - Scan for 50+ security vulnerabilities and PHI exposure patterns
18
+ - **AI Agent Skills scanner** - First HIPAA-focused scanner for SKILL.md files (Claude Code, MCP, Cursor)
19
+ - **AI-powered analysis** with Claude API for complex violations and false positive reduction
18
20
  - Auto-fix common issues with one command
19
21
  - Generate professional audit reports (HTML, PDF, JSON)
20
22
  - Detect your tech stack and provide tailored recommendations
@@ -46,15 +48,70 @@ node dist/cli.js score /path/to/project
46
48
 
47
49
  # Generate auditor-ready report
48
50
  node dist/cli.js report /path/to/project -o audit-report.html
51
+
52
+ # Scan AI Agent Skills (NEW!)
53
+ node dist/cli.js skill-scan ~/Downloads/patient-lookup.SKILL.md
49
54
  ```
50
55
 
51
56
  ---
52
57
 
53
- ## 🌐 Web Dashboard
58
+ ## 🛡️ AI Agent Skills Security Scanner
59
+
60
+ **vlayer is the first HIPAA-focused security scanner for AI Agent Skills.**
61
+
62
+ Protect your healthcare environment from malicious skills before installation:
63
+
64
+ ```bash
65
+ # Scan before installing any skill
66
+ vlayer skill-scan ~/Downloads/patient-exporter.SKILL.md
67
+
68
+ # Scan all skills in directory
69
+ vlayer skill-scan ~/.claw/skills/
70
+
71
+ # CI/CD integration
72
+ vlayer skill-scan ./custom-skills/ || exit 1
73
+ ```
74
+
75
+ ### The Problem
76
+
77
+ - **36.82%** of AI Agent Skills have security flaws (Snyk, Feb 2026)
78
+ - **341 malicious skills** distribute Atomic Stealer malware
79
+ - **283 skills** expose credentials in plaintext
80
+ - **Zero existing scanners** have HIPAA-specific rules
81
+
82
+ ### What It Detects
54
83
 
55
- **Live Dashboard**: [https://dashboard-silk-zeta-55.vercel.app](https://dashboard-silk-zeta-55.vercel.app)
84
+ - PHI exposure (SSN, MRN, DOB in examples)
85
+ - ✅ Hardcoded credentials (API keys, passwords)
86
+ - ✅ Malicious patterns (reverse shells, data exfiltration)
87
+ - ✅ HIPAA violations (HTTP transmission, no audit logging)
88
+
89
+ ### Example Output
90
+
91
+ ```
92
+ 🚨 Critical: 7 | ⚠️ High: 14 | ⚡ Medium: 1
56
93
 
57
- Enterprise-grade HIPAA compliance monitoring platform with professional dark theme and real-time visualizations.
94
+ Issues:
95
+ PHI Exposure: 8
96
+ Credential Leaks: 1
97
+ Data Exfiltration: 1
98
+
99
+ ❌ DO NOT INSTALL THIS SKILL
100
+ Critical HIPAA violations detected.
101
+ ```
102
+
103
+ 📖 **[Full Documentation](docs/SKILLS-SCANNER.md)**
104
+
105
+ ---
106
+
107
+ ## 🌐 VLayer Ecosystem
108
+
109
+ **Dashboard**: [https://app.vlayer.app](https://app.vlayer.app) - Compliance monitoring platform
110
+ **Playground**: [https://play.vlayer.app](https://play.vlayer.app) - Try vlayer in your browser
111
+ **Documentation**: [https://docs.vlayer.app](https://docs.vlayer.app) - Complete guides and API reference
112
+ **Landing Page**: [https://vlayer.app](https://vlayer.app) - Marketing site
113
+
114
+ Enterprise-grade HIPAA compliance monitoring platform for tracking violations, compliance scores, and generating audit reports.
58
115
 
59
116
  ### Design
60
117
 
@@ -68,6 +125,7 @@ Enterprise-grade HIPAA compliance monitoring platform with professional dark the
68
125
 
69
126
  ### Features
70
127
 
128
+ - 🔐 **Supabase Authentication** - Secure email/password authentication with session management
71
129
  - 📊 **Visual Compliance Dashboard** - 4-metric overview with real-time scores and status distribution
72
130
  - 📈 **Historical Score Tracking** - Interactive charts showing compliance trends over time
73
131
  - 🗂️ **Multi-Project Management** - Monitor unlimited projects with inline progress indicators
@@ -75,18 +133,20 @@ Enterprise-grade HIPAA compliance monitoring platform with professional dark the
75
133
  - 📋 **Executive Summaries** - Professional reports with grade assignments (A-F)
76
134
  - 🎨 **Enterprise Tables** - Sortable project lists with circular scores and status badges
77
135
  - 📱 **Responsive Design** - Optimized for desktop, tablet, and mobile devices
136
+ - 👤 **User Management** - User profiles with logout functionality in sidebar
78
137
 
79
138
  ### Quick Start
80
139
 
81
- 1. **Visit Dashboard**: Navigate to [dashboard-silk-zeta-55.vercel.app](https://dashboard-silk-zeta-55.vercel.app)
82
- 2. **Create Project**: Click "+ New Project" and enter your project details
83
- 3. **Run Scan**: Execute a compliance scan on your codebase
140
+ 1. **Create Account**: Sign up at [app.vlayer.app/signup](https://app.vlayer.app/signup) with your email
141
+ 2. **Login**: Access the dashboard at [app.vlayer.app](https://app.vlayer.app)
142
+ 3. **Create Project**: Click "+ New Project" and enter your project details
143
+ 4. **Run Scan**: Execute a compliance scan on your codebase
84
144
  ```bash
85
145
  node dist/cli.js scan ./src --format json --output scan.json
86
146
  ```
87
- 4. **Upload Results**: Send scan data to your project via API
147
+ 5. **Upload Results**: Send scan data to your project via API
88
148
  ```bash
89
- curl -X POST https://dashboard-silk-zeta-55.vercel.app/api/projects/{projectId}/scans \
149
+ curl -X POST https://app.vlayer.app/api/projects/{projectId}/scans \
90
150
  -H "Content-Type: application/json" \
91
151
  -d @scan.json
92
152
  ```
@@ -399,6 +459,96 @@ node dist/cli.js audit ./my-app --generate-report --org "Healthcare Inc" --audit
399
459
 
400
460
  ---
401
461
 
462
+ ### 6. AI-Powered Scanning (Beta)
463
+
464
+ **Reduce false positives and catch complex violations with Claude AI.**
465
+
466
+ vlayer now includes optional AI-powered analysis using Anthropic's Claude API:
467
+
468
+ #### Features
469
+
470
+ - **🤖 LLM-Powered Rules**: 6 specialized AI rules for detecting complex HIPAA violations
471
+ - **🎯 AI Triage**: Automatically classify findings to reduce false positives by 50%+
472
+ - **🔒 PHI Scrubbing**: All code is sanitized before sending to the LLM (HIPAA-safe)
473
+ - **💰 Cost Control**: Budget limits, caching, and rate limiting built-in
474
+ - **📊 Confidence Scores**: AI provides reasoning and confidence for each finding
475
+
476
+ #### Quick Start
477
+
478
+ ```bash
479
+ # Set your API key
480
+ export ANTHROPIC_API_KEY="sk-ant-..."
481
+
482
+ # Run AI-powered scan (default: 50¢ budget)
483
+ node dist/cli.js ai-scan ./my-app
484
+
485
+ # Adjust budget
486
+ node dist/cli.js ai-scan ./my-app --budget 100
487
+
488
+ # Run LLM rules only (skip triage)
489
+ node dist/cli.js ai-scan ./my-app --rules-only
490
+
491
+ # Enable AI triage in regular scan
492
+ node dist/cli.js scan ./my-app # AI triage runs automatically if API key is set
493
+
494
+ # Disable AI features
495
+ node dist/cli.js scan ./my-app --no-ai
496
+ ```
497
+
498
+ #### AI Rules
499
+
500
+ The AI scanner includes 6 specialized rules:
501
+
502
+ | Rule ID | Name | Detects |
503
+ |---------|------|---------|
504
+ | **HIPAA-PHI-003** | Minimum Necessary Access | APIs returning more PHI than needed (SELECT * violations) |
505
+ | **HIPAA-SEC-001** | PHI Encryption | Unencrypted PHI in transit or at rest |
506
+ | **HIPAA-ACCESS-001** | Role-Based Access Control | Missing auth checks, hardcoded roles, IDOR vulnerabilities |
507
+ | **HIPAA-AUDIT-001** | Audit Logging | PHI operations without proper audit trails |
508
+ | **HIPAA-RETENTION-001** | Data Retention | Improper deletion, missing retention policies |
509
+ | **HIPAA-AUTH-001** | Session Management | Weak session configs, missing timeouts |
510
+
511
+ #### Configuration
512
+
513
+ Add AI settings to `.vlayerrc.json`:
514
+
515
+ ```json
516
+ {
517
+ "ai": {
518
+ "enabled": true,
519
+ "enableTriage": true,
520
+ "enableLLMRules": true,
521
+ "filterFalsePositives": true,
522
+ "budgetCents": 50
523
+ }
524
+ }
525
+ ```
526
+
527
+ #### Cost & Performance
528
+
529
+ - **Typical scan**: 5-20 API calls, $0.10-$0.50
530
+ - **Caching**: Results cached for 24 hours by file hash
531
+ - **Rate limiting**: Max 20 calls/minute, 50 calls/scan
532
+ - **PHI protection**: All sensitive data scrubbed before API call
533
+
534
+ **Example output:**
535
+ ```
536
+ 🤖 Starting AI-powered HIPAA scan...
537
+ 🔒 Scrubbed 3 PHI patterns from src/api/patients.ts
538
+ 📋 Running 6 LLM-powered rules...
539
+ ✅ AI scan complete: 12 findings, 48¢
540
+
541
+ AI Scan Summary:
542
+ Files scanned: 8
543
+ AI findings: 12
544
+ AI calls made: 18
545
+ Cost: 48¢
546
+ Critical: 2
547
+ High: 5
548
+ ```
549
+
550
+ ---
551
+
402
552
  ## Report Examples
403
553
 
404
554
  ### HTML Report
@@ -524,6 +674,30 @@ Each finding maps to specific HIPAA regulations:
524
674
  ## Roadmap
525
675
 
526
676
  ### Recently Completed ✅
677
+ - [x] **Phase 4E: Authentication & User Management**
678
+ - [x] Supabase Auth integration
679
+ - [x] Email/password authentication flow
680
+ - [x] Login and signup pages with dark theme
681
+ - [x] Protected routes via Next.js middleware
682
+ - [x] User session management
683
+ - [x] User profile display in sidebar
684
+ - [x] Logout functionality
685
+ - [x] Environment variables configured in Vercel
686
+ - [x] **Phase 4D: Custom Domain Configuration**
687
+ - [x] Configured custom domains on vlayer.app
688
+ - [x] Dashboard: app.vlayer.app
689
+ - [x] Playground: play.vlayer.app
690
+ - [x] Documentation: docs.vlayer.app
691
+ - [x] Landing page: vlayer.app
692
+ - [x] Automatic DNS configuration via Vercel
693
+ - [x] SSL/TLS certificates provisioned for all domains
694
+ - [x] Updated all cross-project links
695
+ - [x] **Phase 4C: Dashboard Consolidation**
696
+ - [x] Moved landing page to separate repo ([vlayer-website](https://github.com/Francosimon53/vlayer-website))
697
+ - [x] Dashboard now at root route (/) instead of /dashboard
698
+ - [x] Simplified route structure (/, /projects, /projects/[id])
699
+ - [x] Removed route groups for cleaner app organization
700
+ - [x] Dashboard-focused application architecture
527
701
  - [x] **Phase 4A: Web Dashboard (Enterprise Redesign)**
528
702
  - [x] Next.js dashboard deployed to Vercel
529
703
  - [x] Enterprise-grade dark navy theme with emerald accents
@@ -535,7 +709,6 @@ Each finding maps to specific HIPAA regulations:
535
709
  - [x] Demo data with 4 realistic projects
536
710
  - [x] Glassmorphism effects and professional shadows
537
711
  - [x] Responsive design optimized for all devices
538
- - [x] Live at: https://dashboard-silk-zeta-55.vercel.app
539
712
  - [x] **Phase 3B: Dashboard & Compliance Score**
540
713
  - [x] HIPAA Compliance Score (0-100) with severity weighting
541
714
  - [x] Enhanced HTML reports with visual gauge
@@ -0,0 +1,15 @@
1
+ /**
2
+ * AI Cache - Cache results by file hash
3
+ */
4
+ export declare class AICache {
5
+ private cacheDir;
6
+ private ttlMs;
7
+ constructor();
8
+ ensureCacheDir(): Promise<void>;
9
+ getFileHash(content: string): string;
10
+ getCacheKey(fileHash: string, ruleId: string): string;
11
+ get(fileContent: string, ruleId: string): Promise<any | null>;
12
+ set(fileContent: string, ruleId: string, result: any): Promise<void>;
13
+ clear(): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/ai/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;;IAOhB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAIpC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAI/C,GAAG,CACP,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IA2BhB,GAAG,CACP,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,IAAI,CAAC;IAqBV,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * AI Cache - Cache results by file hash
3
+ */
4
+ import * as crypto from 'crypto';
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ import { AI_CONFIG } from './config.js';
8
+ export class AICache {
9
+ cacheDir;
10
+ ttlMs;
11
+ constructor() {
12
+ this.cacheDir = AI_CONFIG.cache.directory;
13
+ this.ttlMs = AI_CONFIG.cache.ttlHours * 60 * 60 * 1000;
14
+ }
15
+ async ensureCacheDir() {
16
+ try {
17
+ await fs.mkdir(this.cacheDir, { recursive: true });
18
+ }
19
+ catch (error) {
20
+ // Directory might already exist
21
+ }
22
+ }
23
+ getFileHash(content) {
24
+ return crypto.createHash('sha256').update(content).digest('hex');
25
+ }
26
+ getCacheKey(fileHash, ruleId) {
27
+ return `${fileHash}-${ruleId}.json`;
28
+ }
29
+ async get(fileContent, ruleId) {
30
+ if (!AI_CONFIG.cache.enabled) {
31
+ return null;
32
+ }
33
+ await this.ensureCacheDir();
34
+ const fileHash = this.getFileHash(fileContent);
35
+ const cacheKey = this.getCacheKey(fileHash, ruleId);
36
+ const cachePath = path.join(this.cacheDir, cacheKey);
37
+ try {
38
+ const data = await fs.readFile(cachePath, 'utf-8');
39
+ const entry = JSON.parse(data);
40
+ // Check if cache is expired
41
+ const age = Date.now() - entry.timestamp;
42
+ if (age > this.ttlMs) {
43
+ await fs.unlink(cachePath); // Delete expired cache
44
+ return null;
45
+ }
46
+ return entry.result;
47
+ }
48
+ catch (error) {
49
+ return null;
50
+ }
51
+ }
52
+ async set(fileContent, ruleId, result) {
53
+ if (!AI_CONFIG.cache.enabled) {
54
+ return;
55
+ }
56
+ await this.ensureCacheDir();
57
+ const fileHash = this.getFileHash(fileContent);
58
+ const cacheKey = this.getCacheKey(fileHash, ruleId);
59
+ const cachePath = path.join(this.cacheDir, cacheKey);
60
+ const entry = {
61
+ fileHash,
62
+ ruleId,
63
+ result,
64
+ timestamp: Date.now(),
65
+ ttl: this.ttlMs,
66
+ };
67
+ await fs.writeFile(cachePath, JSON.stringify(entry, null, 2), 'utf-8');
68
+ }
69
+ async clear() {
70
+ await this.ensureCacheDir();
71
+ const files = await fs.readdir(this.cacheDir);
72
+ await Promise.all(files.map((file) => fs.unlink(path.join(this.cacheDir, file))));
73
+ }
74
+ }
75
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/ai/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Anthropic AI Client (singleton)
3
+ */
4
+ import Anthropic from '@anthropic-ai/sdk';
5
+ export declare function getAIClient(): Anthropic;
6
+ export declare function isAIAvailable(): boolean;
7
+ /**
8
+ * Reset client (useful for testing)
9
+ */
10
+ export declare function resetAIClient(): void;
11
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ai/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAI1C,wBAAgB,WAAW,IAAI,SAAS,CAavC;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Anthropic AI Client (singleton)
3
+ */
4
+ import Anthropic from '@anthropic-ai/sdk';
5
+ let client = null;
6
+ export function getAIClient() {
7
+ if (!client) {
8
+ const apiKey = process.env.ANTHROPIC_API_KEY || process.env.VLAYER_AI_KEY;
9
+ if (!apiKey) {
10
+ throw new Error('AI features require an Anthropic API key.\n' +
11
+ 'Set ANTHROPIC_API_KEY or VLAYER_AI_KEY environment variable.\n' +
12
+ 'Get your key at: https://console.anthropic.com/settings/keys');
13
+ }
14
+ client = new Anthropic({ apiKey });
15
+ }
16
+ return client;
17
+ }
18
+ export function isAIAvailable() {
19
+ return !!(process.env.ANTHROPIC_API_KEY || process.env.VLAYER_AI_KEY);
20
+ }
21
+ /**
22
+ * Reset client (useful for testing)
23
+ */
24
+ export function resetAIClient() {
25
+ client = null;
26
+ }
27
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/ai/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,IAAI,MAAM,GAAqB,IAAI,CAAC;AAEpC,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QAC1E,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,6CAA6C;gBAC3C,gEAAgE;gBAChE,8DAA8D,CACjE,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * AI Configuration
3
+ */
4
+ export declare const AI_CONFIG: {
5
+ readonly model: "claude-sonnet-4-20250514";
6
+ readonly maxTokens: 2048;
7
+ readonly temperature: 0.1;
8
+ readonly maxFileSizeBytes: 50000;
9
+ readonly maxConcurrentCalls: 3;
10
+ readonly rateLimit: {
11
+ readonly maxCallsPerMinute: 20;
12
+ readonly maxCallsPerScan: 50;
13
+ };
14
+ readonly budget: {
15
+ readonly defaultMaxCentsPerScan: 50;
16
+ readonly estimatedCostPerCall: 1.5;
17
+ };
18
+ readonly cache: {
19
+ readonly enabled: true;
20
+ readonly directory: ".vlayer/ai-cache";
21
+ readonly ttlHours: 24;
22
+ };
23
+ readonly pricing: {
24
+ readonly inputCostPerMillion: 3;
25
+ readonly outputCostPerMillion: 15;
26
+ };
27
+ };
28
+ export type AIModel = typeof AI_CONFIG.model;
29
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/ai/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;CAwBZ,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,OAAO,SAAS,CAAC,KAAK,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * AI Configuration
3
+ */
4
+ export const AI_CONFIG = {
5
+ model: 'claude-sonnet-4-20250514',
6
+ maxTokens: 2048,
7
+ temperature: 0.1, // Deterministic for security
8
+ maxFileSizeBytes: 50_000, // Don't send files > 50KB
9
+ maxConcurrentCalls: 3,
10
+ rateLimit: {
11
+ maxCallsPerMinute: 20,
12
+ maxCallsPerScan: 50,
13
+ },
14
+ budget: {
15
+ defaultMaxCentsPerScan: 50, // $0.50 default
16
+ estimatedCostPerCall: 1.5, // ~$0.015 per call with Sonnet
17
+ },
18
+ cache: {
19
+ enabled: true,
20
+ directory: '.vlayer/ai-cache',
21
+ ttlHours: 24,
22
+ },
23
+ pricing: {
24
+ // Claude Sonnet 4 pricing (per million tokens)
25
+ inputCostPerMillion: 3.0,
26
+ outputCostPerMillion: 15.0,
27
+ },
28
+ };
29
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/ai/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,KAAK,EAAE,0BAAmC;IAC1C,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,GAAG,EAAE,6BAA6B;IAC/C,gBAAgB,EAAE,MAAM,EAAE,0BAA0B;IACpD,kBAAkB,EAAE,CAAC;IACrB,SAAS,EAAE;QACT,iBAAiB,EAAE,EAAE;QACrB,eAAe,EAAE,EAAE;KACpB;IACD,MAAM,EAAE;QACN,sBAAsB,EAAE,EAAE,EAAE,gBAAgB;QAC5C,oBAAoB,EAAE,GAAG,EAAE,+BAA+B;KAC3D;IACD,KAAK,EAAE;QACL,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,kBAAkB;QAC7B,QAAQ,EAAE,EAAE;KACb;IACD,OAAO,EAAE;QACP,+CAA+C;QAC/C,mBAAmB,EAAE,GAAG;QACxB,oBAAoB,EAAE,IAAI;KAC3B;CACO,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Cost Tracker - Track AI API usage and costs
3
+ */
4
+ export declare class CostTracker {
5
+ private totalInputTokens;
6
+ private totalOutputTokens;
7
+ private totalCalls;
8
+ private budgetCents;
9
+ constructor(budgetCents?: number);
10
+ trackUsage(inputTokens: number, outputTokens: number): void;
11
+ getEstimatedCostCents(): number;
12
+ isOverBudget(): boolean;
13
+ getSummary(): string;
14
+ getEstimate(): string;
15
+ getStats(): {
16
+ totalCalls: number;
17
+ totalInputTokens: number;
18
+ totalOutputTokens: number;
19
+ estimatedCost: number;
20
+ };
21
+ reset(): void;
22
+ }
23
+ //# sourceMappingURL=cost-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-tracker.d.ts","sourceRoot":"","sources":["../../src/ai/cost-tracker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,qBAAa,WAAW;IACtB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,GAAE,MAAgD;IAIzE,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAM3D,qBAAqB,IAAI,MAAM;IAW/B,YAAY,IAAI,OAAO;IAIvB,UAAU,IAAI,MAAM;IAUpB,WAAW,IAAI,MAAM;IAOrB,QAAQ;;;;;;IASR,KAAK,IAAI,IAAI;CAKd"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Cost Tracker - Track AI API usage and costs
3
+ */
4
+ import { AI_CONFIG } from './config.js';
5
+ export class CostTracker {
6
+ totalInputTokens = 0;
7
+ totalOutputTokens = 0;
8
+ totalCalls = 0;
9
+ budgetCents;
10
+ constructor(budgetCents = AI_CONFIG.budget.defaultMaxCentsPerScan) {
11
+ this.budgetCents = budgetCents;
12
+ }
13
+ trackUsage(inputTokens, outputTokens) {
14
+ this.totalInputTokens += inputTokens;
15
+ this.totalOutputTokens += outputTokens;
16
+ this.totalCalls++;
17
+ }
18
+ getEstimatedCostCents() {
19
+ // Sonnet pricing: $3/M input, $15/M output
20
+ const inputCost = (this.totalInputTokens * AI_CONFIG.pricing.inputCostPerMillion) /
21
+ 1_000_000;
22
+ const outputCost = (this.totalOutputTokens * AI_CONFIG.pricing.outputCostPerMillion) /
23
+ 1_000_000;
24
+ return (inputCost + outputCost) * 100; // Convert to cents
25
+ }
26
+ isOverBudget() {
27
+ return this.getEstimatedCostCents() >= this.budgetCents;
28
+ }
29
+ getSummary() {
30
+ const cost = this.getEstimatedCostCents() / 100;
31
+ return (`AI scan: ${this.totalCalls} calls, ` +
32
+ `${this.totalInputTokens} input tokens, ` +
33
+ `${this.totalOutputTokens} output tokens, ` +
34
+ `~$${cost.toFixed(3)}`);
35
+ }
36
+ getEstimate() {
37
+ const estimatedCalls = this.totalCalls || 1;
38
+ const estimatedCost = (estimatedCalls * AI_CONFIG.budget.estimatedCostPerCall) / 100;
39
+ return `Estimated cost: ~$${estimatedCost.toFixed(3)} (${estimatedCalls} calls)`;
40
+ }
41
+ getStats() {
42
+ return {
43
+ totalCalls: this.totalCalls,
44
+ totalInputTokens: this.totalInputTokens,
45
+ totalOutputTokens: this.totalOutputTokens,
46
+ estimatedCost: this.getEstimatedCostCents(),
47
+ };
48
+ }
49
+ reset() {
50
+ this.totalInputTokens = 0;
51
+ this.totalOutputTokens = 0;
52
+ this.totalCalls = 0;
53
+ }
54
+ }
55
+ //# sourceMappingURL=cost-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-tracker.js","sourceRoot":"","sources":["../../src/ai/cost-tracker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,OAAO,WAAW;IACd,gBAAgB,GAAG,CAAC,CAAC;IACrB,iBAAiB,GAAG,CAAC,CAAC;IACtB,UAAU,GAAG,CAAC,CAAC;IACf,WAAW,CAAS;IAE5B,YAAY,cAAsB,SAAS,CAAC,MAAM,CAAC,sBAAsB;QACvE,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED,UAAU,CAAC,WAAmB,EAAE,YAAoB;QAClD,IAAI,CAAC,gBAAgB,IAAI,WAAW,CAAC;QACrC,IAAI,CAAC,iBAAiB,IAAI,YAAY,CAAC;QACvC,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAED,qBAAqB;QACnB,2CAA2C;QAC3C,MAAM,SAAS,GACb,CAAC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC;YAC/D,SAAS,CAAC;QACZ,MAAM,UAAU,GACd,CAAC,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC,OAAO,CAAC,oBAAoB,CAAC;YACjE,SAAS,CAAC;QACZ,OAAO,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,mBAAmB;IAC5D,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,qBAAqB,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC;IAC1D,CAAC;IAED,UAAU;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,qBAAqB,EAAE,GAAG,GAAG,CAAC;QAChD,OAAO,CACL,YAAY,IAAI,CAAC,UAAU,UAAU;YACrC,GAAG,IAAI,CAAC,gBAAgB,iBAAiB;YACzC,GAAG,IAAI,CAAC,iBAAiB,kBAAkB;YAC3C,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CACvB,CAAC;IACJ,CAAC;IAED,WAAW;QACT,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QAC5C,MAAM,aAAa,GACjB,CAAC,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,oBAAoB,CAAC,GAAG,GAAG,CAAC;QACjE,OAAO,qBAAqB,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,cAAc,SAAS,CAAC;IACnF,CAAC;IAED,QAAQ;QACN,OAAO;YACL,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,aAAa,EAAE,IAAI,CAAC,qBAAqB,EAAE;SAC5C,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * AI-Powered HIPAA Scanning
3
+ * Export all AI functionality
4
+ */
5
+ export { getAIClient, isAIAvailable } from './client.js';
6
+ export { AI_CONFIG } from './config.js';
7
+ export { sanitizeCodeForLLM } from './sanitizer.js';
8
+ export type { SanitizationResult } from './sanitizer.js';
9
+ export { CostTracker } from './cost-tracker.js';
10
+ export { AICache } from './cache.js';
11
+ export { RateLimiter } from './rate-limiter.js';
12
+ export { RuleRunner, triageFinding, triageFindings, AI_RULES, } from './rules/index.js';
13
+ export type { LLMRule, AIFinding, TriagedFinding, TriageClassification, LLMRuleResponse, TriageResponse, } from './rules/index.js';
14
+ export { runAIScan, triageExistingFindings } from './scanner.js';
15
+ export type { AIScanOptions, AIScanResult } from './scanner.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,OAAO,EACP,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * AI-Powered HIPAA Scanning
3
+ * Export all AI functionality
4
+ */
5
+ export { getAIClient, isAIAvailable } from './client.js';
6
+ export { AI_CONFIG } from './config.js';
7
+ export { sanitizeCodeForLLM } from './sanitizer.js';
8
+ export { CostTracker } from './cost-tracker.js';
9
+ export { AICache } from './cache.js';
10
+ export { RateLimiter } from './rate-limiter.js';
11
+ export { RuleRunner, triageFinding, triageFindings, AI_RULES, } from './rules/index.js';
12
+ export { runAIScan, triageExistingFindings } from './scanner.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Rate Limiter - Prevent exceeding API rate limits
3
+ */
4
+ export declare class RateLimiter {
5
+ private callTimestamps;
6
+ private totalCalls;
7
+ canMakeCall(): boolean;
8
+ recordCall(): void;
9
+ waitIfNeeded(): Promise<void>;
10
+ reset(): void;
11
+ getStats(): {
12
+ callsThisMinute: number;
13
+ totalCalls: number;
14
+ };
15
+ }
16
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/ai/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,qBAAa,WAAW;IACtB,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,UAAU,CAAK;IAEvB,WAAW,IAAI,OAAO;IAsBtB,UAAU,IAAI,IAAI;IAKZ,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAenC,KAAK,IAAI,IAAI;IAKb,QAAQ,IAAI;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;CAM5D"}