@vibecheckai/cli 3.3.0 → 3.5.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 (170) hide show
  1. package/bin/registry.js +389 -269
  2. package/bin/runners/cli-utils.js +2 -33
  3. package/bin/runners/context/generators/cursor.js +49 -2
  4. package/bin/runners/lib/agent-firewall/learning/learning-engine.js +849 -0
  5. package/bin/runners/lib/analyzers.js +599 -142
  6. package/bin/runners/lib/audit-logger.js +532 -0
  7. package/bin/runners/lib/authority/authorities/architecture.js +364 -0
  8. package/bin/runners/lib/authority/authorities/compliance.js +341 -0
  9. package/bin/runners/lib/authority/authorities/human.js +343 -0
  10. package/bin/runners/lib/authority/authorities/quality.js +420 -0
  11. package/bin/runners/lib/authority/authorities/security.js +228 -0
  12. package/bin/runners/lib/authority/index.js +293 -0
  13. package/bin/runners/lib/authority-badge.js +425 -425
  14. package/bin/runners/lib/bundle/bundle-intelligence.js +846 -0
  15. package/bin/runners/lib/cli-charts.js +368 -0
  16. package/bin/runners/lib/cli-config-display.js +405 -0
  17. package/bin/runners/lib/cli-demo.js +275 -0
  18. package/bin/runners/lib/cli-errors.js +438 -0
  19. package/bin/runners/lib/cli-help-formatter.js +439 -0
  20. package/bin/runners/lib/cli-interactive-menu.js +509 -0
  21. package/bin/runners/lib/cli-prompts.js +441 -0
  22. package/bin/runners/lib/cli-scan-cards.js +362 -0
  23. package/bin/runners/lib/compliance-reporter.js +710 -0
  24. package/bin/runners/lib/conductor/index.js +671 -0
  25. package/bin/runners/lib/easy/README.md +123 -0
  26. package/bin/runners/lib/easy/index.js +140 -0
  27. package/bin/runners/lib/easy/interactive-wizard.js +788 -0
  28. package/bin/runners/lib/easy/one-click-firewall.js +564 -0
  29. package/bin/runners/lib/easy/zero-config-reality.js +714 -0
  30. package/bin/runners/lib/engines/accessibility-engine.js +218 -18
  31. package/bin/runners/lib/engines/api-consistency-engine.js +335 -30
  32. package/bin/runners/lib/engines/async-patterns-engine.js +444 -0
  33. package/bin/runners/lib/engines/bundle-size-engine.js +433 -0
  34. package/bin/runners/lib/engines/confidence-scoring.js +276 -0
  35. package/bin/runners/lib/engines/context-detection.js +264 -0
  36. package/bin/runners/lib/engines/cross-file-analysis-engine.js +292 -27
  37. package/bin/runners/lib/engines/database-patterns-engine.js +429 -0
  38. package/bin/runners/lib/engines/duplicate-code-engine.js +354 -0
  39. package/bin/runners/lib/engines/empty-catch-engine.js +127 -17
  40. package/bin/runners/lib/engines/env-variables-engine.js +458 -0
  41. package/bin/runners/lib/engines/error-handling-engine.js +437 -0
  42. package/bin/runners/lib/engines/false-positive-prevention.js +630 -0
  43. package/bin/runners/lib/engines/framework-adapters/index.js +607 -0
  44. package/bin/runners/lib/engines/framework-detection.js +508 -0
  45. package/bin/runners/lib/engines/import-order-engine.js +429 -0
  46. package/bin/runners/lib/engines/mock-data-engine.js +53 -10
  47. package/bin/runners/lib/engines/naming-conventions-engine.js +544 -0
  48. package/bin/runners/lib/engines/noise-reduction-engine.js +452 -0
  49. package/bin/runners/lib/engines/orchestrator.js +334 -0
  50. package/bin/runners/lib/engines/performance-issues-engine.js +176 -36
  51. package/bin/runners/lib/engines/react-patterns-engine.js +457 -0
  52. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +382 -54
  53. package/bin/runners/lib/engines/type-aware-engine.js +263 -39
  54. package/bin/runners/lib/engines/vibecheck-engines/index.js +122 -13
  55. package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +806 -0
  56. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +373 -73
  57. package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +577 -0
  58. package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +543 -0
  59. package/bin/runners/lib/engines/vibecheck-engines.js +514 -0
  60. package/bin/runners/lib/enhanced-features/index.js +305 -0
  61. package/bin/runners/lib/enhanced-output.js +631 -0
  62. package/bin/runners/lib/enterprise.js +300 -0
  63. package/bin/runners/lib/entitlements-v2.js +161 -478
  64. package/bin/runners/lib/firewall/command-validator.js +351 -0
  65. package/bin/runners/lib/firewall/config.js +341 -0
  66. package/bin/runners/lib/firewall/content-validator.js +519 -0
  67. package/bin/runners/lib/firewall/index.js +101 -0
  68. package/bin/runners/lib/firewall/path-validator.js +256 -0
  69. package/bin/runners/lib/html-proof-report.js +350 -700
  70. package/bin/runners/lib/intelligence/cross-repo-intelligence.js +817 -0
  71. package/bin/runners/lib/mcp-utils.js +425 -0
  72. package/bin/runners/lib/missions/plan.js +46 -6
  73. package/bin/runners/lib/missions/templates.js +232 -0
  74. package/bin/runners/lib/output/index.js +1022 -0
  75. package/bin/runners/lib/policy-engine.js +652 -0
  76. package/bin/runners/lib/polish/autofix/accessibility-fixes.js +333 -0
  77. package/bin/runners/lib/polish/autofix/async-handlers.js +273 -0
  78. package/bin/runners/lib/polish/autofix/dead-code.js +280 -0
  79. package/bin/runners/lib/polish/autofix/imports-optimizer.js +344 -0
  80. package/bin/runners/lib/polish/autofix/index.js +200 -0
  81. package/bin/runners/lib/polish/autofix/remove-consoles.js +209 -0
  82. package/bin/runners/lib/polish/autofix/strengthen-types.js +245 -0
  83. package/bin/runners/lib/polish/backend-checks.js +148 -0
  84. package/bin/runners/lib/polish/documentation-checks.js +111 -0
  85. package/bin/runners/lib/polish/frontend-checks.js +168 -0
  86. package/bin/runners/lib/polish/index.js +71 -0
  87. package/bin/runners/lib/polish/infrastructure-checks.js +131 -0
  88. package/bin/runners/lib/polish/library-detection.js +175 -0
  89. package/bin/runners/lib/polish/performance-checks.js +100 -0
  90. package/bin/runners/lib/polish/security-checks.js +148 -0
  91. package/bin/runners/lib/polish/utils.js +203 -0
  92. package/bin/runners/lib/prompt-builder.js +540 -0
  93. package/bin/runners/lib/proof-certificate.js +634 -0
  94. package/bin/runners/lib/reality/accessibility-audit.js +946 -0
  95. package/bin/runners/lib/reality/api-contract-validator.js +1012 -0
  96. package/bin/runners/lib/reality/chaos-engineering.js +1084 -0
  97. package/bin/runners/lib/reality/performance-tracker.js +1077 -0
  98. package/bin/runners/lib/reality/scenario-generator.js +1404 -0
  99. package/bin/runners/lib/reality/visual-regression.js +852 -0
  100. package/bin/runners/lib/reality-profiler.js +717 -0
  101. package/bin/runners/lib/replay/flight-recorder-viewer.js +1160 -0
  102. package/bin/runners/lib/review/ai-code-review.js +832 -0
  103. package/bin/runners/lib/rules/custom-rule-engine.js +985 -0
  104. package/bin/runners/lib/sbom-generator.js +641 -0
  105. package/bin/runners/lib/scan-output-enhanced.js +512 -0
  106. package/bin/runners/lib/scan-output.js +65 -19
  107. package/bin/runners/lib/security/owasp-scanner.js +939 -0
  108. package/bin/runners/lib/ship-output.js +18 -25
  109. package/bin/runners/lib/terminal-ui.js +113 -1
  110. package/bin/runners/lib/unified-cli-output.js +603 -430
  111. package/bin/runners/lib/upsell.js +90 -338
  112. package/bin/runners/lib/validators/contract-validator.js +283 -0
  113. package/bin/runners/lib/validators/dead-export-detector.js +279 -0
  114. package/bin/runners/lib/validators/dep-audit.js +245 -0
  115. package/bin/runners/lib/validators/env-validator.js +319 -0
  116. package/bin/runners/lib/validators/index.js +120 -0
  117. package/bin/runners/lib/validators/license-checker.js +252 -0
  118. package/bin/runners/lib/validators/route-validator.js +290 -0
  119. package/bin/runners/runAIAgent.js +5 -10
  120. package/bin/runners/runAgent.js +3 -0
  121. package/bin/runners/runApprove.js +1233 -1200
  122. package/bin/runners/runAuth.js +22 -1
  123. package/bin/runners/runAuthority.js +528 -0
  124. package/bin/runners/runCheckpoint.js +4 -24
  125. package/bin/runners/runClassify.js +862 -859
  126. package/bin/runners/runConductor.js +772 -0
  127. package/bin/runners/runContainer.js +366 -0
  128. package/bin/runners/runContext.js +3 -0
  129. package/bin/runners/runDoctor.js +28 -41
  130. package/bin/runners/runEasy.js +410 -0
  131. package/bin/runners/runFirewall.js +3 -0
  132. package/bin/runners/runFirewallHook.js +3 -0
  133. package/bin/runners/runFix.js +76 -66
  134. package/bin/runners/runGuard.js +411 -18
  135. package/bin/runners/runIaC.js +372 -0
  136. package/bin/runners/runInit.js +10 -60
  137. package/bin/runners/runMcp.js +11 -12
  138. package/bin/runners/runPolish.js +240 -64
  139. package/bin/runners/runPromptFirewall.js +5 -12
  140. package/bin/runners/runProve.js +20 -55
  141. package/bin/runners/runReality.js +68 -59
  142. package/bin/runners/runReport.js +31 -5
  143. package/bin/runners/runRuntime.js +5 -8
  144. package/bin/runners/runScan.js +194 -1273
  145. package/bin/runners/runShip.js +695 -47
  146. package/bin/runners/runTruth.js +3 -0
  147. package/bin/runners/runValidate.js +7 -11
  148. package/bin/runners/runVibe.js +791 -0
  149. package/bin/runners/runWatch.js +14 -23
  150. package/bin/vibecheck.js +179 -65
  151. package/mcp-server/index.js +202 -636
  152. package/mcp-server/lib/api-client.cjs +7 -299
  153. package/mcp-server/package.json +1 -1
  154. package/mcp-server/tier-auth.js +175 -574
  155. package/mcp-server/tools-v3.js +800 -505
  156. package/mcp-server/tools.js +495 -0
  157. package/package.json +1 -1
  158. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
  159. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
  160. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
  161. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
  162. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
  163. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
  164. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
  165. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
  166. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
  167. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
  168. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
  169. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
  170. package/mcp-server/index-v1.js +0 -698
