@vibecheckai/cli 3.2.5 → 3.3.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 (197) hide show
  1. package/bin/.generated +25 -25
  2. package/bin/dev/run-v2-torture.js +30 -30
  3. package/bin/registry.js +192 -5
  4. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
  5. package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
  6. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  7. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  8. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  9. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  10. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  11. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  12. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  13. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  14. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  15. package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
  16. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
  17. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
  18. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  19. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  20. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  21. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  22. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  23. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  24. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  25. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  26. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  27. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  28. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  29. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  30. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  31. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  32. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  33. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  34. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  35. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  36. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  37. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  38. package/bin/runners/lib/analyzers.js +81 -18
  39. package/bin/runners/lib/api-client.js +269 -0
  40. package/bin/runners/lib/auth-truth.js +193 -193
  41. package/bin/runners/lib/authority-badge.js +425 -0
  42. package/bin/runners/lib/backup.js +62 -62
  43. package/bin/runners/lib/billing.js +107 -107
  44. package/bin/runners/lib/claims.js +118 -118
  45. package/bin/runners/lib/cli-output.js +7 -1
  46. package/bin/runners/lib/cli-ui.js +540 -540
  47. package/bin/runners/lib/contracts/auth-contract.js +202 -202
  48. package/bin/runners/lib/contracts/env-contract.js +181 -181
  49. package/bin/runners/lib/contracts/external-contract.js +206 -206
  50. package/bin/runners/lib/contracts/guard.js +168 -168
  51. package/bin/runners/lib/contracts/index.js +89 -89
  52. package/bin/runners/lib/contracts/plan-validator.js +311 -311
  53. package/bin/runners/lib/contracts/route-contract.js +199 -199
  54. package/bin/runners/lib/contracts.js +804 -804
  55. package/bin/runners/lib/detect.js +89 -89
  56. package/bin/runners/lib/doctor/autofix.js +254 -254
  57. package/bin/runners/lib/doctor/index.js +37 -37
  58. package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
  59. package/bin/runners/lib/doctor/modules/index.js +46 -46
  60. package/bin/runners/lib/doctor/modules/network.js +250 -250
  61. package/bin/runners/lib/doctor/modules/project.js +312 -312
  62. package/bin/runners/lib/doctor/modules/runtime.js +224 -224
  63. package/bin/runners/lib/doctor/modules/security.js +348 -348
  64. package/bin/runners/lib/doctor/modules/system.js +213 -213
  65. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
  66. package/bin/runners/lib/doctor/reporter.js +262 -262
  67. package/bin/runners/lib/doctor/service.js +262 -262
  68. package/bin/runners/lib/doctor/types.js +113 -113
  69. package/bin/runners/lib/doctor/ui.js +263 -263
  70. package/bin/runners/lib/doctor-v2.js +608 -608
  71. package/bin/runners/lib/drift.js +425 -425
  72. package/bin/runners/lib/enforcement.js +72 -72
  73. package/bin/runners/lib/enterprise-detect.js +603 -603
  74. package/bin/runners/lib/enterprise-init.js +942 -942
  75. package/bin/runners/lib/env-resolver.js +417 -417
  76. package/bin/runners/lib/env-template.js +66 -66
  77. package/bin/runners/lib/env.js +189 -189
  78. package/bin/runners/lib/error-handler.js +16 -9
  79. package/bin/runners/lib/exit-codes.js +275 -0
  80. package/bin/runners/lib/extractors/client-calls.js +990 -990
  81. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
  82. package/bin/runners/lib/extractors/fastify-routes.js +426 -426
  83. package/bin/runners/lib/extractors/index.js +363 -363
  84. package/bin/runners/lib/extractors/next-routes.js +524 -524
  85. package/bin/runners/lib/extractors/proof-graph.js +431 -431
  86. package/bin/runners/lib/extractors/route-matcher.js +451 -451
  87. package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
  88. package/bin/runners/lib/extractors/ui-bindings.js +547 -547
  89. package/bin/runners/lib/findings-schema.js +281 -281
  90. package/bin/runners/lib/firewall-prompt.js +50 -50
  91. package/bin/runners/lib/global-flags.js +37 -0
  92. package/bin/runners/lib/graph/graph-builder.js +265 -265
  93. package/bin/runners/lib/graph/html-renderer.js +413 -413
  94. package/bin/runners/lib/graph/index.js +32 -32
  95. package/bin/runners/lib/graph/runtime-collector.js +215 -215
  96. package/bin/runners/lib/graph/static-extractor.js +518 -518
  97. package/bin/runners/lib/help-formatter.js +413 -0
  98. package/bin/runners/lib/html-report.js +650 -650
  99. package/bin/runners/lib/llm.js +75 -75
  100. package/bin/runners/lib/logger.js +38 -0
  101. package/bin/runners/lib/meter.js +61 -61
  102. package/bin/runners/lib/missions/evidence.js +126 -126
  103. package/bin/runners/lib/patch.js +40 -40
  104. package/bin/runners/lib/permissions/auth-model.js +213 -213
  105. package/bin/runners/lib/permissions/idor-prover.js +205 -205
  106. package/bin/runners/lib/permissions/index.js +45 -45
  107. package/bin/runners/lib/permissions/matrix-builder.js +198 -198
  108. package/bin/runners/lib/pkgjson.js +28 -28
  109. package/bin/runners/lib/policy.js +295 -295
  110. package/bin/runners/lib/preflight.js +142 -142
  111. package/bin/runners/lib/reality/correlation-detectors.js +359 -359
  112. package/bin/runners/lib/reality/index.js +318 -318
  113. package/bin/runners/lib/reality/request-hashing.js +416 -416
  114. package/bin/runners/lib/reality/request-mapper.js +453 -453
  115. package/bin/runners/lib/reality/safety-rails.js +463 -463
  116. package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
  117. package/bin/runners/lib/reality/toast-detector.js +393 -393
  118. package/bin/runners/lib/reality-findings.js +84 -84
  119. package/bin/runners/lib/receipts.js +179 -179
  120. package/bin/runners/lib/redact.js +29 -29
  121. package/bin/runners/lib/replay/capsule-manager.js +154 -154
  122. package/bin/runners/lib/replay/index.js +263 -263
  123. package/bin/runners/lib/replay/player.js +348 -348
  124. package/bin/runners/lib/replay/recorder.js +331 -331
  125. package/bin/runners/lib/report.js +135 -135
  126. package/bin/runners/lib/route-detection.js +1140 -1140
  127. package/bin/runners/lib/sandbox/index.js +59 -59
  128. package/bin/runners/lib/sandbox/proof-chain.js +399 -399
  129. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
  130. package/bin/runners/lib/sandbox/worktree.js +174 -174
  131. package/bin/runners/lib/schema-validator.js +350 -350
  132. package/bin/runners/lib/schemas/contracts.schema.json +160 -160
  133. package/bin/runners/lib/schemas/finding.schema.json +100 -100
  134. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
  135. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
  136. package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
  137. package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
  138. package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
  139. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
  140. package/bin/runners/lib/schemas/validator.js +438 -438
  141. package/bin/runners/lib/score-history.js +282 -282
  142. package/bin/runners/lib/share-pack.js +239 -239
  143. package/bin/runners/lib/snippets.js +67 -67
  144. package/bin/runners/lib/unified-cli-output.js +604 -0
  145. package/bin/runners/lib/upsell.js +658 -510
  146. package/bin/runners/lib/usage.js +153 -153
  147. package/bin/runners/lib/validate-patch.js +156 -156
  148. package/bin/runners/lib/verdict-engine.js +628 -628
  149. package/bin/runners/reality/engine.js +917 -917
  150. package/bin/runners/reality/flows.js +122 -122
  151. package/bin/runners/reality/report.js +378 -378
  152. package/bin/runners/reality/session.js +193 -193
  153. package/bin/runners/runAgent.d.ts +5 -0
  154. package/bin/runners/runApprove.js +1200 -0
  155. package/bin/runners/runAuth.js +324 -95
  156. package/bin/runners/runCheckpoint.js +39 -21
  157. package/bin/runners/runClassify.js +859 -0
  158. package/bin/runners/runContext.js +136 -24
  159. package/bin/runners/runDoctor.js +108 -68
  160. package/bin/runners/runFirewall.d.ts +5 -0
  161. package/bin/runners/runFirewallHook.d.ts +5 -0
  162. package/bin/runners/runFix.js +6 -5
  163. package/bin/runners/runGuard.js +262 -168
  164. package/bin/runners/runInit.js +3 -2
  165. package/bin/runners/runMcp.js +130 -52
  166. package/bin/runners/runPolish.js +43 -20
  167. package/bin/runners/runProve.js +1 -2
  168. package/bin/runners/runReport.js +3 -2
  169. package/bin/runners/runScan.js +145 -44
  170. package/bin/runners/runShip.js +3 -4
  171. package/bin/runners/runTruth.d.ts +5 -0
  172. package/bin/runners/runValidate.js +19 -2
  173. package/bin/runners/runWatch.js +104 -53
  174. package/bin/vibecheck.js +106 -19
  175. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  176. package/mcp-server/agent-firewall-interceptor.js +367 -31
  177. package/mcp-server/authority-tools.js +569 -0
  178. package/mcp-server/conductor/conflict-resolver.js +588 -0
  179. package/mcp-server/conductor/execution-planner.js +544 -0
  180. package/mcp-server/conductor/index.js +377 -0
  181. package/mcp-server/conductor/lock-manager.js +615 -0
  182. package/mcp-server/conductor/request-queue.js +550 -0
  183. package/mcp-server/conductor/session-manager.js +500 -0
  184. package/mcp-server/conductor/tools.js +510 -0
  185. package/mcp-server/index.js +1199 -208
  186. package/mcp-server/lib/api-client.cjs +305 -0
  187. package/mcp-server/lib/logger.cjs +30 -0
  188. package/mcp-server/logger.js +173 -0
  189. package/mcp-server/package.json +2 -2
  190. package/mcp-server/premium-tools.js +2 -2
  191. package/mcp-server/tier-auth.js +351 -136
  192. package/mcp-server/tools/index.js +72 -72
  193. package/mcp-server/truth-firewall-tools.js +145 -15
  194. package/mcp-server/vibecheck-tools.js +2 -2
  195. package/package.json +2 -3
  196. package/mcp-server/index.old.js +0 -4137
  197. package/mcp-server/package-lock.json +0 -165
