vaspera 2.14.0 → 2.15.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 (257) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +15 -2
  3. package/dist/__tests__/certification/agent-certificate-e2e.test.d.ts +2 -0
  4. package/dist/__tests__/certification/agent-certificate-e2e.test.d.ts.map +1 -0
  5. package/dist/__tests__/certification/agent-certificate-e2e.test.js +90 -0
  6. package/dist/__tests__/certification/agent-certificate-e2e.test.js.map +1 -0
  7. package/dist/__tests__/certification/agent-certificate-map.test.d.ts +2 -0
  8. package/dist/__tests__/certification/agent-certificate-map.test.d.ts.map +1 -0
  9. package/dist/__tests__/certification/agent-certificate-map.test.js +107 -0
  10. package/dist/__tests__/certification/agent-certificate-map.test.js.map +1 -0
  11. package/dist/__tests__/certification/agent-certificate.test.d.ts +2 -0
  12. package/dist/__tests__/certification/agent-certificate.test.d.ts.map +1 -0
  13. package/dist/__tests__/certification/agent-certificate.test.js +78 -0
  14. package/dist/__tests__/certification/agent-certificate.test.js.map +1 -0
  15. package/dist/__tests__/certification/verify-endpoint.test.d.ts +2 -0
  16. package/dist/__tests__/certification/verify-endpoint.test.d.ts.map +1 -0
  17. package/dist/__tests__/certification/verify-endpoint.test.js +81 -0
  18. package/dist/__tests__/certification/verify-endpoint.test.js.map +1 -0
  19. package/dist/__tests__/compliance/ai-frameworks.test.d.ts +2 -0
  20. package/dist/__tests__/compliance/ai-frameworks.test.d.ts.map +1 -0
  21. package/dist/__tests__/compliance/ai-frameworks.test.js +87 -0
  22. package/dist/__tests__/compliance/ai-frameworks.test.js.map +1 -0
  23. package/dist/__tests__/eval/llm-analyzer.test.d.ts +2 -0
  24. package/dist/__tests__/eval/llm-analyzer.test.d.ts.map +1 -0
  25. package/dist/__tests__/eval/llm-analyzer.test.js +93 -0
  26. package/dist/__tests__/eval/llm-analyzer.test.js.map +1 -0
  27. package/dist/__tests__/eval/redteam-harness.test.d.ts +2 -0
  28. package/dist/__tests__/eval/redteam-harness.test.d.ts.map +1 -0
  29. package/dist/__tests__/eval/redteam-harness.test.js +136 -0
  30. package/dist/__tests__/eval/redteam-harness.test.js.map +1 -0
  31. package/dist/__tests__/evidence/evidence.test.d.ts +2 -0
  32. package/dist/__tests__/evidence/evidence.test.d.ts.map +1 -0
  33. package/dist/__tests__/evidence/evidence.test.js +240 -0
  34. package/dist/__tests__/evidence/evidence.test.js.map +1 -0
  35. package/dist/__tests__/history/decisions.test.d.ts +2 -0
  36. package/dist/__tests__/history/decisions.test.d.ts.map +1 -0
  37. package/dist/__tests__/history/decisions.test.js +54 -0
  38. package/dist/__tests__/history/decisions.test.js.map +1 -0
  39. package/dist/__tests__/http-auth.test.d.ts +2 -0
  40. package/dist/__tests__/http-auth.test.d.ts.map +1 -0
  41. package/dist/__tests__/http-auth.test.js +55 -0
  42. package/dist/__tests__/http-auth.test.js.map +1 -0
  43. package/dist/__tests__/http-policy.test.d.ts +2 -0
  44. package/dist/__tests__/http-policy.test.d.ts.map +1 -0
  45. package/dist/__tests__/http-policy.test.js +69 -0
  46. package/dist/__tests__/http-policy.test.js.map +1 -0
  47. package/dist/__tests__/http-server-transport.test.d.ts +2 -0
  48. package/dist/__tests__/http-server-transport.test.d.ts.map +1 -0
  49. package/dist/__tests__/http-server-transport.test.js +132 -0
  50. package/dist/__tests__/http-server-transport.test.js.map +1 -0
  51. package/dist/__tests__/integration/destructive-guards.test.d.ts +2 -0
  52. package/dist/__tests__/integration/destructive-guards.test.d.ts.map +1 -0
  53. package/dist/__tests__/integration/destructive-guards.test.js +49 -0
  54. package/dist/__tests__/integration/destructive-guards.test.js.map +1 -0
  55. package/dist/__tests__/logger-redaction.test.d.ts +2 -0
  56. package/dist/__tests__/logger-redaction.test.d.ts.map +1 -0
  57. package/dist/__tests__/logger-redaction.test.js +74 -0
  58. package/dist/__tests__/logger-redaction.test.js.map +1 -0
  59. package/dist/__tests__/manifest-schema.test.d.ts +2 -0
  60. package/dist/__tests__/manifest-schema.test.d.ts.map +1 -0
  61. package/dist/__tests__/manifest-schema.test.js +43 -0
  62. package/dist/__tests__/manifest-schema.test.js.map +1 -0
  63. package/dist/__tests__/scanners/builtin-rules.test.d.ts +2 -0
  64. package/dist/__tests__/scanners/builtin-rules.test.d.ts.map +1 -0
  65. package/dist/__tests__/scanners/builtin-rules.test.js +51 -0
  66. package/dist/__tests__/scanners/builtin-rules.test.js.map +1 -0
  67. package/dist/__tests__/scanners/runtime/golden-path-runner.test.js +13 -1
  68. package/dist/__tests__/scanners/runtime/golden-path-runner.test.js.map +1 -1
  69. package/dist/__tests__/tool-guard.test.d.ts +2 -0
  70. package/dist/__tests__/tool-guard.test.d.ts.map +1 -0
  71. package/dist/__tests__/tool-guard.test.js +97 -0
  72. package/dist/__tests__/tool-guard.test.js.map +1 -0
  73. package/dist/__tests__/util/contained-file.test.d.ts +2 -0
  74. package/dist/__tests__/util/contained-file.test.d.ts.map +1 -0
  75. package/dist/__tests__/util/contained-file.test.js +78 -0
  76. package/dist/__tests__/util/contained-file.test.js.map +1 -0
  77. package/dist/__tests__/util/subprocess.test.d.ts +2 -0
  78. package/dist/__tests__/util/subprocess.test.d.ts.map +1 -0
  79. package/dist/__tests__/util/subprocess.test.js +48 -0
  80. package/dist/__tests__/util/subprocess.test.js.map +1 -0
  81. package/dist/action/diff-mode.d.ts.map +1 -1
  82. package/dist/action/diff-mode.js +31 -12
  83. package/dist/action/diff-mode.js.map +1 -1
  84. package/dist/certification/agent-certificate-map.d.ts +51 -0
  85. package/dist/certification/agent-certificate-map.d.ts.map +1 -0
  86. package/dist/certification/agent-certificate-map.js +265 -0
  87. package/dist/certification/agent-certificate-map.js.map +1 -0
  88. package/dist/certification/agent-certificate-sample.d.ts +25 -0
  89. package/dist/certification/agent-certificate-sample.d.ts.map +1 -0
  90. package/dist/certification/agent-certificate-sample.js +207 -0
  91. package/dist/certification/agent-certificate-sample.js.map +1 -0
  92. package/dist/certification/agent-certificate.d.ts +1981 -0
  93. package/dist/certification/agent-certificate.d.ts.map +1 -0
  94. package/dist/certification/agent-certificate.js +309 -0
  95. package/dist/certification/agent-certificate.js.map +1 -0
  96. package/dist/certification/autofix.d.ts.map +1 -1
  97. package/dist/certification/autofix.js +5 -3
  98. package/dist/certification/autofix.js.map +1 -1
  99. package/dist/certification/store.d.ts.map +1 -1
  100. package/dist/certification/store.js +5 -2
  101. package/dist/certification/store.js.map +1 -1
  102. package/dist/certification/verify-endpoint.d.ts +48 -0
  103. package/dist/certification/verify-endpoint.d.ts.map +1 -0
  104. package/dist/certification/verify-endpoint.js +79 -0
  105. package/dist/certification/verify-endpoint.js.map +1 -0
  106. package/dist/compliance/index.d.ts +2 -0
  107. package/dist/compliance/index.d.ts.map +1 -1
  108. package/dist/compliance/index.js +4 -0
  109. package/dist/compliance/index.js.map +1 -1
  110. package/dist/compliance/iso42001.d.ts +21 -0
  111. package/dist/compliance/iso42001.d.ts.map +1 -0
  112. package/dist/compliance/iso42001.js +160 -0
  113. package/dist/compliance/iso42001.js.map +1 -0
  114. package/dist/compliance/mapper.d.ts.map +1 -1
  115. package/dist/compliance/mapper.js +12 -0
  116. package/dist/compliance/mapper.js.map +1 -1
  117. package/dist/compliance/nist-ai-rmf.d.ts +20 -0
  118. package/dist/compliance/nist-ai-rmf.d.ts.map +1 -0
  119. package/dist/compliance/nist-ai-rmf.js +140 -0
  120. package/dist/compliance/nist-ai-rmf.js.map +1 -0
  121. package/dist/config/flags.d.ts +4 -4
  122. package/dist/eval/fixtures.d.ts.map +1 -1
  123. package/dist/eval/fixtures.js +161 -119
  124. package/dist/eval/fixtures.js.map +1 -1
  125. package/dist/eval/fixtures.test.js +4 -2
  126. package/dist/eval/fixtures.test.js.map +1 -1
  127. package/dist/eval/llm-analyzer.d.ts +40 -0
  128. package/dist/eval/llm-analyzer.d.ts.map +1 -0
  129. package/dist/eval/llm-analyzer.js +154 -0
  130. package/dist/eval/llm-analyzer.js.map +1 -0
  131. package/dist/eval/redteam-harness.d.ts +95 -0
  132. package/dist/eval/redteam-harness.d.ts.map +1 -0
  133. package/dist/eval/redteam-harness.js +137 -0
  134. package/dist/eval/redteam-harness.js.map +1 -0
  135. package/dist/evidence/collector.d.ts.map +1 -1
  136. package/dist/evidence/collector.js +21 -1
  137. package/dist/evidence/collector.js.map +1 -1
  138. package/dist/evidence/store.d.ts.map +1 -1
  139. package/dist/evidence/store.js +29 -5
  140. package/dist/evidence/store.js.map +1 -1
  141. package/dist/evidence/types.d.ts +16 -9
  142. package/dist/evidence/types.d.ts.map +1 -1
  143. package/dist/history/decisions.d.ts +63 -0
  144. package/dist/history/decisions.d.ts.map +1 -0
  145. package/dist/history/decisions.js +60 -0
  146. package/dist/history/decisions.js.map +1 -0
  147. package/dist/history/index.d.ts +2 -0
  148. package/dist/history/index.d.ts.map +1 -1
  149. package/dist/history/index.js +2 -0
  150. package/dist/history/index.js.map +1 -1
  151. package/dist/history/types.d.ts +34 -5
  152. package/dist/history/types.d.ts.map +1 -1
  153. package/dist/history/types.js +2 -0
  154. package/dist/history/types.js.map +1 -1
  155. package/dist/http-auth.d.ts +22 -0
  156. package/dist/http-auth.d.ts.map +1 -0
  157. package/dist/http-auth.js +58 -0
  158. package/dist/http-auth.js.map +1 -0
  159. package/dist/http-policy.d.ts +30 -0
  160. package/dist/http-policy.d.ts.map +1 -0
  161. package/dist/http-policy.js +54 -0
  162. package/dist/http-policy.js.map +1 -0
  163. package/dist/http-server.js +195 -12
  164. package/dist/http-server.js.map +1 -1
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +247 -15
  167. package/dist/index.js.map +1 -1
  168. package/dist/logger.d.ts.map +1 -1
  169. package/dist/logger.js +56 -2
  170. package/dist/logger.js.map +1 -1
  171. package/dist/plugins/types.d.ts +2 -2
  172. package/dist/scanners/agent/prompt-injection-fuzzer.d.ts.map +1 -1
  173. package/dist/scanners/agent/prompt-injection-fuzzer.js +26 -0
  174. package/dist/scanners/agent/prompt-injection-fuzzer.js.map +1 -1
  175. package/dist/scanners/agent/types.d.ts +10 -10
  176. package/dist/scanners/bandit.d.ts.map +1 -1
  177. package/dist/scanners/bandit.js +35 -29
  178. package/dist/scanners/bandit.js.map +1 -1
  179. package/dist/scanners/binary-analysis.d.ts.map +1 -1
  180. package/dist/scanners/binary-analysis.js +24 -49
  181. package/dist/scanners/binary-analysis.js.map +1 -1
  182. package/dist/scanners/brakeman.d.ts.map +1 -1
  183. package/dist/scanners/brakeman.js +19 -33
  184. package/dist/scanners/brakeman.js.map +1 -1
  185. package/dist/scanners/builtin-rules.d.ts +24 -0
  186. package/dist/scanners/builtin-rules.d.ts.map +1 -0
  187. package/dist/scanners/builtin-rules.js +175 -0
  188. package/dist/scanners/builtin-rules.js.map +1 -0
  189. package/dist/scanners/dast.d.ts.map +1 -1
  190. package/dist/scanners/dast.js +24 -34
  191. package/dist/scanners/dast.js.map +1 -1
  192. package/dist/scanners/deploy/types.d.ts +6 -6
  193. package/dist/scanners/eslint.d.ts.map +1 -1
  194. package/dist/scanners/eslint.js +15 -24
  195. package/dist/scanners/eslint.js.map +1 -1
  196. package/dist/scanners/gosec.d.ts.map +1 -1
  197. package/dist/scanners/gosec.js +14 -62
  198. package/dist/scanners/gosec.js.map +1 -1
  199. package/dist/scanners/index.d.ts.map +1 -1
  200. package/dist/scanners/index.js +38 -7
  201. package/dist/scanners/index.js.map +1 -1
  202. package/dist/scanners/memory-safety.d.ts.map +1 -1
  203. package/dist/scanners/memory-safety.js +27 -28
  204. package/dist/scanners/memory-safety.js.map +1 -1
  205. package/dist/scanners/openapi.d.ts.map +1 -1
  206. package/dist/scanners/openapi.js +14 -22
  207. package/dist/scanners/openapi.js.map +1 -1
  208. package/dist/scanners/race-condition.d.ts.map +1 -1
  209. package/dist/scanners/race-condition.js +17 -16
  210. package/dist/scanners/race-condition.js.map +1 -1
  211. package/dist/scanners/runtime/types.d.ts +4 -4
  212. package/dist/scanners/rust.d.ts.map +1 -1
  213. package/dist/scanners/rust.js +38 -37
  214. package/dist/scanners/rust.js.map +1 -1
  215. package/dist/scanners/scale/types.d.ts +16 -16
  216. package/dist/scanners/secrets.d.ts.map +1 -1
  217. package/dist/scanners/secrets.js +66 -78
  218. package/dist/scanners/secrets.js.map +1 -1
  219. package/dist/scanners/semgrep.d.ts +2 -0
  220. package/dist/scanners/semgrep.d.ts.map +1 -1
  221. package/dist/scanners/semgrep.js +12 -0
  222. package/dist/scanners/semgrep.js.map +1 -1
  223. package/dist/scanners/terraform.d.ts.map +1 -1
  224. package/dist/scanners/terraform.js +47 -40
  225. package/dist/scanners/terraform.js.map +1 -1
  226. package/dist/scanners/trivy.d.ts.map +1 -1
  227. package/dist/scanners/trivy.js +38 -30
  228. package/dist/scanners/trivy.js.map +1 -1
  229. package/dist/tool-guard.d.ts +40 -0
  230. package/dist/tool-guard.d.ts.map +1 -0
  231. package/dist/tool-guard.js +55 -0
  232. package/dist/tool-guard.js.map +1 -0
  233. package/dist/util/index.d.ts +2 -1
  234. package/dist/util/index.d.ts.map +1 -1
  235. package/dist/util/index.js +2 -1
  236. package/dist/util/index.js.map +1 -1
  237. package/dist/util/paths.d.ts +20 -3
  238. package/dist/util/paths.d.ts.map +1 -1
  239. package/dist/util/paths.js +84 -4
  240. package/dist/util/paths.js.map +1 -1
  241. package/dist/util/subprocess.d.ts +51 -0
  242. package/dist/util/subprocess.d.ts.map +1 -0
  243. package/dist/util/subprocess.js +77 -0
  244. package/dist/util/subprocess.js.map +1 -0
  245. package/package.json +12 -2
  246. package/dist/eval/fixtures/healthcare/audit-gaps.d.ts +0 -28
  247. package/dist/eval/fixtures/healthcare/audit-gaps.d.ts.map +0 -1
  248. package/dist/eval/fixtures/healthcare/audit-gaps.js +0 -90
  249. package/dist/eval/fixtures/healthcare/audit-gaps.js.map +0 -1
  250. package/dist/eval/fixtures/healthcare/consent-bypass.d.ts +0 -31
  251. package/dist/eval/fixtures/healthcare/consent-bypass.d.ts.map +0 -1
  252. package/dist/eval/fixtures/healthcare/consent-bypass.js +0 -61
  253. package/dist/eval/fixtures/healthcare/consent-bypass.js.map +0 -1
  254. package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts +0 -24
  255. package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts.map +0 -1
  256. package/dist/eval/fixtures/healthcare/phi-in-logs.js +0 -41
  257. package/dist/eval/fixtures/healthcare/phi-in-logs.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,10 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#61](https://github.com/RCOLKITT/hardening-mcp/pull/61) [`1ecf11d`](https://github.com/RCOLKITT/hardening-mcp/commit/1ecf11dbc073af3430e6df17d0792e2b87ad2568) Thanks [@RCOLKITT](https://github.com/RCOLKITT)! - Agent Certification, independent verification, accuracy + red-team benchmarks, and hardening.