@@ -0,0 +1,425 @@
1
+ /**
2
+ * MCP Utilities
3
+ *
4
+ * Shared utilities for MCP server implementations.
5
+ * Used by both the stdio (mcp-server/index.js) and HTTP (runMcp.js) implementations.
6
+ */
7
+
8
+ "use strict";
9
+
10
+ const path = require("path");
11
+ const fs = require("fs");
12
+
13
+ // =============================================================================
14
+ // TIER DEFINITIONS (mirrors @vibecheck/core)
15
+ // =============================================================================
16
+
17
+ const TIERS = {
18
+ free: {
19
+ name: 'FREE',
20
+ price: '$0',
21
+ rateLimit: { rpm: 10, burst: 20, daily: 100 },
22
+ },
23
+ pro: {
24
+ name: 'PRO',
25
+ price: '$69/mo',
26
+ rateLimit: { rpm: 100, burst: 200, daily: Infinity },
27
+ },
28
+ };
29
+
30
+ // =============================================================================
31
+ // TOOL TIER MAPPINGS
32
+ // =============================================================================
33
+
34
+ const TOOL_TIERS = {
35
+ // FREE - Inspect & Observe
36
+ 'vibecheck.scan': 'free',
37
+ 'vibecheck.ctx': 'free',
38
+ 'vibecheck.verify': 'free',
39
+ 'vibecheck.report': 'free',
40
+ 'vibecheck.status': 'free',
41
+ 'vibecheck.doctor': 'free',
42
+ 'vibecheck.firewall': 'free',
43
+ 'authority.list': 'free',
44
+ 'authority.classify': 'free',
45
+ 'vibecheck_conductor_status': 'free',
46
+
47
+ // HTTP tools (legacy names)
48
+ 'repo_map': 'free',
49
+ 'routes_list': 'free',
50
+ 'truthpack_get': 'free',
51
+ 'findings_latest': 'free',
52
+
53
+ // PRO - Fix, Prove & Enforce
54
+ 'vibecheck.ship': 'pro',
55
+ 'vibecheck.fix': 'pro',
56
+ 'vibecheck.prove': 'pro',
57
+ 'vibecheck.gate': 'pro',
58
+ 'vibecheck.badge': 'pro',
59
+ 'vibecheck.reality': 'pro',
60
+ 'vibecheck.ai_test': 'pro',
61
+ 'vibecheck.share': 'pro',
62
+ 'authority.approve': 'pro',
63
+ 'vibecheck_conductor_register': 'pro',
64
+ 'vibecheck_conductor_acquire_lock': 'pro',
65
+ 'vibecheck_conductor_release_lock': 'pro',
66
+ 'vibecheck_conductor_propose': 'pro',
67
+ 'vibecheck_conductor_terminate': 'pro',
68
+ 'vibecheck_agent_firewall_intercept': 'pro',
69
+
70
+ // HTTP tools (legacy names)
71
+ 'run_ship': 'pro',
72
+ 'policy_check': 'pro',
73
+ };
74
+
75
+ /**
76
+ * Check if tool requires pro tier
77
+ */
78
+ function requiresPro(toolName) {
79
+ return TOOL_TIERS[toolName] === 'pro';
80
+ }
81
+
82
+ /**
83
+ * Check tier access for a tool
84
+ */
85
+ function checkTierAccess(toolName, userTier) {
86
+ const required = TOOL_TIERS[toolName];
87
+
88
+ // Unknown tools default to pro
89
+ if (!required) {
90
+ return {
91
+ allowed: userTier === 'pro',
92
+ error: userTier !== 'pro'
93
+ ? `Unknown tool "${toolName}" requires Pro tier`
94
+ : undefined,
95
+ };
96
+ }
97
+
98
+ if (required === 'free') {
99
+ return { allowed: true };
100
+ }
101
+
102
+ if (userTier === 'pro') {
103
+ return { allowed: true };
104
+ }
105
+
106
+ return {
107
+ allowed: false,
108
+ error: `${toolName} requires Pro ($69/mo). Upgrade at https://vibecheckai.dev/pricing`,
109
+ };
110
+ }
111
+
112
+ // =============================================================================
113
+ // RATE LIMITING
114
+ // =============================================================================
115
+
116
+ class RateLimiter {
117
+ constructor() {
118
+ this.clients = new Map();
119
+ }
120
+
121
+ check(clientId, tier) {
122
+ const now = Date.now();
123
+ const limits = TIERS[tier]?.rateLimit || TIERS.free.rateLimit;
124
+
125
+ if (!this.clients.has(clientId)) {
126
+ this.clients.set(clientId, {
127
+ requests: [],
128
+ dailyCount: 0,
129
+ dailyReset: this.getNextMidnight(),
130
+ });
131
+ }
132
+
133
+ const client = this.clients.get(clientId);
134
+
135
+ // Reset daily counter if needed
136
+ if (now > client.dailyReset) {
137
+ client.dailyCount = 0;
138
+ client.dailyReset = this.getNextMidnight();
139
+ }
140
+
141
+ // Clean old requests (older than 1 minute)
142
+ client.requests = client.requests.filter(time => now - time < 60000);
143
+
144
+ // Check RPM limit
145
+ if (client.requests.length >= limits.rpm) {
146
+ return {
147
+ allowed: false,
148
+ error: 'Rate limit exceeded',
149
+ resetAt: Math.min(...client.requests) + 60000,
150
+ remaining: 0,
151
+ };
152
+ }
153
+
154
+ // Check daily limit
155
+ if (limits.daily !== Infinity && client.dailyCount >= limits.daily) {
156
+ return {
157
+ allowed: false,
158
+ error: 'Daily quota exceeded',
159
+ resetAt: client.dailyReset,
160
+ remaining: 0,
161
+ };
162
+ }
163
+
164
+ // Record request
165
+ client.requests.push(now);
166
+ client.dailyCount++;
167
+
168
+ return {
169
+ allowed: true,
170
+ remaining: limits.rpm - client.requests.length,
171
+ dailyRemaining: limits.daily === Infinity
172
+ ? Infinity
173
+ : limits.daily - client.dailyCount,
174
+ };
175
+ }
176
+
177
+ getNextMidnight() {
178
+ const tomorrow = new Date();
179
+ tomorrow.setHours(24, 0, 0, 0);
180
+ return tomorrow.getTime();
181
+ }
182
+
183
+ cleanup() {
184
+ const now = Date.now();
185
+ for (const [clientId, client] of this.clients) {
186
+ // Remove clients with no recent activity
187
+ if (client.requests.length === 0 && now > client.dailyReset) {
188
+ this.clients.delete(clientId);
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ // =============================================================================
195
+ // AUDIT LOGGING
196
+ // =============================================================================
197
+
198
+ class AuditLogger {
199
+ constructor(logPath) {
200
+ this.logPath = logPath || path.join(process.cwd(), '.vibecheck', 'audit', 'mcp-audit.jsonl');
201
+ this.ensureDir();
202
+ }
203
+
204
+ ensureDir() {
205
+ try {
206
+ fs.mkdirSync(path.dirname(this.logPath), { recursive: true });
207
+ } catch {
208
+ // Ignore
209
+ }
210
+ }
211
+
212
+ log(event) {
213
+ const entry = {
214
+ timestamp: new Date().toISOString(),
215
+ ...event,
216
+ };
217
+
218
+ try {
219
+ fs.appendFileSync(this.logPath, JSON.stringify(entry) + '\n');
220
+ } catch (err) {
221
+ // Silent fail for audit logging
222
+ }
223
+ }
224
+
225
+ logToolCall(toolName, tier, success, duration, error) {
226
+ this.log({
227
+ type: 'tool_call',
228
+ tool: toolName,
229
+ tier,
230
+ success,
231
+ duration,
232
+ error: error?.message,
233
+ });
234
+ }
235
+
236
+ logAuth(tier, success, error) {
237
+ this.log({
238
+ type: 'auth',
239
+ tier,
240
+ success,
241
+ error: error?.message,
242
+ });
243
+ }
244
+ }
245
+
246
+ // =============================================================================
247
+ // PATH SECURITY
248
+ // =============================================================================
249
+
250
+ const BLOCKED_PATHS = [
251
+ '.env',
252
+ '.env.local',
253
+ '.env.production',
254
+ 'credentials',
255
+ 'secrets',
256
+ '.ssh',
257
+ '.aws',
258
+ '.npmrc',
259
+ '.pypirc',
260
+ ];
261
+
262
+ /**
263
+ * Check if path is safe to access
264
+ */
265
+ function isPathSafe(requestedPath, projectRoot) {
266
+ const resolved = path.resolve(projectRoot, requestedPath);
267
+
268
+ // Must be within project root
269
+ if (!resolved.startsWith(projectRoot)) {
270
+ return { safe: false, error: 'Path traversal detected' };
271
+ }
272
+
273
+ // Check blocked paths
274
+ const relative = path.relative(projectRoot, resolved);
275
+ for (const blocked of BLOCKED_PATHS) {
276
+ if (relative.includes(blocked) || relative.startsWith(blocked)) {
277
+ return { safe: false, error: `Access to ${blocked} is blocked` };
278
+ }
279
+ }
280
+
281
+ return { safe: true };
282
+ }
283
+
284
+ // =============================================================================
285
+ // INPUT VALIDATION
286
+ // =============================================================================
287
+
288
+ /**
289
+ * Validate tool arguments against schema
290
+ */
291
+ function validateArgs(args, schema) {
292
+ const errors = [];
293
+
294
+ if (!schema || !schema.properties) {
295
+ return { valid: true, args };
296
+ }
297
+
298
+ const validated = {};
299
+
300
+ for (const [key, prop] of Object.entries(schema.properties)) {
301
+ const value = args?.[key];
302
+
303
+ // Check required
304
+ if (schema.required?.includes(key) && value === undefined) {
305
+ errors.push(`Missing required argument: ${key}`);
306
+ continue;
307
+ }
308
+
309
+ // Use default if not provided
310
+ if (value === undefined && prop.default !== undefined) {
311
+ validated[key] = prop.default;
312
+ continue;
313
+ }
314
+
315
+ // Skip undefined optional args
316
+ if (value === undefined) {
317
+ continue;
318
+ }
319
+
320
+ // Type check
321
+ if (prop.type === 'string' && typeof value !== 'string') {
322
+ errors.push(`${key} must be a string`);
323
+ } else if (prop.type === 'boolean' && typeof value !== 'boolean') {
324
+ errors.push(`${key} must be a boolean`);
325
+ } else if (prop.type === 'number' && typeof value !== 'number') {
326
+ errors.push(`${key} must be a number`);
327
+ } else if (prop.type === 'array' && !Array.isArray(value)) {
328
+ errors.push(`${key} must be an array`);
329
+ }
330
+
331
+ // Enum check
332
+ if (prop.enum && !prop.enum.includes(value)) {
333
+ errors.push(`${key} must be one of: ${prop.enum.join(', ')}`);
334
+ }
335
+
336
+ validated[key] = value;
337
+ }
338
+
339
+ return {
340
+ valid: errors.length === 0,
341
+ errors,
342
+ args: validated,
343
+ };
344
+ }
345
+
346
+ // =============================================================================
347
+ // SECRET REDACTION
348
+ // =============================================================================
349
+
350
+ const SECRET_PATTERNS = [
351
+ /sk[_-][a-zA-Z0-9]{20,}/g, // Stripe keys
352
+ /pk[_-][a-zA-Z0-9]{20,}/g, // Stripe public keys
353
+ /ghp_[a-zA-Z0-9]{36}/g, // GitHub tokens
354
+ /gho_[a-zA-Z0-9]{36}/g, // GitHub OAuth
355
+ /xox[baprs]-[a-zA-Z0-9-]{10,}/g, // Slack tokens
356
+ /Bearer\s+[a-zA-Z0-9._-]+/gi, // Bearer tokens
357
+ /api[_-]?key[_-]?[=:]["']?[a-zA-Z0-9]{16,}/gi,
358
+ /password[_-]?[=:]["']?[^\s"']+/gi,
359
+ /secret[_-]?[=:]["']?[^\s"']+/gi,
360
+ ];
361
+
362
+ /**
363
+ * Redact secrets from output
364
+ */
365
+ function redactSecrets(text) {
366
+ if (!text || typeof text !== 'string') return text;
367
+
368
+ let redacted = text;
369
+ for (const pattern of SECRET_PATTERNS) {
370
+ redacted = redacted.replace(pattern, '[REDACTED]');
371
+ }
372
+ return redacted;
373
+ }
374
+
375
+ /**
376
+ * Redact secrets from object (deep)
377
+ */
378
+ function redactObject(obj) {
379
+ if (!obj) return obj;
380
+ if (typeof obj === 'string') return redactSecrets(obj);
381
+ if (Array.isArray(obj)) return obj.map(redactObject);
382
+ if (typeof obj !== 'object') return obj;
383
+
384
+ const result = {};
385
+ for (const [key, value] of Object.entries(obj)) {
386
+ // Always redact certain keys
387
+ const lowerKey = key.toLowerCase();
388
+ if (lowerKey.includes('password') ||
389
+ lowerKey.includes('secret') ||
390
+ lowerKey.includes('token') ||
391
+ lowerKey.includes('apikey') ||
392
+ lowerKey.includes('api_key')) {
393
+ result[key] = '[REDACTED]';
394
+ } else {
395
+ result[key] = redactObject(value);
396
+ }
397
+ }
398
+ return result;
399
+ }
400
+
401
+ // =============================================================================
402
+ // EXPORTS
403
+ // =============================================================================
404
+
405
+ module.exports = {
406
+ // Tier management
407
+ TIERS,
408
+ TOOL_TIERS,
409
+ requiresPro,
410
+ checkTierAccess,
411
+
412
+ // Rate limiting
413
+ RateLimiter,
414
+
415
+ // Audit logging
416
+ AuditLogger,
417
+
418
+ // Security
419
+ isPathSafe,
420
+ validateArgs,
421
+ redactSecrets,
422
+ redactObject,
423
+ BLOCKED_PATHS,
424
+ SECRET_PATTERNS,
425
+ };
@@ -69,6 +69,7 @@ const CATEGORY_TO_MISSION_TYPE = {
69
69
  GhostAuth: "ADD_SERVER_AUTH",
70
70
  AuthCoverage: "ADD_SERVER_AUTH",
71
71
  AuthDrift: "FIX_AUTH_DRIFT",
72
+ SecurityVulnerabilities: "FIX_SECURITY_VULN",
72
73
 
73
74
  // Billing & Payments
74
75
  Billing: "FIX_STRIPE_WEBHOOKS",
@@ -77,9 +78,12 @@ const CATEGORY_TO_MISSION_TYPE = {
77
78
  // Routes & APIs
78
79
  MissingRoute: "FIX_MISSING_ROUTE",
79
80
  RouteDrift: "FIX_ROUTE_DRIFT",
81
+ APIConsistency: "FIX_API_CONSISTENCY",
80
82
 
81
83
  // Environment & Config
82
84
  EnvContract: "FIX_ENV_CONTRACT",
85
+ EnvVariable: "FIX_ENV_VALIDATION",
86
+ EnvSetup: "FIX_ENV_SETUP",
83
87
 
84
88
  // Reality/Runtime issues
85
89
  FakeSuccess: "FIX_FAKE_SUCCESS",
@@ -93,6 +97,26 @@ const CATEGORY_TO_MISSION_TYPE = {
93
97
  TestKeys: "FIX_TEST_KEYS",
94
98
  HardcodedSecrets: "FIX_HARDCODED_SECRETS",
95
99
  SilentFallback: "FIX_SILENT_FALLBACK",
100
+ CodeQuality: "FIX_CODE_QUALITY",
101
+
102
+ // React Patterns (V5)
103
+ ReactPatterns: "FIX_REACT_PATTERN",
104
+
105
+ // Database Patterns (V5)
106
+ DatabasePatterns: "FIX_DATABASE_PATTERN",
107
+
108
+ // Async Patterns (V5)
109
+ AsyncPatterns: "FIX_ASYNC_PATTERN",
110
+
111
+ // Error Handling (V5)
112
+ ErrorHandling: "FIX_ERROR_HANDLING",
113
+
114
+ // Performance (V5)
115
+ Performance: "FIX_PERFORMANCE",
116
+ BundleSize: "FIX_BUNDLE_SIZE",
117
+
118
+ // Accessibility
119
+ Accessibility: "FIX_ACCESSIBILITY",
96
120
  };
97
121
 
98
122
  /**
@@ -104,6 +128,7 @@ const MISSION_PRIORITY = {
104
128
  REMOVE_OWNER_MODE: 1,
105
129
  FIX_HARDCODED_SECRETS: 2,
106
130
  FIX_AUTH_DRIFT: 3,
131
+ FIX_SECURITY_VULN: 4,
107
132
 
108
133
  // P1: Security & billing (fix before shipping)
109
134
  FIX_STRIPE_WEBHOOKS: 10,
@@ -116,17 +141,32 @@ const MISSION_PRIORITY = {
116
141
  FIX_PLACEHOLDER_DATA: 21,
117
142
  FIX_FAKE_SUCCESS: 22,
118
143
 
119
- // P3: Code quality (fix when possible)
144
+ // P3: Code quality & patterns (fix when possible)
120
145
  FIX_MISSING_ROUTE: 30,
121
146
  FIX_ROUTE_DRIFT: 31,
122
147
  FIX_ENV_CONTRACT: 32,
123
- FIX_EMPTY_CATCH: 33,
124
- FIX_SILENT_FALLBACK: 34,
148
+ FIX_ENV_VALIDATION: 33,
149
+ FIX_ENV_SETUP: 34,
150
+ FIX_EMPTY_CATCH: 35,
151
+ FIX_SILENT_FALLBACK: 36,
152
+ FIX_ERROR_HANDLING: 37,
153
+ FIX_API_CONSISTENCY: 38,
154
+
155
+ // P4: React & Framework patterns
156
+ FIX_REACT_PATTERN: 40,
157
+ FIX_ASYNC_PATTERN: 41,
158
+ FIX_DATABASE_PATTERN: 42,
159
+ FIX_CODE_QUALITY: 43,
160
+
161
+ // P5: Performance & optimization
162
+ FIX_PERFORMANCE: 50,
163
+ FIX_BUNDLE_SIZE: 51,
125
164
 
126
- // P4: UI issues (fix before polish)
127
- FIX_DEAD_UI: 40,
165
+ // P6: UI & accessibility
166
+ FIX_DEAD_UI: 60,
167
+ FIX_ACCESSIBILITY: 61,
128
168
 
129
- // P5: Generic (lowest priority)
169
+ // P7: Generic (lowest priority)
130
170
  GENERIC_FIX: 99,
131
171
  };
132
172