@safetnsr/vet 1.7.0 → 1.8.2

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 (42) hide show
  1. package/dist/checks/debt.js +17 -4
  2. package/dist/checks/deps.js +146 -135
  3. package/dist/checks/diff.js +23 -4
  4. package/dist/checks/integrity.js +94 -17
  5. package/dist/checks/memory.js +6 -10
  6. package/dist/checks/models.js +60 -13
  7. package/dist/checks/owasp/asi01-goal-hijack.d.ts +5 -0
  8. package/dist/checks/owasp/asi01-goal-hijack.js +49 -0
  9. package/dist/checks/owasp/asi02-tool-misuse.d.ts +5 -0
  10. package/dist/checks/owasp/asi02-tool-misuse.js +98 -0
  11. package/dist/checks/owasp/asi03-identity-abuse.d.ts +5 -0
  12. package/dist/checks/owasp/asi03-identity-abuse.js +80 -0
  13. package/dist/checks/owasp/asi04-supply-chain.d.ts +5 -0
  14. package/dist/checks/owasp/asi04-supply-chain.js +79 -0
  15. package/dist/checks/owasp/asi05-code-execution.d.ts +5 -0
  16. package/dist/checks/owasp/asi05-code-execution.js +67 -0
  17. package/dist/checks/owasp/asi06-memory-poisoning.d.ts +5 -0
  18. package/dist/checks/owasp/asi06-memory-poisoning.js +61 -0
  19. package/dist/checks/owasp/asi07-inter-agent.d.ts +5 -0
  20. package/dist/checks/owasp/asi07-inter-agent.js +62 -0
  21. package/dist/checks/owasp/asi08-cascading.d.ts +5 -0
  22. package/dist/checks/owasp/asi08-cascading.js +36 -0
  23. package/dist/checks/owasp/asi09-trust-exploitation.d.ts +5 -0
  24. package/dist/checks/owasp/asi09-trust-exploitation.js +65 -0
  25. package/dist/checks/owasp/asi10-rogue-agents.d.ts +5 -0
  26. package/dist/checks/owasp/asi10-rogue-agents.js +31 -0
  27. package/dist/checks/owasp/index.d.ts +11 -0
  28. package/dist/checks/owasp/index.js +11 -0
  29. package/dist/checks/owasp/shared.d.ts +11 -0
  30. package/dist/checks/owasp/shared.js +61 -0
  31. package/dist/checks/owasp.js +1 -1
  32. package/dist/checks/ready.js +42 -7
  33. package/dist/checks/receipt.js +2 -16
  34. package/dist/checks/scan.js +54 -6
  35. package/dist/checks/secrets.js +2 -20
  36. package/dist/checks/tests.d.ts +3 -0
  37. package/dist/checks/tests.js +10 -0
  38. package/dist/checks/verify.js +35 -2
  39. package/dist/cli.js +111 -69
  40. package/dist/util.d.ts +0 -1
  41. package/dist/util.js +1 -1
  42. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -106,22 +106,40 @@ if (configContent) {
106
106
  }
107
107
  const ignore = config.ignore || [];
108
108
  if (command === 'init') {
109
- const { init } = await import('./init.js');
110
- await init(cwd);
109
+ try {
110
+ const { init } = await import('./init.js');
111
+ await init(cwd);
112
+ }
113
+ catch (e) {
114
+ console.error(`${c.red}init failed:${c.reset}`, e instanceof Error ? e.message : e);
115
+ process.exit(1);
116
+ }
111
117
  process.exit(0);
112
118
  }
113
119
  if (command === 'receipt') {
114
- const format = isJSON ? 'json' : 'ascii';
115
- await runReceiptCommand(format);
120
+ try {
121
+ const format = isJSON ? 'json' : 'ascii';
122
+ await runReceiptCommand(format);
123
+ }
124
+ catch (e) {
125
+ console.error(`${c.red}receipt failed:${c.reset}`, e instanceof Error ? e.message : e);
126
+ process.exit(1);
127
+ }
116
128
  process.exit(0);
117
129
  }