8
+
9
+ **Agent Certification**
10
+
11
+ - Versioned, signable agent certificate schema (six dimensions) with deterministic content digest; `agent_certificate_generate` / `agent_certificate_verify` MCP tools.
12
+ - ISO 42001 + NIST AI RMF compliance mappings and tamper-evident decision provenance (`decision_record`) on the hash chain.
13
+ - EU AI Act control mapping wired into the certification path (31 controls).
14
+
15
+ **Independent verification (don't trust us — verify)**
16
+
17
+ - Standalone certificate verifier: `npm run verify:cert` CLI and a public, unauthenticated `POST /verify` HTTP endpoint that re-checks schema, content digest, and signature without trusting the issuer.
18
+
19
+ **Measured accuracy + red-team**
20
+
21
+ - Accuracy benchmark (`npm run benchmark`, `npm run benchmark:llm`) over labeled fixtures with precision/recall/F1; built-in Semgrep taint rules took deterministic recall from ~10% to ~63% (added SQLi/cmd/SSRF, then insecure-deserialization + XXE), precision 100%.
22
+ - LLM-layer + Anthropic/OpenAI cross-model consensus benchmark.
23
+ - Red-team resistance harness (`npm run benchmark:redteam`) — reproducible prompt-injection resistance score + tool-scope/exfil exposure; fixed a false-positive bug that flagged 100% of tools.
24
+
25
+ **Integrity + supply chain**
26
+
27
+ - Evidence bundles can now be Sigstore-signed and their signatures are really verified (was a presence-only stub).
28
+ - Published manifest now exposes real per-tool input schemas (was an empty placeholder for all tools).
29
+ - Resolved a transitive esbuild advisory.
30
+
31
+ **Hardening (potentially breaking for three tools)**
32
+
33
+ - `deploy_vercel_promote`, `deploy_vercel_rollback`, and `consensus_clear` are now fail-closed: they return a no-op preview unless called with `confirm: true`. Callers that previously relied on these executing immediately must now pass `confirm: true`.
34
+
3
35
  ## [2.14.0] - 2026-06-05
4
36
 
5
37
  ### Added
6
38
 
7
39
  #### Antagonist Agent
40
+
8
41
  - New meta-analysis agent that runs after all other agents complete
9
42
  - **Synthesis mode**: Chains findings into attack narratives mapped to MITRE ATT&CK kill chain
10
43
  - **Challenger mode**: Internal critic that flags false positives, coverage gaps, and inconsistencies
@@ -13,22 +46,26 @@
13
46
  - New `antagonist_challenge` tool - manually challenge specific findings
14
47
 
15
48
  #### Attack Narrative Features
49
+
16
50
  - Builds attack graphs from findings and exploit chains
17
51
  - Maps vulnerabilities to 14 MITRE ATT&CK kill chain phases
18
52
  - Identifies bottleneck findings that block multiple attack paths
19
53
  - Generates human-readable attack stories with difficulty/likelihood ratings
20
54
 
21
55
  #### Challenger Features
56
+
22
57
  - Detects potential false positives (test files, low confidence, generic descriptions)
23
58
  - Identifies untested attack vectors (17 categories tracked)
24
59
  - Flags agents with zero findings as potentially incomplete
25
60
  - Calculates coverage score across attack surface
26
61
 
27
62
  ### Fixed
63
+
28
64
  - Empty catch blocks in `store.ts` and `signing.ts` now log errors
29
65
  - Antagonist agent integration test types corrected
30
66
 
31
67
  ### Changed
68
+
32
69
  - MCP tools increased from 108 to 110
33
70
  - New agent type `antagonist` with weight 0.15 (informs but doesn't dominate consensus)
34
71
  - Added to AGENT_VERIFICATION_MAP (verified by security, adversary, redteam)
@@ -38,17 +75,20 @@
38
75
  ### Added
39
76
 
40
77
  #### False Positive Feedback System
78
+
41
79
  - New `feedback_submit` tool to mark findings as true/false positives
42
80
  - New `feedback_report` tool to view FP rates by scanner and rule
43
81
  - New `feedback_suppressions` tool to get rule suppression suggestions based on feedback
44
82
  - Feedback stored in `.vaspera/fp-feedback.json` with full audit trail
45
83
 
46
84
  #### Diff-Aware CI Scanning
85
+
47
86
  - New `certification_scan_diff` tool scans only changed files (git diff)
48
87
  - Estimates scan time savings vs full scan
49
88
  - Auto-detects security-critical files that always get scanned
50
89
 
51
90
  #### Standalone Autofix Preview
91
+
52
92
  - `autofix_preview` now works without certification_id
53
93
  - Provide file + pattern_id to preview fixes directly
54
94
  - Use `autofix_list_patterns` to see available fix patterns
@@ -56,27 +96,32 @@
56
96
  ### Fixed
57
97
 
58
98
  #### Persistence DB Fallback
99
+
59
100
  - Added JSON file fallback when SQLite is unavailable
60
101
  - New `src/persistence/json-fallback.ts` with atomic writes
61
102
  - Graceful degradation: warns but continues operating
62
103
 
63
104
  #### scale_bottlenecks False Positives
105
+
64
106
  - Added semantic analysis for workflow/pipeline patterns
65
107
  - Confidence scoring (60-100) based on context
66
108
  - Sequential workflows no longer flagged as N+1 queries
67
109
 
68
110
  #### ai_code_verify Diagnostics
111
+
69
112
  - Returns detailed diagnostics when 0 files found
70
113
  - Shows which extensions were searched
71
114
  - Reports which exclude patterns matched
72
115
  - Suggests alternative file extensions
73
116
 
74
117
  #### Scanner Error Messages
118
+
75
119
  - Added `ScannerErrorDetails` with actionable suggestions
76
120
  - tsc/eslint now report phase (init/scan/parse) and fix steps
77
121
  - Full error output available for debugging
78
122
 
79
123
  ### Changed
124
+
80
125
  - MCP tools increased from 103 to 108
81
126
 
82
127
  ## 2.10.0
package/README.md CHANGED
@@ -2,12 +2,25 @@
2
2
 
3
3
  Enterprise-grade security certification for codebases **and AI agent systems** with deterministic scanners, LLM-powered analysis, and signed attestations.
4
4
 
5
+ [![Self-Certification](https://github.com/RCOLKITT/hardening-mcp/actions/workflows/certify.yml/badge.svg)](https://github.com/RCOLKITT/hardening-mcp/actions/workflows/certify.yml)
6
+ [![CI](https://github.com/RCOLKITT/hardening-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/RCOLKITT/hardening-mcp/actions/workflows/ci.yml)
5
7
  ![npm version](https://img.shields.io/npm/v/vaspera)
6
8
  ![License](https://img.shields.io/badge/License-MIT-green)
7
- ![Tools](https://img.shields.io/badge/MCP_Tools-78-purple)
9
+ ![Tools](https://img.shields.io/badge/MCP_Tools-113-purple)
8
10
  ![AI Frameworks](https://img.shields.io/badge/AI_Frameworks-5-blue)
9
11
  ![Scanners](https://img.shields.io/badge/Scanners-12-orange)
10
- ![Tests](https://img.shields.io/badge/Tests-2942-brightgreen)
12
+ ![Tests](https://img.shields.io/badge/Tests-1891-brightgreen)
13
+
14
+ > **We pass our own strictest certification on every commit.** The
15
+ > Self-Certification badge above is the live result of running this
16
+ > product against its own codebase as a blocking CI gate — the one claim
17
+ > a scanner-wrapper can't fake. [How it works »](docs/SELF-CERTIFICATION.md)
18
+ >
19
+ > **Don't trust us — verify.** Any agent certificate can be checked
20
+ > independently (`npm run verify:cert -- cert.json`, or `POST /verify`)
21
+ > with no token and no trust in Vaspera: it recomputes the content digest
22
+ > and checks the signature from the certificate itself.
23
+ > [Verifying a certificate »](docs/VERIFYING-A-CERTIFICATE.md)
11
24
 
12
25
  ---
13
26
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-certificate-e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-certificate-e2e.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/certification/agent-certificate-e2e.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,90 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtemp, rm } from "fs/promises";
3
+ import { tmpdir } from "os";
4
+ import { join } from "path";
5
+ import { recordDecision, getDecisionProvenance } from "../../history/decisions.js";
6
+ import { certificationToCertificateBody } from "../../certification/agent-certificate-map.js";
7
+ import { finalizeCertificate, verifyCertificate } from "../../certification/agent-certificate.js";
8
+ function certification() {
9
+ return {
10
+ metadata: {
11
+ id: "cert_e2e",
12
+ project_name: "e2e-agent",
13
+ project_path: "/tmp/e2e-agent",
14
+ started_at: "2026-06-12T00:00:00.000Z",
15
+ completed_at: "2026-06-12T00:05:00.000Z",
16
+ status: "completed",
17
+ agents_requested: ["security"],
18
+ agents_completed: ["security"],
19
+ certification_level: "APPROVED",
20
+ final_score: 84,
21
+ project_hash: "deadbeef",
22
+ },
23
+ agents: {
24
+ security: {
25
+ agent: "security",
26
+ started_at: "2026-06-12T00:00:00.000Z",
27
+ completed_at: "2026-06-12T00:03:00.000Z",
28
+ status: "completed",
29
+ findings: [
30
+ {
31
+ id: "f1",
32
+ severity: "high",
33
+ category: "exfil-path",
34
+ description: "Secret can reach the network",
35
+ evidence: "…",
36
+ confidence: 95,
37
+ verifications: [],
38
+ created_at: "2026-06-12T00:01:00.000Z",
39
+ },
40
+ ],
41
+ },
42
+ },
43
+ cross_verifications: [],
44
+ red_team_challenges: [],
45
+ };
46
+ }
47
+ describe("agent certificate — full flow (decisions + frameworks + provenance)", () => {
48
+ let dir;
49
+ beforeEach(async () => {
50
+ dir = await mkdtemp(join(tmpdir(), "cert-e2e-"));
51
+ });
52
+ afterEach(async () => {
53
+ await rm(dir, { recursive: true, force: true });
54
+ });
55
+ it("records decisions, builds a certificate with real frameworks + provenance, verifies", async () => {
56
+ // 1) capture decision provenance on the hash chain
57
+ await recordDecision(dir, { decisionType: "tool_call", model: "m", input: "x", output: "y" });
58
+ await recordDecision(dir, { decisionType: "gen", model: "m", input: "p", output: "q" });
59
+ const provenance = await getDecisionProvenance(dir);
60
+ expect(provenance.decisionRecords).toBe(2);
61
+ // 2) build a certificate from a real certification + AI frameworks + provenance
62
+ const body = certificationToCertificateBody(certification(), {
63
+ toolVersion: "2.14.0",
64
+ issuedAt: "2026-06-12T00:00:00.000Z",
65
+ expiresAt: "2026-09-10T00:00:00.000Z",
66
+ certificateId: "vac_e2e_1",
67
+ complianceFrameworks: ["ISO-42001", "NIST-AI-RMF"],
68
+ provenance,
69
+ });
70
+ // compliance dimension is real (mapped controls, not a label)
71
+ expect(body.dimensions.compliance.frameworks.map((f) => f.framework)).toEqual([
72
+ "ISO-42001",
73
+ "NIST-AI-RMF",
74
+ ]);
75
+ expect(body.dimensions.compliance.frameworks[0].controlsTotal).toBeGreaterThan(0);
76
+ // the exfil-path finding should fail at least one control
77
+ const totalFailed = body.dimensions.compliance.frameworks.reduce((n, f) => n + f.controlsFailed, 0);
78
+ expect(totalFailed).toBeGreaterThan(0);
79
+ // explainability reflects the recorded decisions
80
+ expect(body.dimensions.explainability.checks.some((c) => c.id === "decision-provenance")).toBe(true);
81
+ expect(body.provenance.decisionRecords).toBe(2);
82
+ expect(body.provenance.auditTrailHead).toBe(provenance.auditTrailHead);
83
+ // 3) finalize + verify independently
84
+ const cert = await finalizeCertificate(body);
85
+ const result = await verifyCertificate(cert);
86
+ expect(result.valid).toBe(true);
87
+ expect(result.contentDigestValid).toBe(true);
88
+ });
89
+ });
90
+ //# sourceMappingURL=agent-certificate-e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-certificate-e2e.test.js","sourceRoot":"","sources":["../../../src/__tests__/certification/agent-certificate-e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-certificate-map.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-certificate-map.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/certification/agent-certificate-map.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { certificationToCertificateBody, baselineCertificateBody, } from "../../certification/agent-certificate-map.js";
3
+ import { finalizeCertificate, verifyCertificate, } from "../../certification/agent-certificate.js";
4
+ const opts = {
5
+ toolVersion: "2.14.0",
6
+ issuedAt: "2026-06-11T00:00:00.000Z",
7
+ expiresAt: "2026-09-09T00:00:00.000Z",
8
+ certificateId: "vac_map_0001",
9
+ };
10
+ function fakeCertification() {
11
+ return {
12
+ metadata: {
13
+ id: "cert_1",
14
+ project_name: "demo-agent",
15
+ project_path: "/tmp/demo-agent",
16
+ started_at: "2026-06-11T00:00:00.000Z",
17
+ completed_at: "2026-06-11T00:05:00.000Z",
18
+ status: "completed",
19
+ agents_requested: ["security", "quality"],
20
+ agents_completed: ["security", "quality"],
21
+ certification_level: "APPROVED",
22
+ final_score: 82,
23
+ project_hash: "abc123def456",
24
+ },
25
+ agents: {
26
+ security: {
27
+ agent: "security",
28
+ started_at: "2026-06-11T00:00:00.000Z",
29
+ completed_at: "2026-06-11T00:03:00.000Z",
30
+ status: "completed",
31
+ findings: [
32
+ {
33
+ id: "f1",
34
+ severity: "high",
35
+ category: "prompt-injection",
36
+ file: "src/agent.ts",
37
+ line: 42,
38
+ description: "Untrusted input flows into the system prompt",
39
+ evidence: "…",
40
+ confidence: 90,
41
+ verifications: [],
42
+ created_at: "2026-06-11T00:01:00.000Z",
43
+ },
44
+ {
45
+ id: "f2",
46
+ severity: "low",
47
+ category: "logging-failure",
48
+ description: "Missing structured logging",
49
+ evidence: "…",
50
+ confidence: 70,
51
+ verifications: [],
52
+ created_at: "2026-06-11T00:02:00.000Z",
53
+ },
54
+ ],
55
+ },
56
+ quality: {
57
+ agent: "quality",
58
+ started_at: "2026-06-11T00:00:00.000Z",
59
+ completed_at: "2026-06-11T00:04:00.000Z",
60
+ status: "completed",
61
+ findings: [],
62
+ },
63
+ },
64
+ cross_verifications: [],
65
+ red_team_challenges: [],
66
+ };
67
+ }
68
+ describe("certificationToCertificateBody", () => {
69
+ it("maps a real certification into a verifiable certificate", async () => {
70
+ const body = certificationToCertificateBody(fakeCertification(), opts);
71
+ expect(body.subject.name).toBe("demo-agent");
72
+ expect(body.subject.digest).toBe("abc123def456");
73
+ expect(body.level).toBe("APPROVED");
74
+ expect(body.overallScore).toBe(82);
75
+ // security has a high finding -> fail status, surfaced as a check
76
+ expect(body.dimensions.security.status).toBe("fail");
77
+ expect(body.dimensions.security.checks.some((c) => c.category === "prompt-injection")).toBe(true);
78
+ // quality had no findings -> pass
79
+ expect(body.dimensions.quality.status).toBe("pass");
80
+ // compliance not run -> not_assessed (never fabricated)
81
+ expect(body.dimensions.compliance.status).toBe("not_assessed");
82
+ const cert = await finalizeCertificate(body);
83
+ const result = await verifyCertificate(cert);
84
+ expect(result.valid).toBe(true);
85
+ });
86
+ it("surfaces the most severe findings first and caps the list", () => {
87
+ const c = fakeCertification();
88
+ const body = certificationToCertificateBody(c, opts);
89
+ expect(body.dimensions.security.checks[0].severity).toBe("high");
90
+ });
91
+ it("baseline body is honest — all dimensions not_assessed and verifiable", async () => {
92
+ const body = baselineCertificateBody({
93
+ ...opts,
94
+ subjectName: "fresh-agent",
95
+ subjectKind: "agent",
96
+ identifier: "/tmp/fresh-agent",
97
+ });
98
+ expect(body.overallScore).toBe(0);
99
+ expect(body.level).toBe("REVIEW_REQUIRED");
100
+ for (const dim of Object.values(body.dimensions)) {
101
+ expect(dim.status).toBe("not_assessed");
102
+ }
103
+ const cert = await finalizeCertificate(body);
104
+ expect((await verifyCertificate(cert)).valid).toBe(true);
105
+ });
106
+ });
107
+ //# sourceMappingURL=agent-certificate-map.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-certificate-map.test.js","sourceRoot":"","sources":["../../../src/__tests__/certification/agent-certificate-map.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-certificate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-certificate.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/certification/agent-certificate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,78 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { finalizeCertificate, verifyCertificate, canonicalize, computeContentDigest, parseCertificate, CertificateError, AgentCertificateSchema, AGENT_CERTIFICATE_SCHEMA, } from "../../certification/agent-certificate.js";
3
+ import { buildSampleCertificateBody } from "../../certification/agent-certificate-sample.js";
4
+ const sampleOpts = {
5
+ toolVersion: "2.14.0",
6
+ issuedAt: "2026-06-11T00:00:00.000Z",
7
+ expiresAt: "2026-09-09T00:00:00.000Z",
8
+ certificateId: "vac_test_0001",
9
+ };
10
+ function body() {
11
+ return buildSampleCertificateBody(sampleOpts);
12
+ }
13
+ describe("agent certificate", () => {
14
+ it("finalizes a valid body with a content digest", async () => {
15
+ const cert = await finalizeCertificate(body());
16
+ expect(cert.schemaVersion).toBe(AGENT_CERTIFICATE_SCHEMA);
17
+ expect(cert.integrity.algorithm).toBe("sha256");
18
+ expect(cert.integrity.contentDigest).toMatch(/^[a-f0-9]{64}$/);
19
+ // digest is over the body alone (no signature when unsigned)
20
+ expect(cert.signature).toBeUndefined();
21
+ });
22
+ it("produces a deterministic digest regardless of key order", async () => {
23
+ const a = await finalizeCertificate(body());
24
+ // shuffle top-level key order of the body
25
+ const shuffled = Object.fromEntries(Object.entries(body()).reverse());
26
+ const b = await finalizeCertificate(shuffled);
27
+ expect(a.integrity.contentDigest).toBe(b.integrity.contentDigest);
28
+ });
29
+ it("verifies an untampered certificate", async () => {
30
+ const cert = await finalizeCertificate(body());
31
+ const result = await verifyCertificate(cert);
32
+ expect(result.valid).toBe(true);
33
+ expect(result.schemaValid).toBe(true);
34
+ expect(result.contentDigestValid).toBe(true);
35
+ expect(result.signaturePresent).toBe(false);
36
+ });
37
+ it("detects tampering — any field change breaks the digest", async () => {
38
+ const cert = await finalizeCertificate(body());
39
+ const tampered = { ...cert, overallScore: 100 };
40
+ const result = await verifyCertificate(tampered);
41
+ expect(result.contentDigestValid).toBe(false);
42
+ expect(result.valid).toBe(false);
43
+ expect(result.errors.join(" ")).toMatch(/digest mismatch/i);
44
+ });
45
+ it("detects tampering inside a nested dimension", async () => {
46
+ const cert = await finalizeCertificate(body());
47
+ const tampered = JSON.parse(JSON.stringify(cert));
48
+ tampered.dimensions.security.score = 10;
49
+ const result = await verifyCertificate(tampered);
50
+ expect(result.valid).toBe(false);
51
+ });
52
+ it("rejects a structurally invalid certificate", async () => {
53
+ const result = await verifyCertificate({ not: "a certificate" });
54
+ expect(result.valid).toBe(false);
55
+ expect(result.schemaValid).toBe(false);
56
+ });
57
+ it("round-trips through parseCertificate", async () => {
58
+ const cert = await finalizeCertificate(body());
59
+ const json = JSON.parse(JSON.stringify(cert));
60
+ const parsed = parseCertificate(json);
61
+ expect(parsed.certificateId).toBe(cert.certificateId);
62
+ });
63
+ it("throws a typed error for an invalid body", async () => {
64
+ const bad = { ...body(), overallScore: 999 };
65
+ await expect(finalizeCertificate(bad)).rejects.toBeInstanceOf(CertificateError);
66
+ });
67
+ it("the sample body validates against the full schema once finalized", async () => {
68
+ const cert = await finalizeCertificate(body());
69
+ expect(AgentCertificateSchema.safeParse(cert).success).toBe(true);
70
+ });
71
+ it("canonicalize + computeContentDigest agree with finalize", async () => {
72
+ const b = body();
73
+ const cert = await finalizeCertificate(b);
74
+ expect(computeContentDigest(b)).toBe(cert.integrity.contentDigest);
75
+ expect(typeof canonicalize(b)).toBe("string");
76
+ });
77
+ });
78
+ //# sourceMappingURL=agent-certificate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-certificate.test.js","sourceRoot":"","sources":["../../../src/__tests__/certification/agent-certificate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verify-endpoint.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-endpoint.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/certification/verify-endpoint.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ import { describe, it, expect, beforeAll } from "vitest";
2
+ import { finalizeCertificate, AGENT_CERTIFICATE_SCHEMA, } from "../../certification/agent-certificate.js";
3
+ import { verifyCertificatePayload } from "../../certification/verify-endpoint.js";
4
+ const NOW = new Date("2026-06-15T00:00:00.000Z");
5
+ function bodyFixture(over = {}) {
6
+ const dim = {
7
+ status: "pass",
8
+ score: 95,
9
+ summary: "ok",
10
+ checks: [],
11
+ };
12
+ return {
13
+ schemaVersion: AGENT_CERTIFICATE_SCHEMA,
14
+ certificateId: "vac_test_0001",
15
+ subject: { kind: "mcp-server", name: "test-subject", version: "1.0.0" },
16
+ issuer: { name: "Vaspera", tool: "vaspera-hardening", toolVersion: "2.14.0" },
17
+ issuedAt: "2026-06-10T00:00:00.000Z",
18
+ expiresAt: "2026-09-10T00:00:00.000Z",
19
+ level: "CERTIFIED",
20
+ overallScore: 95,
21
+ dimensions: {
22
+ security: dim,
23
+ scalability: dim,
24
+ quality: dim,
25
+ explainability: dim,
26
+ compliance: { status: "pass", score: 95, summary: "ok", frameworks: [] },
27
+ aiBom: { status: "pass", score: 95, summary: "ok", components: [] },
28
+ },
29
+ provenance: {},
30
+ evidence: [],
31
+ ...over,
32
+ };
33
+ }
34
+ describe("verifyCertificatePayload", () => {
35
+ let validCert;
36
+ beforeAll(async () => {
37
+ validCert = await finalizeCertificate(bodyFixture());
38
+ });
39
+ it("verifies a well-formed, untampered certificate", async () => {
40
+ const r = await verifyCertificatePayload(validCert, NOW);
41
+ expect(r.valid).toBe(true);
42
+ expect(r.schemaValid).toBe(true);
43
+ expect(r.contentDigestValid).toBe(true);
44
+ expect(r.summary).toMatch(/^VALID/);
45
+ });
46
+ it("surfaces the certificate's claims when structurally valid", async () => {
47
+ const r = await verifyCertificatePayload(validCert, NOW);
48
+ expect(r.claims).toBeDefined();
49
+ expect(r.claims.subject.name).toBe("test-subject");
50
+ expect(r.claims.level).toBe("CERTIFIED");
51
+ expect(r.claims.overallScore).toBe(95);
52
+ });
53
+ it("rejects a tampered certificate (digest mismatch)", async () => {
54
+ const tampered = JSON.parse(JSON.stringify(validCert));
55
+ tampered.overallScore = 100; // mutate body without recomputing the digest
56
+ const r = await verifyCertificatePayload(tampered, NOW);
57
+ expect(r.valid).toBe(false);
58
+ expect(r.contentDigestValid).toBe(false);
59
+ expect(r.summary).toMatch(/tampered/i);
60
+ });
61
+ it("rejects a non-certificate document", async () => {
62
+ const r = await verifyCertificatePayload({ hello: "world" }, NOW);
63
+ expect(r.valid).toBe(false);
64
+ expect(r.schemaValid).toBe(false);
65
+ expect(r.summary).toMatch(/not a well-formed/i);
66
+ });
67
+ it("flags an expired certificate as VALID but EXPIRED", async () => {
68
+ const expired = await finalizeCertificate(bodyFixture({ expiresAt: "2026-01-01T00:00:00.000Z" }));
69
+ const r = await verifyCertificatePayload(expired, NOW);
70
+ expect(r.valid).toBe(true); // integrity is independent of expiry
71
+ expect(r.expired).toBe(true);
72
+ expect(r.warnings.some((w) => /expired/i.test(w))).toBe(true);
73
+ expect(r.summary).toMatch(/EXPIRED/);
74
+ });
75
+ it("warns that a digest-only certificate is unsigned", async () => {
76
+ const r = await verifyCertificatePayload(validCert, NOW);
77
+ expect(r.signaturePresent).toBe(false);
78
+ expect(r.warnings.some((w) => /unsigned/i.test(w))).toBe(true);
79
+ });
80
+ });
81
+ //# sourceMappingURL=verify-endpoint.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-endpoint.test.js","sourceRoot":"","sources":["../../../src/__tests__/certification/verify-endpoint.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ai-frameworks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-frameworks.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/compliance/ai-frameworks.test.ts"],"names":[],"mappings":""}