@indicated/vibeguard 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAOA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA2LpD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAoBA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAmOpD"}
@@ -40,6 +40,24 @@ const zod_1 = require("zod");
40
40
  const path = __importStar(require("path"));
41
41
  const scanner_1 = require("../scanner");
42
42
  const definitions_1 = require("../scanner/rules/definitions");
43
+ const license_1 = require("../api/license");
44
+ function calculateGrade(counts) {
45
+ if (counts.critical > 0)
46
+ return 'F';
47
+ if (counts.high > 2)
48
+ return 'D';
49
+ if (counts.high > 0)
50
+ return 'C';
51
+ if (counts.medium > 3)
52
+ return 'C';
53
+ if (counts.medium > 0)
54
+ return 'B';
55
+ if (counts.low > 5)
56
+ return 'B';
57
+ if (counts.low > 0)
58
+ return 'A';
59
+ return 'A+';
60
+ }
43
61
  async function startMcpServer() {
44
62
  const server = new mcp_js_1.McpServer({
45
63
  name: 'vibeguard',
@@ -51,24 +69,27 @@ async function startMcpServer() {
51
69
  staged_only: zod_1.z.boolean().optional().describe('If true, only scan git staged files'),
52
70
  }, async ({ paths, staged_only }) => {
53
71
  try {
72
+ const licenseKey = (0, license_1.getLicenseKey)();
54
73
  const scanner = new scanner_1.Scanner();
55
- await scanner.initialize();
74
+ await scanner.initialize(licenseKey || undefined);
56
75
  const cwd = process.cwd();
57
76
  const targets = paths.map(p => path.resolve(cwd, p));
58
77
  const result = staged_only
59
78
  ? await scanner.scanStaged()
60
79
  : await scanner.scan(targets);
80
+ const userTier = scanner.getUserTier();
81
+ const tierLabel = userTier === 'pro' ? '🔓 Pro' : '🔒 Free';
61
82
  if (result.findings.length === 0) {
62
83
  return {
63
84
  content: [
64
85
  {
65
86
  type: 'text',
66
- text: `✅ No security issues found in ${result.files} file(s).`,
87
+ text: `✅ No security issues found in ${result.files} file(s).\n\nGrade: A+ | Tier: ${tierLabel}`,
67
88
  },
68
89
  ],
69
90
  };
70
91
  }
71
- // Format findings
92
+ // Format findings with restriction info
72
93
  const findings = result.findings.map(f => ({
73
94
  severity: f.rule.severity,
74
95
  rule: f.rule.id,
@@ -77,6 +98,7 @@ async function startMcpServer() {
77
98
  line: f.line,
78
99
  message: f.rule.description,
79
100
  fix: f.rule.fix,
101
+ isRestricted: f.isRestricted,
80
102
  }));
81
103
  const counts = {
82
104
  critical: findings.filter(f => f.severity === 'critical').length,
@@ -84,13 +106,25 @@ async function startMcpServer() {
84
106
  medium: findings.filter(f => f.severity === 'medium').length,
85
107
  low: findings.filter(f => f.severity === 'low').length,
86
108
  };
109
+ const grade = calculateGrade(counts);
110
+ const restrictedCount = findings.filter(f => f.isRestricted).length;
87
111
  const summary = `Found ${findings.length} issue(s): ${counts.critical} critical, ${counts.high} high, ${counts.medium} medium, ${counts.low} low`;
88
- const formattedFindings = findings.map(f => `[${f.severity.toUpperCase()}] ${f.file}:${f.line}\n ${f.name}\n Fix: ${f.fix}`).join('\n\n');
112
+ const formattedFindings = findings.map(f => {
113
+ const proTag = f.isRestricted ? ' [PRO]' : '';
114
+ const fixLine = f.isRestricted
115
+ ? ' Fix: Upgrade to Pro to see fix details'
116
+ : ` Fix: ${f.fix}`;
117
+ return `[${f.severity.toUpperCase()}]${proTag} ${f.file}:${f.line}\n ${f.name}\n${fixLine}`;
118
+ }).join('\n\n');
119
+ let footer = `\nGrade: ${grade} | Tier: ${tierLabel}`;
120
+ if (restrictedCount > 0 && userTier === 'free') {
121
+ footer += `\n\n${restrictedCount} finding(s) require Pro to see fix details. Run 'vibeguard upgrade' to unlock.`;
122
+ }
89
123
  return {
90
124
  content: [
91
125
  {
92
126
  type: 'text',
93
- text: `${summary}\n\n${formattedFindings}`,
127
+ text: `${summary}\n\n${formattedFindings}${footer}`,
94
128
  },
95
129
  ],
96
130
  };
@@ -137,9 +171,12 @@ async function startMcpServer() {
137
171
  const ext = language === 'python' ? '.py' : language === 'typescript' ? '.ts' : '.js';
138
172
  const tempFile = path.join(os.tmpdir(), `vibeguard-check-${Date.now()}${ext}`);
139
173
  fs.writeFileSync(tempFile, code);
174
+ const licenseKey = (0, license_1.getLicenseKey)();
140
175
  const scanner = new scanner_1.Scanner();
141
- await scanner.initialize();
176
+ await scanner.initialize(licenseKey || undefined);
142
177
  const result = await scanner.scan([tempFile]);
178
+ const userTier = scanner.getUserTier();
179
+ const tierLabel = userTier === 'pro' ? '🔓 Pro' : '🔒 Free';
143
180
  // Clean up
144
181
  fs.unlinkSync(tempFile);
145
182
  if (result.findings.length === 0) {
@@ -147,7 +184,7 @@ async function startMcpServer() {
147
184
  content: [
148
185
  {
149
186
  type: 'text',
150
- text: '✅ No security issues found in this code snippet.',
187
+ text: `✅ No security issues found in this code snippet.\n\nGrade: A+ | Tier: ${tierLabel}`,
151
188
  },
152
189
  ],
153
190
  };
@@ -158,13 +195,32 @@ async function startMcpServer() {
158
195
  name: f.rule.name,
159
196
  line: f.line,
160
197
  fix: f.rule.fix,
198
+ isRestricted: f.isRestricted,
161
199
  }));
162
- const formatted = findings.map(f => `[${f.severity.toUpperCase()}] Line ${f.line}: ${f.name}\n Fix: ${f.fix}`).join('\n\n');
200
+ const counts = {
201
+ critical: findings.filter(f => f.severity === 'critical').length,
202
+ high: findings.filter(f => f.severity === 'high').length,
203
+ medium: findings.filter(f => f.severity === 'medium').length,
204
+ low: findings.filter(f => f.severity === 'low').length,
205
+ };
206
+ const grade = calculateGrade(counts);
207
+ const restrictedCount = findings.filter(f => f.isRestricted).length;
208
+ const formatted = findings.map(f => {
209
+ const proTag = f.isRestricted ? ' [PRO]' : '';
210
+ const fixLine = f.isRestricted
211
+ ? ' Fix: Upgrade to Pro to see fix details'
212
+ : ` Fix: ${f.fix}`;
213
+ return `[${f.severity.toUpperCase()}]${proTag} Line ${f.line}: ${f.name}\n${fixLine}`;
214
+ }).join('\n\n');
215
+ let footer = `\nGrade: ${grade} | Tier: ${tierLabel}`;
216
+ if (restrictedCount > 0 && userTier === 'free') {
217
+ footer += `\n\n${restrictedCount} finding(s) require Pro to see fix details.`;
218
+ }
163
219
  return {
164
220
  content: [
165
221
  {
166
222
  type: 'text',
167
- text: `Found ${findings.length} issue(s):\n\n${formatted}`,
223
+ text: `Found ${findings.length} issue(s):\n\n${formatted}${footer}`,
168
224
  },
169
225
  ],
170
226
  };
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indicated/vibeguard",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Local CLI security scanner for AI-generated code",
5
5
  "main": "dist/cli/index.js",
6
6
  "bin": {
package/src/mcp/server.ts CHANGED
@@ -4,6 +4,19 @@ import { z } from 'zod';
4
4
  import * as path from 'path';
5
5
  import { Scanner } from '../scanner';
6
6
  import { securityRules } from '../scanner/rules/definitions';
7
+ import { getLicenseKey } from '../api/license';
8
+ import { Severity, Tier } from '../types';
9
+
10
+ function calculateGrade(counts: Record<Severity, number>): string {
11
+ if (counts.critical > 0) return 'F';
12
+ if (counts.high > 2) return 'D';
13
+ if (counts.high > 0) return 'C';
14
+ if (counts.medium > 3) return 'C';
15
+ if (counts.medium > 0) return 'B';
16
+ if (counts.low > 5) return 'B';
17
+ if (counts.low > 0) return 'A';
18
+ return 'A+';
19
+ }
7
20
 
8
21
  export async function startMcpServer(): Promise<void> {
9
22
  const server = new McpServer({
@@ -21,8 +34,9 @@ export async function startMcpServer(): Promise<void> {
21
34
  },
22
35
  async ({ paths, staged_only }) => {
23
36
  try {
37
+ const licenseKey = getLicenseKey();
24
38
  const scanner = new Scanner();
25
- await scanner.initialize();
39
+ await scanner.initialize(licenseKey || undefined);
26
40
 
27
41
  const cwd = process.cwd();
28
42
  const targets = paths.map(p => path.resolve(cwd, p));
@@ -31,18 +45,21 @@ export async function startMcpServer(): Promise<void> {
31
45
  ? await scanner.scanStaged()
32
46
  : await scanner.scan(targets);
33
47
 
48
+ const userTier: Tier = scanner.getUserTier();
49
+ const tierLabel = userTier === 'pro' ? '🔓 Pro' : '🔒 Free';
50
+
34
51
  if (result.findings.length === 0) {
35
52
  return {
36
53
  content: [
37
54
  {
38
55
  type: 'text' as const,
39
- text: `✅ No security issues found in ${result.files} file(s).`,
56
+ text: `✅ No security issues found in ${result.files} file(s).\n\nGrade: A+ | Tier: ${tierLabel}`,
40
57
  },
41
58
  ],
42
59
  };
43
60
  }
44
61
 
45
- // Format findings
62
+ // Format findings with restriction info
46
63
  const findings = result.findings.map(f => ({
47
64
  severity: f.rule.severity,
48
65
  rule: f.rule.id,
@@ -51,26 +68,39 @@ export async function startMcpServer(): Promise<void> {
51
68
  line: f.line,
52
69
  message: f.rule.description,
53
70
  fix: f.rule.fix,
71
+ isRestricted: f.isRestricted,
54
72
  }));
55
73
 
56
- const counts = {
74
+ const counts: Record<Severity, number> = {
57
75
  critical: findings.filter(f => f.severity === 'critical').length,
58
76
  high: findings.filter(f => f.severity === 'high').length,
59
77
  medium: findings.filter(f => f.severity === 'medium').length,
60
78
  low: findings.filter(f => f.severity === 'low').length,
61
79
  };
62
80
 
81
+ const grade = calculateGrade(counts);
82
+ const restrictedCount = findings.filter(f => f.isRestricted).length;
83
+
63
84
  const summary = `Found ${findings.length} issue(s): ${counts.critical} critical, ${counts.high} high, ${counts.medium} medium, ${counts.low} low`;
64
85
 
65
- const formattedFindings = findings.map(f =>
66
- `[${f.severity.toUpperCase()}] ${f.file}:${f.line}\n ${f.name}\n Fix: ${f.fix}`
67
- ).join('\n\n');
86
+ const formattedFindings = findings.map(f => {
87
+ const proTag = f.isRestricted ? ' [PRO]' : '';
88
+ const fixLine = f.isRestricted
89
+ ? ' Fix: Upgrade to Pro to see fix details'
90
+ : ` Fix: ${f.fix}`;
91
+ return `[${f.severity.toUpperCase()}]${proTag} ${f.file}:${f.line}\n ${f.name}\n${fixLine}`;
92
+ }).join('\n\n');
93
+
94
+ let footer = `\nGrade: ${grade} | Tier: ${tierLabel}`;
95
+ if (restrictedCount > 0 && userTier === 'free') {
96
+ footer += `\n\n${restrictedCount} finding(s) require Pro to see fix details. Run 'vibeguard upgrade' to unlock.`;
97
+ }
68
98
 
69
99
  return {
70
100
  content: [
71
101
  {
72
102
  type: 'text' as const,
73
- text: `${summary}\n\n${formattedFindings}`,
103
+ text: `${summary}\n\n${formattedFindings}${footer}`,
74
104
  },
75
105
  ],
76
106
  };
@@ -136,10 +166,13 @@ export async function startMcpServer(): Promise<void> {
136
166
 
137
167
  fs.writeFileSync(tempFile, code);
138
168
 
169
+ const licenseKey = getLicenseKey();
139
170
  const scanner = new Scanner();
140
- await scanner.initialize();
171
+ await scanner.initialize(licenseKey || undefined);
141
172
 
142
173
  const result = await scanner.scan([tempFile]);
174
+ const userTier: Tier = scanner.getUserTier();
175
+ const tierLabel = userTier === 'pro' ? '🔓 Pro' : '🔒 Free';
143
176
 
144
177
  // Clean up
145
178
  fs.unlinkSync(tempFile);
@@ -149,7 +182,7 @@ export async function startMcpServer(): Promise<void> {
149
182
  content: [
150
183
  {
151
184
  type: 'text' as const,
152
- text: '✅ No security issues found in this code snippet.',
185
+ text: `✅ No security issues found in this code snippet.\n\nGrade: A+ | Tier: ${tierLabel}`,
153
186
  },
154
187
  ],
155
188
  };
@@ -161,17 +194,37 @@ export async function startMcpServer(): Promise<void> {
161
194
  name: f.rule.name,
162
195
  line: f.line,
163
196
  fix: f.rule.fix,
197
+ isRestricted: f.isRestricted,
164
198
  }));
165
199
 
166
- const formatted = findings.map(f =>
167
- `[${f.severity.toUpperCase()}] Line ${f.line}: ${f.name}\n Fix: ${f.fix}`
168
- ).join('\n\n');
200
+ const counts: Record<Severity, number> = {
201
+ critical: findings.filter(f => f.severity === 'critical').length,
202
+ high: findings.filter(f => f.severity === 'high').length,
203
+ medium: findings.filter(f => f.severity === 'medium').length,
204
+ low: findings.filter(f => f.severity === 'low').length,
205
+ };
206
+
207
+ const grade = calculateGrade(counts);
208
+ const restrictedCount = findings.filter(f => f.isRestricted).length;
209
+
210
+ const formatted = findings.map(f => {
211
+ const proTag = f.isRestricted ? ' [PRO]' : '';
212
+ const fixLine = f.isRestricted
213
+ ? ' Fix: Upgrade to Pro to see fix details'
214
+ : ` Fix: ${f.fix}`;
215
+ return `[${f.severity.toUpperCase()}]${proTag} Line ${f.line}: ${f.name}\n${fixLine}`;
216
+ }).join('\n\n');
217
+
218
+ let footer = `\nGrade: ${grade} | Tier: ${tierLabel}`;
219
+ if (restrictedCount > 0 && userTier === 'free') {
220
+ footer += `\n\n${restrictedCount} finding(s) require Pro to see fix details.`;
221
+ }
169
222
 
170
223
  return {
171
224
  content: [
172
225
  {
173
226
  type: 'text' as const,
174
- text: `Found ${findings.length} issue(s):\n\n${formatted}`,
227
+ text: `Found ${findings.length} issue(s):\n\n${formatted}${footer}`,
175
228
  },
176
229
  ],
177
230
  };
package/PROGRESS.md DELETED
@@ -1,221 +0,0 @@
1
- # VibeGuard Development Progress
2
-
3
- ## Overview
4
-
5
- VibeGuard is a local CLI security scanner for AI-generated code. This document tracks what has been implemented and what remains to be done.
6
-
7
- ---
8
-
9
- ## ✅ Completed
10
-
11
- ### Phase 1: Core Scanner
12
- - [x] TypeScript project setup with npm package structure
13
- - [x] Project structure following the planned architecture
14
- - [x] JS/TS parser using @babel/parser for AST analysis
15
- - [x] Pattern-based scanning with regex
16
- - [x] Basic `scan` command with file/directory support
17
- - [x] Finding output with file, line number, and severity
18
-
19
- ### Phase 2: Full Rule Set
20
- - [x] 45 security rules implemented across all severity levels:
21
- - **Critical (8):** hardcoded-secret, sql-injection, eval-usage, command-injection, insecure-deserialization, django-debug-true, django-secret-key-exposed, django-raw-sql
22
- - **High (21):** missing-auth-route, xss-innerhtml, secrets-localstorage, supabase-no-rls, firebase-no-rules, idor-vulnerability, path-traversal, ssrf-vulnerability, open-redirect, insecure-cookie, missing-csrf, nextjs-exposed-server-action, nextjs-api-route-no-auth, nextjs-dangerouslySetInnerHTML, nextjs-exposed-env, django-no-csrf-exempt, fastapi-no-auth-dependency, nestjs-no-auth-guard, react-href-javascript, react-url-state-injection, express-session-insecure
23
- - **Medium (10):** permissive-cors, http-not-https, weak-password, hardcoded-ip, xxe-vulnerability, jwt-none-algorithm, django-allowed-hosts-all, fastapi-cors-all-origins, express-helmet-missing, express-body-parser-limit
24
- - **Low (6):** verbose-errors, missing-rate-limit, console-log-sensitive, debug-mode-enabled, prototype-pollution, nestjs-exposed-internal-exception
25
- - [x] Python parser support (pattern-based)
26
- - [x] Severity levels (critical, high, medium, low)
27
- - [x] Letter grading system (A+ to F)
28
-
29
- ### Phase 3: CLI Polish
30
- - [x] `vibeguard scan` - Main scan command
31
- - [x] Directory scanning
32
- - [x] File scanning
33
- - [x] `--staged` flag for git staged files
34
- - [x] `--json` output format
35
- - [x] `--force` to ignore exit code
36
- - [x] `--quiet` minimal output
37
- - [x] `vibeguard init` - Pre-commit hook setup
38
- - [x] Git hook creation
39
- - [x] Husky detection and integration
40
- - [x] `.vibeguardrc.json` config file creation
41
- - [x] `vibeguard rules` - List security rules
42
- - [x] `--severity` filter
43
- - [x] `--language` filter
44
- - [x] `--json` output
45
- - [x] `vibeguard login` / `vibeguard logout` - License key management
46
- - [x] `vibeguard upgrade` - Show Pro features and pricing
47
- - [x] Pretty terminal output with colors
48
- - [x] Config file support (`.vibeguardrc.json`)
49
-
50
- ### Phase 4: License System (CLI Side)
51
- - [x] `login` command implemented
52
- - [x] `logout` command implemented
53
- - [x] License key storage in `~/.vibeguard/license.json`
54
- - [x] Offline mode fallback (works without server)
55
- - [x] API client stubs ready for server integration
56
-
57
- ### Phase 5: Free/Pro Tier System
58
- - [x] `Tier` type added (`'free' | 'pro'`)
59
- - [x] All 45 rules categorized by tier:
60
- - **Free Tier (24 rules):** Basic vulnerabilities - hardcoded secrets, SQL injection, XSS, eval, command injection, CSRF, SSRF, path traversal, etc.
61
- - **Pro Tier (21 rules):** Framework-specific - Next.js (4), Django (5), FastAPI (2), NestJS (2), React (2), Express (3), Supabase, Firebase, missing-auth-route
62
- - [x] `isRestricted` field on findings for gated content
63
- - [x] `[PRO]` badge display for restricted findings
64
- - [x] Upgrade prompt showing count of restricted findings
65
- - [x] `vibeguard upgrade` command with pricing and features
66
- - [x] Tier info in JSON output (`tier`, `isRestricted` fields)
67
- - [x] License tier caching for offline mode
68
- - [x] `getUserTier()` and `getCachedTier()` functions
69
-
70
- ### Bonus: MCP Integration
71
- - [x] `vibeguard mcp` command to start MCP server
72
- - [x] `scan_code` tool - Scan files/directories
73
- - [x] `list_security_rules` tool - List available rules
74
- - [x] `check_code_snippet` tool - Validate code without saving
75
- - [x] Documentation for Claude Code integration
76
-
77
- ---
78
-
79
- ## 🔲 Not Yet Implemented
80
-
81
- ### Server-Side: Website + Backend (Phase 2 - Future Session)
82
- - [ ] Next.js 14+ website on Vercel
83
- - [ ] Landing page with feature showcase
84
- - [ ] Pricing page (Monthly $9, Annual $79)
85
- - [ ] Documentation site
86
- - [ ] User dashboard (license management, usage stats)
87
- - [ ] License validation API (`POST /v1/license/validate`)
88
- - [ ] License activation API (`POST /v1/license/activate`)
89
- - [ ] Rules API (`GET /v1/rules`) for auto-updates
90
- - [ ] Vercel Postgres database (users, licenses, activations tables)
91
- - [ ] NextAuth.js or Clerk authentication
92
-
93
- ### Server-Side: Stripe Integration (Phase 3 - Future Session)
94
- - [ ] Stripe product setup (Pro Monthly, Pro Annual)
95
- - [ ] Checkout flow
96
- - [ ] Webhook handlers for payment events
97
- - [ ] License key email delivery
98
- - [ ] Subscription management
99
-
100
- ### CLI Enhancements
101
- - [ ] `vibeguard update` - Manual rule update command
102
- - [ ] `vibeguard ignore` - Add inline ignore comments
103
- - [ ] `vibeguard fix` - Auto-fix certain issues (where safe)
104
- - [ ] Watch mode (`--watch`) for continuous scanning
105
- - [ ] SARIF output format for GitHub Advanced Security
106
- - [ ] GitLab CI/CD integration format
107
-
108
- ### Additional Rules
109
- - [x] Command injection detection
110
- - [x] Path traversal detection
111
- - [x] Insecure deserialization
112
- - [x] Hardcoded IP addresses
113
- - [x] Missing CSRF protection
114
- - [x] Insecure cookie settings
115
- - [x] Open redirect vulnerabilities
116
- - [x] XXE (XML External Entity) detection
117
- - [x] SSRF (Server-Side Request Forgery) patterns
118
- - [x] JWT none algorithm vulnerability
119
- - [x] Console logging sensitive data
120
- - [x] Debug mode enabled
121
- - [x] Prototype pollution
122
-
123
- ### Parser Improvements
124
- - [ ] Tree-sitter Python parser (currently regex-only)
125
- - [ ] Better AST-based SQL injection detection for JS
126
- - [x] Framework-specific rules (Next.js, Django, FastAPI, NestJS, Express, React)
127
- - [ ] JSX/TSX component-level analysis
128
-
129
- ### Testing
130
- - [x] Unit tests for scanner (13 tests)
131
- - [x] Unit tests for rule matching (186 tests across all 45 rules)
132
- - [x] Rule definitions tests (47 tests)
133
- - [x] Test coverage reporting (Vitest + v8)
134
- - [x] CI/CD pipeline (GitHub Actions)
135
- - [x] CI workflow: tests on Node 18, 20, 22
136
- - [x] Release workflow: auto-publish to npm on tags
137
- - [ ] Integration tests for CLI commands
138
-
139
- ### Documentation
140
- - [ ] API documentation for server endpoints
141
- - [ ] Contributing guide
142
- - [ ] Rule authoring guide
143
- - [ ] Examples for each vulnerability type
144
-
145
- ### Distribution
146
- - [ ] Publish to npm
147
- - [ ] Homebrew formula
148
- - [ ] Binary releases (pkg)
149
- - [ ] Docker image
150
-
151
- ---
152
-
153
- ## 📁 Current Project Structure
154
-
155
- ```
156
- vibeguard/
157
- ├── src/
158
- │ ├── cli/
159
- │ │ ├── index.ts # CLI entry point
160
- │ │ ├── config.ts # Config file loading
161
- │ │ ├── output.ts # Terminal formatting
162
- │ │ └── commands/
163
- │ │ ├── scan.ts # scan command
164
- │ │ ├── init.ts # init command
165
- │ │ ├── login.ts # login/logout commands
166
- │ │ ├── rules.ts # rules command
167
- │ │ ├── mcp.ts # mcp command
168
- │ │ └── upgrade.ts # upgrade command (Pro features/pricing)
169
- │ ├── scanner/
170
- │ │ ├── index.ts # Main scanner logic
171
- │ │ ├── parsers/
172
- │ │ │ ├── javascript.ts # JS/TS AST + pattern scanning
173
- │ │ │ └── python.ts # Python pattern scanning
174
- │ │ └── rules/
175
- │ │ ├── definitions.ts # 45 security rules (24 free, 21 pro)
176
- │ │ ├── loader.ts # Rule loading (local + API)
177
- │ │ └── matcher.ts # Pattern matching utilities
178
- │ ├── mcp/
179
- │ │ └── server.ts # MCP server for AI assistants
180
- │ ├── api/
181
- │ │ ├── license.ts # License management
182
- │ │ └── rules.ts # Rules API client
183
- │ └── types.ts # TypeScript types
184
- ├── dist/ # Compiled JavaScript
185
- ├── test-samples/ # Test files with vulnerabilities
186
- ├── package.json
187
- ├── tsconfig.json
188
- ├── README.md
189
- └── PROGRESS.md # This file
190
- ```
191
-
192
- ---
193
-
194
- ## 🚀 Next Steps (Recommended Order)
195
-
196
- 1. **Website + Backend (Phase 2)** - Build vibeguard-web on Vercel with Next.js
197
- - Landing page, pricing, docs
198
- - License validation API
199
- - Vercel Postgres database
200
- 2. **Stripe Integration (Phase 3)** - Payment flow and license delivery
201
- 3. **npm Publish** - Get it in users' hands
202
- 4. **CI Integration** - SARIF output for GitHub/GitLab
203
- 5. **More Rules** - Expand rule coverage based on user feedback
204
-
205
- ---
206
-
207
- ## 📊 Stats
208
-
209
- | Metric | Count |
210
- |--------|-------|
211
- | Security Rules | 45 (24 free, 21 pro) |
212
- | CLI Commands | 7 |
213
- | MCP Tools | 3 |
214
- | Supported Languages | 3 (JS, TS, Python) |
215
- | Frameworks | 6 (Next.js, Django, FastAPI, NestJS, Express, React) |
216
- | Unit Tests | 246 |
217
- | Lines of TypeScript | ~2,200 |
218
-
219
- ---
220
-
221
- *Last updated: January 30, 2026*