118
130
  if (command === 'map') {
119
- const result = await checkMap(cwd);
120
- if (isJSON) {
121
- console.log(renderMapReport(result, true));
131
+ try {
132
+ const result = await checkMap(cwd);
133
+ if (isJSON) {
134
+ console.log(renderMapReport(result, true));
135
+ }
136
+ else {
137
+ console.log(renderMapReport(result, false));
138
+ }
122
139
  }
123
- else {
124
- console.log(renderMapReport(result, false));
140
+ catch (e) {
141
+ console.error(`${c.red}map failed:${c.reset}`, e instanceof Error ? e.message : e);
142
+ process.exit(1);
125
143
  }
126
144
  process.exit(0);
127
145
  }
@@ -155,61 +173,79 @@ if (!isGitRepo(cwd)) {
155
173
  }
156
174
  // --fix mode
157
175
  if (isFix) {
158
- console.log(`\n ${c.bold}vet --fix${c.reset}\n`);
159
- const { fixConfig } = await import('./fix/config.js');
160
- const { fixModels } = await import('./fix/models.js');
161
- const configResult = fixConfig(cwd);
162
- const modelsResult = fixModels(cwd, ignore);
163
- const allMessages = [...configResult.messages, ...modelsResult.messages];
164
- const totalFixed = configResult.fixed + modelsResult.fixed;
165
- if (allMessages.length > 0) {
166
- for (const msg of allMessages)
167
- console.log(msg);
176
+ try {
177
+ console.log(`\n ${c.bold}vet --fix${c.reset}\n`);
178
+ const { fixConfig } = await import('./fix/config.js');
179
+ const { fixModels } = await import('./fix/models.js');
180
+ const configResult = fixConfig(cwd);
181
+ const modelsResult = fixModels(cwd, ignore);
182
+ const allMessages = [...configResult.messages, ...modelsResult.messages];
183
+ const totalFixed = configResult.fixed + modelsResult.fixed;
184
+ if (allMessages.length > 0) {
185
+ for (const msg of allMessages)
186
+ console.log(msg);
187
+ }
188
+ console.log(`\n ${totalFixed > 0 ? c.green : c.dim}fixed ${totalFixed} issue${totalFixed !== 1 ? 's' : ''}${c.reset}\n`);
189
+ }
190
+ catch (e) {
191
+ console.error(`${c.red}fix failed:${c.reset}`, e instanceof Error ? e.message : e);
192
+ process.exit(1);
168
193
  }
169
- console.log(`\n ${totalFixed > 0 ? c.green : c.dim}fixed ${totalFixed} issue${totalFixed !== 1 ? 's' : ''}${c.reset}\n`);
170
194
  process.exit(0);
171
195
  }
172
196
  async function runChecks() {
173
- // Run all checks, grouped into categories
174
- // Security: scan, secrets, config, models, owasp, permissions
175
- const [scanResult, secretsResult, configResult, modelsResult, owaspResult] = await Promise.all([
176
- Promise.resolve(checkScan(cwd)),
177
- checkSecrets(cwd),
178
- Promise.resolve(checkConfig(cwd, ignore)),
179
- checkModels(cwd, ignore),
180
- Promise.resolve(checkOwasp(cwd)),
181
- ]);
182
- const permissionsResult = checkPermissions(cwd);
183
- // Integrity: diff, integrity checks
184
- const diffResult = checkDiff(cwd, { since });
185
- const integrityResult = await checkIntegrity(cwd, ignore);
186
- // Debt: ready, history, debt
187
- const [readyResult, debtResult] = await Promise.all([
188
- checkReady(cwd, ignore),
189
- checkDebt(cwd, ignore),
190
- ]);
191
- const historyResult = checkHistory(cwd);
192
- // Deps: deps
193
- const depsResult = await checkDeps(cwd);
194
- // Receipt is informational — fold into integrity category but keep low weight
195
- const receiptResult = await checkReceipt(cwd);
196
- // Memory: stale facts in agent memory files
197
- const memoryResult = checkMemory(cwd);
198
- // Verify: agent claim validation
199
- const verifyResult = checkVerify(cwd, since);
200
- // Tests: test theater detection
201
- const testsResult = checkTests(cwd, ignore);
202
- return score(cwd, {
203
- security: [scanResult, secretsResult, configResult, modelsResult, owaspResult, permissionsResult],
204
- integrity: [diffResult, integrityResult, receiptResult, memoryResult, verifyResult, testsResult],
205
- debt: [readyResult, historyResult, debtResult],
206
- deps: [depsResult],
207
- });
197
+ try {
198
+ // Run all checks, grouped into categories
199
+ // Security: scan, secrets, config, models, owasp, permissions
200
+ const [scanResult, secretsResult, configResult, modelsResult, owaspResult] = await Promise.all([
201
+ Promise.resolve(checkScan(cwd)),
202
+ checkSecrets(cwd),
203
+ Promise.resolve(checkConfig(cwd, ignore)),
204
+ checkModels(cwd, ignore),
205
+ Promise.resolve(checkOwasp(cwd)),
206
+ ]);
207
+ const permissionsResult = checkPermissions(cwd);
208
+ // Integrity: diff, integrity checks
209
+ const diffResult = checkDiff(cwd, { since });
210
+ const integrityResult = await checkIntegrity(cwd, ignore);
211
+ // Debt: ready, history, debt
212
+ const [readyResult, debtResult] = await Promise.all([
213
+ checkReady(cwd, ignore),
214
+ checkDebt(cwd, ignore),
215
+ ]);
216
+ const historyResult = checkHistory(cwd);
217
+ // Deps: deps
218
+ const depsResult = await checkDeps(cwd);
219
+ // Receipt is informational — fold into integrity category but keep low weight
220
+ const receiptResult = await checkReceipt(cwd);
221
+ // Memory: stale facts in agent memory files
222
+ const memoryResult = checkMemory(cwd);
223
+ // Verify: agent claim validation
224
+ const verifyResult = checkVerify(cwd, since);
225
+ // Tests: test theater detection
226
+ const testsResult = checkTests(cwd, ignore);
227
+ return score(cwd, {
228
+ security: [scanResult, secretsResult, configResult, modelsResult, owaspResult, permissionsResult],
229
+ integrity: [diffResult, integrityResult, receiptResult, memoryResult, verifyResult, testsResult],
230
+ debt: [readyResult, historyResult, debtResult],
231
+ deps: [depsResult],
232
+ });
233
+ }
234
+ catch (e) {
235
+ console.error('check failed:', e instanceof Error ? e.message : e);
236
+ process.exit(1);
237
+ }
208
238
  }
209
239
  // --badge mode
210
240
  if (isBadge && !isWatch) {
211
- const result = await runChecks();
212
- console.log(reportBadge(result));
241
+ try {
242
+ const result = await runChecks();
243
+ console.log(reportBadge(result));
244
+ }
245
+ catch (e) {
246
+ console.error(`${c.red}badge failed:${c.reset}`, e instanceof Error ? e.message : e);
247
+ process.exit(1);
248
+ }
213
249
  process.exit(0);
214
250
  }
215
251
  // --watch mode
@@ -247,18 +283,24 @@ if (isWatch) {
247
283
  }
248
284
  else {
249
285
  // Normal run
250
- const result = await runChecks();
251
- if (isJSON) {
252
- console.log(reportJSON(result));
253
- }
254
- else {
255
- console.log(reportPretty(result));
286
+ try {
287
+ const result = await runChecks();
288
+ if (isJSON) {
289
+ console.log(reportJSON(result));
290
+ }
291
+ else {
292
+ console.log(reportPretty(result));
293
+ }
294
+ if (isCI || isHook) {
295
+ // --hook uses grade C (60) as threshold
296
+ // --ci uses config threshold or grade C default
297
+ const minScore = isHook ? 60 : (config.thresholds?.min ?? 60);
298
+ const minGrade = isHook ? 'C' : (config.thresholds?.grade ?? 'C');
299
+ process.exit(result.score >= minScore ? 0 : 1);
300
+ }
256
301
  }
257
- if (isCI || isHook) {
258
- // --hook uses grade C (60) as threshold
259
- // --ci uses config threshold or grade C default
260
- const minScore = isHook ? 60 : (config.thresholds?.min ?? 60);
261
- const minGrade = isHook ? 'C' : (config.thresholds?.grade ?? 'C');
262
- process.exit(result.score >= minScore ? 0 : 1);
302
+ catch (e) {
303
+ console.error(`${c.red}vet failed:${c.reset}`, e instanceof Error ? e.message : e);
304
+ process.exit(1);
263
305
  }
264
306
  }
package/dist/util.d.ts CHANGED
@@ -22,4 +22,3 @@ export declare function walkFiles(dir: string, ignore?: string[]): string[];
22
22
  export declare function isTextFile(filePath: string): boolean;
23
23
  /** Recursively collect all file paths under a directory */
24
24
  export declare function collectDirFiles(dir: string): string[];
25
- export declare function matchesAny(file: string, patterns: string[]): boolean;
package/dist/util.js CHANGED
@@ -103,7 +103,7 @@ export function collectDirFiles(dir) {
103
103
  catch { /* skip */ }
104
104
  return files;
105
105
  }
106
- export function matchesAny(file, patterns) {
106
+ function matchesAny(file, patterns) {
107
107
  return patterns.some(p => {
108
108
  if (p.endsWith('/'))
109
109
  return file.startsWith(p) || file.includes('/' + p);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@safetnsr/vet",
3
- "version": "1.7.0",
3
+ "version": "1.8.2",
4
4
  "description": "vet your AI-generated code — one command, one score card, one letter grade",
5
5
  "type": "module",
6
6
  "bin": {