@@ -0,0 +1,421 @@
1
+ /**
2
+ * Risk Vectors
3
+ *
4
+ * Defines the risk vectors and their default weights for scoring changes.
5
+ * Each vector contributes to the overall risk score.
6
+ */
7
+
8
+ "use strict";
9
+
10
+ /**
11
+ * Risk vector definitions
12
+ */
13
+ const RISK_VECTORS = {
14
+ /**
15
+ * Surface Area
16
+ * How many files are touched by the change
17
+ */
18
+ SURFACE_AREA: {
19
+ id: "surface_area",
20
+ name: "Surface Area",
21
+ description: "Number of files touched by the change",
22
+ baseWeight: 1,
23
+ calculate: (context) => {
24
+ const files = context.files || [];
25
+ const fileCount = files.length;
26
+
27
+ // Single file changes are very common and safe - no penalty
28
+ if (fileCount <= 1) return 0;
29
+
30
+ // Count "safe" files that shouldn't add to risk
31
+ const safeFiles = files.filter(f => {
32
+ const path = (f.path || f).toLowerCase();
33
+ return (
34
+ path.includes('.test.') || path.includes('.spec.') ||
35
+ path.includes('__tests__') || path.includes('__mocks__') ||
36
+ path.endsWith('.md') || path.endsWith('.mdx') ||
37
+ path.endsWith('.d.ts') || path.includes('.stories.') ||
38
+ path.endsWith('-lock.json') || path.endsWith('.lock') ||
39
+ path.includes('/docs/')
40
+ );
41
+ });
42
+
43
+ // Effective file count excludes safe files
44
+ const effectiveCount = fileCount - safeFiles.length;
45
+
46
+ // More generous thresholds
47
+ if (effectiveCount <= 1) return 0;
48
+ if (effectiveCount <= 3) return effectiveCount; // 1 point each
49
+ if (effectiveCount <= 5) return 3 + (effectiveCount - 3) * 2; // 2 points each
50
+ if (effectiveCount <= 10) return 7 + (effectiveCount - 5) * 3; // 3 points each
51
+ return 22 + (effectiveCount - 10) * 4; // 4 points each for large changes
52
+ },
53
+ },
54
+
55
+ /**
56
+ * Blast Radius
57
+ * Impact on core vs peripheral code
58
+ */
59
+ BLAST_RADIUS: {
60
+ id: "blast_radius",
61
+ name: "Blast Radius",
62
+ description: "Impact on core vs peripheral code paths",
63
+ baseWeight: 1,
64
+ calculate: (context) => {
65
+ let score = 0;
66
+ const files = context.files || [];
67
+
68
+ // For single-file changes, apply a discount since they're typically safer
69
+ const singleFileDiscount = files.length === 1 ? 0.6 : 1;
70
+
71
+ for (const file of files) {
72
+ const path = (file.path || file).toLowerCase();
73
+ let fileScore = 0;
74
+
75
+ // Tests have ZERO impact - they can't break production
76
+ if (path.includes("/test") || path.includes(".test.") || path.includes(".spec.") ||
77
+ path.includes("__tests__") || path.includes("__mocks__")) {
78
+ fileScore = 0;
79
+ }
80
+ // Documentation and config have minimal impact
81
+ else if (path.endsWith(".md") || path.endsWith(".mdx") ||
82
+ path.includes("/docs/") || path.includes("readme")) {
83
+ fileScore = 0;
84
+ }
85
+ // Type definitions are low risk
86
+ else if (path.endsWith(".d.ts") || path.includes("/types/")) {
87
+ fileScore = 2;
88
+ }
89
+ // Storybook/examples - no production impact
90
+ else if (path.includes(".stories.") || path.includes("/examples/") || path.includes("/storybook/")) {
91
+ fileScore = 0;
92
+ }
93
+ // Core paths - high impact but reduced from 25
94
+ else if (path.includes("/core/") || path.includes("/lib/") || path.includes("/shared/")) {
95
+ fileScore = 15;
96
+ }
97
+ // Database/schema - high impact
98
+ else if (path.includes("/prisma/") || path.includes("/db/") || path.includes("/schema/")) {
99
+ fileScore = 18;
100
+ }
101
+ // Service paths - medium-high impact (reduced from 20)
102
+ else if (path.includes("/services/") || path.includes("/providers/")) {
103
+ fileScore = 12;
104
+ }
105
+ // Middleware - medium-high impact (reduced from 18)
106
+ else if (path.includes("/middleware/")) {
107
+ fileScore = 10;
108
+ }
109
+ // API routes - medium impact (reduced from 15)
110
+ else if (path.includes("/routes/") || path.includes("/api/")) {
111
+ fileScore = 8;
112
+ }
113
+ // Config files - low impact (reduced from 12)
114
+ else if (path.includes("/config/")) {
115
+ fileScore = 5;
116
+ }
117
+ // Package.json is special - lock files are fine, package.json needs care
118
+ else if (path.endsWith("package.json")) {
119
+ fileScore = 8;
120
+ }
121
+ else if (path.endsWith("package-lock.json") || path.endsWith("pnpm-lock.yaml") || path.endsWith("yarn.lock")) {
122
+ fileScore = 0; // Lock files are auto-generated
123
+ }
124
+ // JSON/YAML config files - minimal impact
125
+ else if (path.endsWith(".json") || path.endsWith(".yaml") || path.endsWith(".yml")) {
126
+ fileScore = 3;
127
+ }
128
+ // Components/Pages - low impact (UI changes)
129
+ else if (path.includes("/components/") || path.includes("/pages/") || path.includes("/app/")) {
130
+ fileScore = 3;
131
+ }
132
+ // Styles - minimal impact
133
+ else if (path.endsWith(".css") || path.endsWith(".scss") || path.endsWith(".less")) {
134
+ fileScore = 1;
135
+ }
136
+ // Everything else - low impact
137
+ else {
138
+ fileScore = 2;
139
+ }
140
+
141
+ score += fileScore;
142
+ }
143
+
144
+ // Apply single-file discount
145
+ return Math.round(score * singleFileDiscount);
146
+ },
147
+ },
148
+
149
+ /**
150
+ * Irreversibility
151
+ * How hard it is to undo the change
152
+ */
153
+ IRREVERSIBILITY: {
154
+ id: "irreversibility",
155
+ name: "Irreversibility",
156
+ description: "Difficulty of undoing the change",
157
+ baseWeight: 1,
158
+ calculate: (context) => {
159
+ let score = 0;
160
+ const operations = context.operations || [];
161
+ const files = context.files || [];
162
+
163
+ for (const op of operations) {
164
+ const type = op.type?.toLowerCase();
165
+ const path = (op.path || "").toLowerCase();
166
+
167
+ // Deletions are highly irreversible
168
+ if (type === "delete") {
169
+ score += 20;
170
+ // Even more for core files
171
+ if (path.includes("/core/") || path.includes("/lib/")) {
172
+ score += 15;
173
+ }
174
+ }
175
+ // Migrations are very irreversible
176
+ else if (path.includes("migration") || path.includes("/prisma/")) {
177
+ score += 30;
178
+ }
179
+ // Schema changes are irreversible
180
+ else if (path.includes("schema") || path.includes(".prisma")) {
181
+ score += 25;
182
+ }
183
+ }
184
+
185
+ // Check for delete operations in files
186
+ for (const file of files) {
187
+ const path = (file.path || file).toLowerCase();
188
+ if (path.includes("migration")) {
189
+ score += 25;
190
+ }
191
+ }
192
+
193
+ return score;
194
+ },
195
+ },
196
+
197
+ /**
198
+ * Confidence
199
+ * How confident we are in the change's safety
200
+ */
201
+ CONFIDENCE: {
202
+ id: "confidence",
203
+ name: "Confidence Gap",
204
+ description: "Points added for unverified assumptions",
205
+ baseWeight: 1,
206
+ calculate: (context) => {
207
+ let score = 0;
208
+
209
+ // Unresolved assumptions add risk (reduced from 40 to 15 per assumption)
210
+ // Most assumptions are benign and resolve at runtime
211
+ const unresolvedAssumptions = context.unresolvedAssumptions || [];
212
+ const assumptionCount = unresolvedAssumptions.length;
213
+
214
+ // Use diminishing returns for multiple assumptions
215
+ if (assumptionCount > 0) {
216
+ // First assumption: 15 points, then 10, then 5 each for more
217
+ score += Math.min(15 + Math.max(0, assumptionCount - 1) * 5, 40);
218
+ }
219
+
220
+ // Low confidence in proposal (reduced from 30/20/10 to 15/10/5)
221
+ const confidence = context.proposalConfidence ?? 1;
222
+ if (confidence < 0.3) {
223
+ score += 15;
224
+ } else if (confidence < 0.5) {
225
+ score += 10;
226
+ } else if (confidence < 0.7) {
227
+ score += 5;
228
+ }
229
+ // Note: 0.7+ confidence adds no penalty (default is fine)
230
+
231
+ // Missing intent - only penalize if completely missing
232
+ // Many agents provide minimal but valid intents
233
+ if (!context.intent || context.intent.trim().length === 0) {
234
+ score += 8;
235
+ }
236
+
237
+ return score;
238
+ },
239
+ },
240
+
241
+ /**
242
+ * Novelty
243
+ * Whether this introduces new patterns
244
+ */
245
+ NOVELTY: {
246
+ id: "novelty",
247
+ name: "Novelty",
248
+ description: "Introduction of new patterns or dependencies",
249
+ baseWeight: 1,
250
+ calculate: (context) => {
251
+ let score = 0;
252
+
253
+ // New dependencies - only risky if adding many
254
+ // Single new dependency is very common during development
255
+ const newDependencies = context.newDependencies || [];
256
+ if (newDependencies.length > 3) {
257
+ score += 5 + (newDependencies.length - 3) * 3; // Only penalize bulk additions
258
+ }
259
+
260
+ // New files being created - very normal during development
261
+ // Only flag if creating many files at once (could be a scaffold)
262
+ const operations = context.operations || [];
263
+ const creations = operations.filter(op => op.type === "create");
264
+ if (creations.length > 5) {
265
+ score += (creations.length - 5) * 2;
266
+ }
267
+
268
+ // New env vars - reduced from 15 to 5 per var
269
+ // New env vars are common when adding features
270
+ const newEnvVars = context.newEnvVars || [];
271
+ score += Math.min(newEnvVars.length * 5, 15); // Cap at 15 points
272
+
273
+ // New routes - reduced from 8 to 3 per route
274
+ // Adding routes is normal API development
275
+ const newRoutes = context.newRoutes || [];
276
+ score += Math.min(newRoutes.length * 3, 12); // Cap at 12 points
277
+
278
+ return score;
279
+ },
280
+ },
281
+
282
+ /**
283
+ * Domain Risk
284
+ * Risk based on the domain being modified
285
+ */
286
+ DOMAIN: {
287
+ id: "domain",
288
+ name: "Domain Risk",
289
+ description: "Risk associated with specific domains",
290
+ baseWeight: 1,
291
+ calculate: (context) => {
292
+ const domains = context.domains || [];
293
+
294
+ // If no domains identified, it's likely a safe general change
295
+ if (domains.length === 0) return 0;
296
+
297
+ // Reduced domain weights to avoid over-penalizing
298
+ // Single-file auth changes shouldn't trigger blocks by themselves
299
+ const domainWeights = {
300
+ payments: 20, // Reduced from 35 - payments is sensitive but not always blocking
301
+ auth: 15, // Reduced from 30 - many auth changes are benign
302
+ security: 15, // Reduced from 30 - security patterns are common
303
+ database: 12, // Reduced from 25 - schema changes are normal
304
+ middleware: 8, // Reduced from 20 - middleware is often safe
305
+ core: 10, // Reduced from 20 - core changes happen regularly
306
+ routes: 5, // Reduced from 15 - route changes are common
307
+ contracts: 8, // Reduced from 15 - API contracts evolve
308
+ config: 3, // Reduced from 12 - config is usually safe
309
+ ui: 0, // Reduced from 5 - UI changes are generally safe
310
+ test: 0, // Reduced from 2 - tests have no production impact
311
+ general: 0, // Reduced from 3 - general is the default, shouldn't add risk
312
+ };
313
+
314
+ // Only count the highest-risk domain (don't stack)
315
+ // This prevents a file in "auth + routes" from getting double-penalized
316
+ let maxScore = 0;
317
+ for (const domain of domains) {
318
+ const weight = domainWeights[domain] ?? 2;
319
+ maxScore = Math.max(maxScore, weight);
320
+ }
321
+
322
+ return maxScore;
323
+ },
324
+ },
325
+
326
+ /**
327
+ * Side Effects
328
+ * Potential for unintended side effects
329
+ */
330
+ SIDE_EFFECTS: {
331
+ id: "side_effects",
332
+ name: "Side Effects",
333
+ description: "Potential for unintended side effects",
334
+ baseWeight: 1,
335
+ calculate: (context) => {
336
+ let score = 0;
337
+ const claims = context.claims || [];
338
+
339
+ // Network calls - very common, reduced impact
340
+ // Only penalize if there are many or if they're to external services
341
+ const networkClaims = claims.filter(c =>
342
+ c.type === "fetch" || c.type === "api_call" || c.type === "network"
343
+ );
344
+ // First 3 network calls are free (normal API usage)
345
+ if (networkClaims.length > 3) {
346
+ score += (networkClaims.length - 3) * 5;
347
+ }
348
+
349
+ // File system operations - only server-side concerns
350
+ const fsClaims = claims.filter(c =>
351
+ c.type === "fs_write" || c.type === "fs_delete"
352
+ );
353
+ // Writes are more concerning than reads
354
+ const writeOps = fsClaims.filter(c => c.type === "fs_write");
355
+ const deleteOps = fsClaims.filter(c => c.type === "fs_delete");
356
+ score += writeOps.length * 5;
357
+ score += deleteOps.length * 10; // Deletes are more dangerous
358
+
359
+ // Database mutations - important but common
360
+ const dbClaims = claims.filter(c =>
361
+ c.type === "db_write" || c.type === "db_delete" || c.type === "db_mutation"
362
+ );
363
+ // Only penalize destructive DB operations heavily
364
+ const dbDeletes = dbClaims.filter(c => c.type === "db_delete");
365
+ const dbWrites = dbClaims.filter(c => c.type !== "db_delete");
366
+ score += dbWrites.length * 3;
367
+ score += dbDeletes.length * 12;
368
+
369
+ // External service calls - reduced from 18 to 8
370
+ // Calling external APIs is normal
371
+ const externalClaims = claims.filter(c =>
372
+ c.type === "external_service" || c.type === "webhook"
373
+ );
374
+ score += Math.min(externalClaims.length * 8, 20); // Cap at 20
375
+
376
+ return score;
377
+ },
378
+ },
379
+ };
380
+
381
+ /**
382
+ * Risk level thresholds
383
+ */
384
+ const RISK_LEVELS = {
385
+ LOW: { min: 0, max: 25, label: "LOW", color: "green" },
386
+ MEDIUM: { min: 26, max: 50, label: "MEDIUM", color: "yellow" },
387
+ HIGH: { min: 51, max: 80, label: "HIGH", color: "orange" },
388
+ CRITICAL: { min: 81, max: Infinity, label: "CRITICAL", color: "red" },
389
+ };
390
+
391
+ /**
392
+ * Get risk level from score
393
+ */
394
+ function getRiskLevel(score) {
395
+ if (score <= RISK_LEVELS.LOW.max) return RISK_LEVELS.LOW;
396
+ if (score <= RISK_LEVELS.MEDIUM.max) return RISK_LEVELS.MEDIUM;
397
+ if (score <= RISK_LEVELS.HIGH.max) return RISK_LEVELS.HIGH;
398
+ return RISK_LEVELS.CRITICAL;
399
+ }
400
+
401
+ /**
402
+ * Get all vector IDs
403
+ */
404
+ function getVectorIds() {
405
+ return Object.values(RISK_VECTORS).map(v => v.id);
406
+ }
407
+
408
+ /**
409
+ * Get vector by ID
410
+ */
411
+ function getVector(id) {
412
+ return Object.values(RISK_VECTORS).find(v => v.id === id);
413
+ }
414
+
415
+ module.exports = {
416
+ RISK_VECTORS,
417
+ RISK_LEVELS,
418
+ getRiskLevel,
419
+ getVectorIds,
420
+ getVector,
421
+ };