@complior/engine 0.9.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 (594) hide show
  1. package/.well-known/ai-compliance.json +16 -0
  2. package/COMPLIANCE.md +64 -0
  3. package/data/data-integrity.test.ts +75 -0
  4. package/data/eval/eval-mappings.json +33 -0
  5. package/data/llm/model-pricing.json +15 -0
  6. package/data/llm/model-routing.json +36 -0
  7. package/data/onboarding/risk-profile.json +17 -0
  8. package/data/regulations/eu-ai-act/README.md +245 -0
  9. package/data/regulations/eu-ai-act/applicability-tree.json +160 -0
  10. package/data/regulations/eu-ai-act/cross-mapping.json +175 -0
  11. package/data/regulations/eu-ai-act/localization.json +186 -0
  12. package/data/regulations/eu-ai-act/obligations.json +3981 -0
  13. package/data/regulations/eu-ai-act/regulation-meta.json +482 -0
  14. package/data/regulations/eu-ai-act/scoring.json +342 -0
  15. package/data/regulations/eu-ai-act/technical-requirements.json +2590 -0
  16. package/data/regulations/eu-ai-act/timeline.json +160 -0
  17. package/data/regulations/jurisdictions/at.json +15 -0
  18. package/data/regulations/jurisdictions/be.json +15 -0
  19. package/data/regulations/jurisdictions/bg.json +15 -0
  20. package/data/regulations/jurisdictions/cy.json +15 -0
  21. package/data/regulations/jurisdictions/cz.json +15 -0
  22. package/data/regulations/jurisdictions/de.json +15 -0
  23. package/data/regulations/jurisdictions/dk.json +15 -0
  24. package/data/regulations/jurisdictions/ee.json +15 -0
  25. package/data/regulations/jurisdictions/es.json +15 -0
  26. package/data/regulations/jurisdictions/fi.json +15 -0
  27. package/data/regulations/jurisdictions/fr.json +15 -0
  28. package/data/regulations/jurisdictions/gr.json +15 -0
  29. package/data/regulations/jurisdictions/hr.json +15 -0
  30. package/data/regulations/jurisdictions/hu.json +15 -0
  31. package/data/regulations/jurisdictions/ie.json +15 -0
  32. package/data/regulations/jurisdictions/is.json +15 -0
  33. package/data/regulations/jurisdictions/it.json +15 -0
  34. package/data/regulations/jurisdictions/li.json +15 -0
  35. package/data/regulations/jurisdictions/lt.json +15 -0
  36. package/data/regulations/jurisdictions/lu.json +15 -0
  37. package/data/regulations/jurisdictions/lv.json +15 -0
  38. package/data/regulations/jurisdictions/mt.json +15 -0
  39. package/data/regulations/jurisdictions/nl.json +15 -0
  40. package/data/regulations/jurisdictions/no.json +15 -0
  41. package/data/regulations/jurisdictions/pl.json +15 -0
  42. package/data/regulations/jurisdictions/pt.json +15 -0
  43. package/data/regulations/jurisdictions/ro.json +15 -0
  44. package/data/regulations/jurisdictions/se.json +15 -0
  45. package/data/regulations/jurisdictions/si.json +15 -0
  46. package/data/regulations/jurisdictions/sk.json +15 -0
  47. package/data/scanner/check-id-categories.json +81 -0
  48. package/data/scanner/confidence-params.json +16 -0
  49. package/data/scanner/limits.json +4 -0
  50. package/data/schemas/http-contract-sample.json +79 -0
  51. package/data/schemas/http-contract.json +144 -0
  52. package/data/semgrep-rules/bare-call.yaml +37 -0
  53. package/data/semgrep-rules/injection.yaml +73 -0
  54. package/data/semgrep-rules/missing-error-handling.yaml +58 -0
  55. package/data/semgrep-rules/unsafe-deser.yaml +65 -0
  56. package/data/templates/eu-ai-act/ai-literacy.md +184 -0
  57. package/data/templates/eu-ai-act/art5-screening.md +131 -0
  58. package/data/templates/eu-ai-act/data-governance.md +145 -0
  59. package/data/templates/eu-ai-act/declaration-of-conformity.md +161 -0
  60. package/data/templates/eu-ai-act/fria.md +127 -0
  61. package/data/templates/eu-ai-act/gpai-systemic-risk.md +150 -0
  62. package/data/templates/eu-ai-act/gpai-transparency.md +166 -0
  63. package/data/templates/eu-ai-act/incident-report.md +188 -0
  64. package/data/templates/eu-ai-act/instructions-for-use.md +202 -0
  65. package/data/templates/eu-ai-act/monitoring-policy.md +110 -0
  66. package/data/templates/eu-ai-act/qms.md +180 -0
  67. package/data/templates/eu-ai-act/risk-management-system.md +123 -0
  68. package/data/templates/eu-ai-act/technical-documentation.md +287 -0
  69. package/data/templates/eu-ai-act/worker-notification.md +143 -0
  70. package/data/templates/policies/biometrics-ai-policy.md +214 -0
  71. package/data/templates/policies/critical-infra-ai-policy.md +228 -0
  72. package/data/templates/policies/education-ai-policy.md +184 -0
  73. package/data/templates/policies/finance-ai-policy.md +191 -0
  74. package/data/templates/policies/healthcare-ai-policy.md +197 -0
  75. package/data/templates/policies/hr-ai-policy.md +178 -0
  76. package/data/templates/policies/legal-ai-policy.md +189 -0
  77. package/data/templates/policies/migration-ai-policy.md +239 -0
  78. package/engine.log +7 -0
  79. package/package.json +74 -0
  80. package/src/composition-root.ts +791 -0
  81. package/src/data/eval/conformity-tests.test.ts +122 -0
  82. package/src/data/eval/ct-1-transparency.ts +106 -0
  83. package/src/data/eval/ct-10-gpai.ts +25 -0
  84. package/src/data/eval/ct-11-industry.ts +42 -0
  85. package/src/data/eval/ct-2-oversight.ts +41 -0
  86. package/src/data/eval/ct-3-explanation.ts +14 -0
  87. package/src/data/eval/ct-4-bias.ts +83 -0
  88. package/src/data/eval/ct-5-accuracy.ts +41 -0
  89. package/src/data/eval/ct-6-robustness.ts +81 -0
  90. package/src/data/eval/ct-7-prohibited.ts +52 -0
  91. package/src/data/eval/ct-8-logging.ts +68 -0
  92. package/src/data/eval/ct-9-risk-awareness.ts +33 -0
  93. package/src/data/eval/deterministic-evaluator.ts +120 -0
  94. package/src/data/eval/index.ts +55 -0
  95. package/src/data/eval/judge-prompts.ts +146 -0
  96. package/src/data/eval/llm-judged-tests.ts +279 -0
  97. package/src/data/eval/llm-tests.test.ts +83 -0
  98. package/src/data/eval/remediation/ct-1-transparency.ts +91 -0
  99. package/src/data/eval/remediation/ct-10-gpai.ts +94 -0
  100. package/src/data/eval/remediation/ct-11-industry.ts +94 -0
  101. package/src/data/eval/remediation/ct-2-oversight.ts +71 -0
  102. package/src/data/eval/remediation/ct-3-explanation.ts +70 -0
  103. package/src/data/eval/remediation/ct-4-bias.ts +70 -0
  104. package/src/data/eval/remediation/ct-5-accuracy.ts +70 -0
  105. package/src/data/eval/remediation/ct-6-robustness.ts +70 -0
  106. package/src/data/eval/remediation/ct-7-prohibited.ts +94 -0
  107. package/src/data/eval/remediation/ct-8-logging.ts +94 -0
  108. package/src/data/eval/remediation/ct-9-risk-awareness.ts +94 -0
  109. package/src/data/eval/remediation/index.ts +89 -0
  110. package/src/data/eval/remediation/owasp-art5.ts +15 -0
  111. package/src/data/eval/remediation/owasp-llm01.ts +72 -0
  112. package/src/data/eval/remediation/owasp-llm02.ts +72 -0
  113. package/src/data/eval/remediation/owasp-llm03.ts +15 -0
  114. package/src/data/eval/remediation/owasp-llm04.ts +15 -0
  115. package/src/data/eval/remediation/owasp-llm05.ts +15 -0
  116. package/src/data/eval/remediation/owasp-llm06.ts +15 -0
  117. package/src/data/eval/remediation/owasp-llm07.ts +15 -0
  118. package/src/data/eval/remediation/owasp-llm08.ts +15 -0
  119. package/src/data/eval/remediation/owasp-llm09.ts +15 -0
  120. package/src/data/eval/remediation/owasp-llm10.ts +15 -0
  121. package/src/data/eval/remediation/remediation.test.ts +229 -0
  122. package/src/data/eval/remediation/test-mapping.ts +290 -0
  123. package/src/data/eval/security-rubrics.ts +381 -0
  124. package/src/data/finding-explanations.json +453 -0
  125. package/src/data/industry-patterns.ts +161 -0
  126. package/src/data/registry-cards.ts +368 -0
  127. package/src/data/regulation/index.ts +5 -0
  128. package/src/data/regulation/jurisdiction-data.test.ts +73 -0
  129. package/src/data/regulation/jurisdiction-data.ts +65 -0
  130. package/src/data/regulation/regulation-data.ts +19 -0
  131. package/src/data/regulation/regulation-loader.test.ts +107 -0
  132. package/src/data/regulation/regulation-loader.ts +56 -0
  133. package/src/data/scanner-constants.ts +46 -0
  134. package/src/data/schemas/schemas-core.ts +140 -0
  135. package/src/data/schemas/schemas-supplementary.ts +211 -0
  136. package/src/data/schemas/schemas.ts +28 -0
  137. package/src/data/security/attack-probes.test.ts +62 -0
  138. package/src/data/security/attack-probes.ts +496 -0
  139. package/src/data/security/eu-ai-act-security.ts +40 -0
  140. package/src/data/security/index.ts +19 -0
  141. package/src/data/security/mitre-atlas.test.ts +43 -0
  142. package/src/data/security/mitre-atlas.ts +93 -0
  143. package/src/data/security/nist-ai-rmf.ts +43 -0
  144. package/src/data/security/owasp-llm-top10.test.ts +60 -0
  145. package/src/data/security/owasp-llm-top10.ts +138 -0
  146. package/src/data/template-registry.ts +53 -0
  147. package/src/data/tool-versions.json +22 -0
  148. package/src/domain/audit/audit-package.test.ts +152 -0
  149. package/src/domain/audit/audit-package.ts +166 -0
  150. package/src/domain/audit/audit-trail.test.ts +121 -0
  151. package/src/domain/audit/audit-trail.ts +174 -0
  152. package/src/domain/audit/index.ts +8 -0
  153. package/src/domain/audit/permissions-matrix.test.ts +136 -0
  154. package/src/domain/audit/permissions-matrix.ts +121 -0
  155. package/src/domain/certification/adversarial/bias-tests.ts +95 -0
  156. package/src/domain/certification/adversarial/evaluators.ts +304 -0
  157. package/src/domain/certification/adversarial/index.ts +11 -0
  158. package/src/domain/certification/adversarial/prompt-injection.ts +103 -0
  159. package/src/domain/certification/adversarial/safety-boundary.ts +132 -0
  160. package/src/domain/certification/aiuc1-readiness.test.ts +236 -0
  161. package/src/domain/certification/aiuc1-readiness.ts +298 -0
  162. package/src/domain/certification/aiuc1-requirements.ts +235 -0
  163. package/src/domain/certification/index.ts +10 -0
  164. package/src/domain/certification/redteam-runner.test.ts +97 -0
  165. package/src/domain/certification/redteam-runner.ts +205 -0
  166. package/src/domain/certification/test-runner.test.ts +232 -0
  167. package/src/domain/certification/test-runner.ts +289 -0
  168. package/src/domain/cost/cost-estimator.test.ts +187 -0
  169. package/src/domain/cost/cost-estimator.ts +133 -0
  170. package/src/domain/disclaimer.test.ts +52 -0
  171. package/src/domain/disclaimer.ts +39 -0
  172. package/src/domain/documents/ai-enricher.test.ts +120 -0
  173. package/src/domain/documents/ai-enricher.ts +159 -0
  174. package/src/domain/documents/document-generator.test.ts +318 -0
  175. package/src/domain/documents/document-generator.ts +239 -0
  176. package/src/domain/documents/index.ts +9 -0
  177. package/src/domain/documents/passport-helpers.ts +25 -0
  178. package/src/domain/documents/policy-generator.test.ts +252 -0
  179. package/src/domain/documents/policy-generator.ts +94 -0
  180. package/src/domain/documents/worker-notification-generator.test.ts +162 -0
  181. package/src/domain/documents/worker-notification-generator.ts +141 -0
  182. package/src/domain/eval/adapters/adapter-port.ts +94 -0
  183. package/src/domain/eval/adapters/adapters.test.ts +303 -0
  184. package/src/domain/eval/adapters/anthropic-adapter.ts +57 -0
  185. package/src/domain/eval/adapters/auto-detect.ts +104 -0
  186. package/src/domain/eval/adapters/create-chat-adapter.ts +106 -0
  187. package/src/domain/eval/adapters/custom-adapter.ts +74 -0
  188. package/src/domain/eval/adapters/http-adapter.ts +66 -0
  189. package/src/domain/eval/adapters/index.ts +7 -0
  190. package/src/domain/eval/adapters/ollama-adapter.ts +48 -0
  191. package/src/domain/eval/adapters/openai-adapter.ts +58 -0
  192. package/src/domain/eval/adapters/with-timeout.ts +25 -0
  193. package/src/domain/eval/conformity-score.test.ts +161 -0
  194. package/src/domain/eval/conformity-score.ts +135 -0
  195. package/src/domain/eval/eval-constants.ts +55 -0
  196. package/src/domain/eval/eval-evidence.test.ts +85 -0
  197. package/src/domain/eval/eval-evidence.ts +103 -0
  198. package/src/domain/eval/eval-fix-generator.test.ts +421 -0
  199. package/src/domain/eval/eval-fix-generator.ts +205 -0
  200. package/src/domain/eval/eval-passport.test.ts +82 -0
  201. package/src/domain/eval/eval-passport.ts +89 -0
  202. package/src/domain/eval/eval-remediation-report.test.ts +682 -0
  203. package/src/domain/eval/eval-remediation-report.ts +170 -0
  204. package/src/domain/eval/eval-report.ts +108 -0
  205. package/src/domain/eval/eval-runner.test.ts +609 -0
  206. package/src/domain/eval/eval-runner.ts +593 -0
  207. package/src/domain/eval/eval-to-findings.test.ts +293 -0
  208. package/src/domain/eval/eval-to-findings.ts +83 -0
  209. package/src/domain/eval/index.ts +31 -0
  210. package/src/domain/eval/llm-judge.test.ts +139 -0
  211. package/src/domain/eval/llm-judge.ts +168 -0
  212. package/src/domain/eval/remediation-types.ts +90 -0
  213. package/src/domain/eval/security-integration.test.ts +196 -0
  214. package/src/domain/eval/security-integration.ts +136 -0
  215. package/src/domain/eval/types.test.ts +173 -0
  216. package/src/domain/eval/types.ts +244 -0
  217. package/src/domain/eval/verdict-utils.ts +45 -0
  218. package/src/domain/fixer/create-fixer.ts +101 -0
  219. package/src/domain/fixer/diff.ts +70 -0
  220. package/src/domain/fixer/fix-history.ts +23 -0
  221. package/src/domain/fixer/fixer.test.ts +306 -0
  222. package/src/domain/fixer/index.ts +9 -0
  223. package/src/domain/fixer/strategies/bandit-fix.ts +61 -0
  224. package/src/domain/fixer/strategies/bias-testing.ts +49 -0
  225. package/src/domain/fixer/strategies/ci-compliance.ts +57 -0
  226. package/src/domain/fixer/strategies/content-marking.ts +45 -0
  227. package/src/domain/fixer/strategies/cve-upgrade.ts +66 -0
  228. package/src/domain/fixer/strategies/data-governance.ts +65 -0
  229. package/src/domain/fixer/strategies/disclosure.ts +69 -0
  230. package/src/domain/fixer/strategies/doc-code-sync.ts +53 -0
  231. package/src/domain/fixer/strategies/documentation.ts +59 -0
  232. package/src/domain/fixer/strategies/error-handler.ts +63 -0
  233. package/src/domain/fixer/strategies/hitl-gate.ts +67 -0
  234. package/src/domain/fixer/strategies/index.ts +61 -0
  235. package/src/domain/fixer/strategies/kill-switch-test.ts +85 -0
  236. package/src/domain/fixer/strategies/kill-switch.ts +53 -0
  237. package/src/domain/fixer/strategies/license-fix.ts +57 -0
  238. package/src/domain/fixer/strategies/log-retention.ts +40 -0
  239. package/src/domain/fixer/strategies/logging.ts +59 -0
  240. package/src/domain/fixer/strategies/metadata.ts +45 -0
  241. package/src/domain/fixer/strategies/permission-guard.ts +84 -0
  242. package/src/domain/fixer/strategies/record-keeping.ts +69 -0
  243. package/src/domain/fixer/strategies/secret-rotation.ts +52 -0
  244. package/src/domain/fixer/strategies.test.ts +341 -0
  245. package/src/domain/fixer/template-engine.test.ts +64 -0
  246. package/src/domain/fixer/template-engine.ts +38 -0
  247. package/src/domain/fixer/types.ts +88 -0
  248. package/src/domain/frameworks/aiuc1-framework.test.ts +159 -0
  249. package/src/domain/frameworks/aiuc1-framework.ts +126 -0
  250. package/src/domain/frameworks/collect-foundation-metrics.test.ts +96 -0
  251. package/src/domain/frameworks/collect-foundation-metrics.ts +34 -0
  252. package/src/domain/frameworks/eu-ai-act-framework.test.ts +117 -0
  253. package/src/domain/frameworks/eu-ai-act-framework.ts +100 -0
  254. package/src/domain/frameworks/framework-registry.test.ts +91 -0
  255. package/src/domain/frameworks/framework-registry.ts +38 -0
  256. package/src/domain/frameworks/index.ts +8 -0
  257. package/src/domain/frameworks/mitre-atlas-framework.test.ts +53 -0
  258. package/src/domain/frameworks/mitre-atlas-framework.ts +53 -0
  259. package/src/domain/frameworks/owasp-llm-framework.test.ts +77 -0
  260. package/src/domain/frameworks/owasp-llm-framework.ts +54 -0
  261. package/src/domain/frameworks/score-plugin-framework.ts +117 -0
  262. package/src/domain/fria/fria-generator.test.ts +273 -0
  263. package/src/domain/fria/fria-generator.ts +366 -0
  264. package/src/domain/import/promptfoo-importer.test.ts +103 -0
  265. package/src/domain/import/promptfoo-importer.ts +151 -0
  266. package/src/domain/onboarding/guided-onboarding.test.ts +144 -0
  267. package/src/domain/onboarding/guided-onboarding.ts +135 -0
  268. package/src/domain/passport/builder/domain-mapper.ts +9 -0
  269. package/src/domain/passport/builder/manifest-builder.test.ts +546 -0
  270. package/src/domain/passport/builder/manifest-builder.ts +535 -0
  271. package/src/domain/passport/builder/manifest-diff.test.ts +105 -0
  272. package/src/domain/passport/builder/manifest-diff.ts +89 -0
  273. package/src/domain/passport/builder/manifest-files.ts +17 -0
  274. package/src/domain/passport/crypto-signer.test.ts +93 -0
  275. package/src/domain/passport/crypto-signer.ts +157 -0
  276. package/src/domain/passport/discovery/agent-discovery.test.ts +296 -0
  277. package/src/domain/passport/discovery/agent-discovery.ts +325 -0
  278. package/src/domain/passport/discovery/autonomy-analyzer.test.ts +141 -0
  279. package/src/domain/passport/discovery/autonomy-analyzer.ts +113 -0
  280. package/src/domain/passport/discovery/permission-scanner.test.ts +191 -0
  281. package/src/domain/passport/discovery/permission-scanner.ts +414 -0
  282. package/src/domain/passport/export/a2a-mapper.ts +75 -0
  283. package/src/domain/passport/export/aiuc1-mapper.ts +126 -0
  284. package/src/domain/passport/export/export.test.ts +207 -0
  285. package/src/domain/passport/export/index.ts +41 -0
  286. package/src/domain/passport/export/nist-mapper.ts +227 -0
  287. package/src/domain/passport/import/a2a-importer.test.ts +133 -0
  288. package/src/domain/passport/import/a2a-importer.ts +156 -0
  289. package/src/domain/passport/import/index.ts +2 -0
  290. package/src/domain/passport/index.ts +32 -0
  291. package/src/domain/passport/obligation-field-map.test.ts +113 -0
  292. package/src/domain/passport/obligation-field-map.ts +117 -0
  293. package/src/domain/passport/passport-validator.test.ts +156 -0
  294. package/src/domain/passport/passport-validator.ts +126 -0
  295. package/src/domain/passport/scan-to-compliance.test.ts +336 -0
  296. package/src/domain/passport/scan-to-compliance.ts +166 -0
  297. package/src/domain/passport/test-generator.test.ts +93 -0
  298. package/src/domain/passport/test-generator.ts +136 -0
  299. package/src/domain/proxy/index.ts +11 -0
  300. package/src/domain/proxy/json-rpc.test.ts +72 -0
  301. package/src/domain/proxy/json-rpc.ts +53 -0
  302. package/src/domain/proxy/policy-engine.test.ts +259 -0
  303. package/src/domain/proxy/policy-engine.ts +137 -0
  304. package/src/domain/proxy/proxy-bridge.ts +125 -0
  305. package/src/domain/proxy/proxy-interceptor.test.ts +184 -0
  306. package/src/domain/proxy/proxy-interceptor.ts +120 -0
  307. package/src/domain/proxy/proxy-types.ts +35 -0
  308. package/src/domain/registry/compute-agent-score.test.ts +279 -0
  309. package/src/domain/registry/compute-agent-score.ts +162 -0
  310. package/src/domain/reporter/audit-report.test.ts +87 -0
  311. package/src/domain/reporter/audit-report.ts +116 -0
  312. package/src/domain/reporter/badge-generator.test.ts +54 -0
  313. package/src/domain/reporter/badge-generator.ts +40 -0
  314. package/src/domain/reporter/compliance-md.ts +45 -0
  315. package/src/domain/reporter/index.ts +7 -0
  316. package/src/domain/reporter/pdf-renderer.ts +282 -0
  317. package/src/domain/reporter/share.test.ts +92 -0
  318. package/src/domain/reporter/share.ts +80 -0
  319. package/src/domain/scanner/ast/swc-analyzer.test.ts +49 -0
  320. package/src/domain/scanner/ast/swc-analyzer.ts +124 -0
  321. package/src/domain/scanner/attestations.ts +97 -0
  322. package/src/domain/scanner/checks/ai-disclosure.test.ts +90 -0
  323. package/src/domain/scanner/checks/ai-disclosure.ts +54 -0
  324. package/src/domain/scanner/checks/ai-literacy.ts +163 -0
  325. package/src/domain/scanner/checks/behavioral-constraints.test.ts +167 -0
  326. package/src/domain/scanner/checks/behavioral-constraints.ts +86 -0
  327. package/src/domain/scanner/checks/compliance-metadata.ts +63 -0
  328. package/src/domain/scanner/checks/content-marking.ts +74 -0
  329. package/src/domain/scanner/checks/dep-deep-scan.test.ts +318 -0
  330. package/src/domain/scanner/checks/dep-deep-scan.ts +137 -0
  331. package/src/domain/scanner/checks/documentation.test.ts +88 -0
  332. package/src/domain/scanner/checks/documentation.ts +79 -0
  333. package/src/domain/scanner/checks/git-history.test.ts +120 -0
  334. package/src/domain/scanner/checks/git-history.ts +163 -0
  335. package/src/domain/scanner/checks/gpai-systemic-risk.test.ts +84 -0
  336. package/src/domain/scanner/checks/gpai-systemic-risk.ts +98 -0
  337. package/src/domain/scanner/checks/gpai-transparency.ts +94 -0
  338. package/src/domain/scanner/checks/index.ts +28 -0
  339. package/src/domain/scanner/checks/industry/index.ts +40 -0
  340. package/src/domain/scanner/checks/industry/industry.test.ts +287 -0
  341. package/src/domain/scanner/checks/interaction-logging.test.ts +113 -0
  342. package/src/domain/scanner/checks/interaction-logging.ts +142 -0
  343. package/src/domain/scanner/checks/nhi-scanner.test.ts +158 -0
  344. package/src/domain/scanner/checks/nhi-scanner.ts +78 -0
  345. package/src/domain/scanner/checks/passport-completeness.test.ts +127 -0
  346. package/src/domain/scanner/checks/passport-completeness.ts +82 -0
  347. package/src/domain/scanner/checks/passport-presence.test.ts +56 -0
  348. package/src/domain/scanner/checks/passport-presence.ts +78 -0
  349. package/src/domain/scanner/checks/pattern-check-factory.ts +70 -0
  350. package/src/domain/scanner/checks/permission-scanner.test.ts +279 -0
  351. package/src/domain/scanner/checks/permission-scanner.ts +90 -0
  352. package/src/domain/scanner/checks/presence-check-factory.test.ts +124 -0
  353. package/src/domain/scanner/checks/presence-check-factory.ts +275 -0
  354. package/src/domain/scanner/compliance-diff.test.ts +165 -0
  355. package/src/domain/scanner/compliance-diff.ts +138 -0
  356. package/src/domain/scanner/confidence.test.ts +235 -0
  357. package/src/domain/scanner/confidence.ts +156 -0
  358. package/src/domain/scanner/constants.ts +13 -0
  359. package/src/domain/scanner/create-scanner.ts +573 -0
  360. package/src/domain/scanner/cross-layer.test.ts +372 -0
  361. package/src/domain/scanner/cross-layer.ts +232 -0
  362. package/src/domain/scanner/data/ai-packages.ts +82 -0
  363. package/src/domain/scanner/debt-calculator.test.ts +89 -0
  364. package/src/domain/scanner/debt-calculator.ts +111 -0
  365. package/src/domain/scanner/drift.test.ts +191 -0
  366. package/src/domain/scanner/drift.ts +73 -0
  367. package/src/domain/scanner/evidence-store.test.ts +207 -0
  368. package/src/domain/scanner/evidence-store.ts +195 -0
  369. package/src/domain/scanner/evidence.test.ts +104 -0
  370. package/src/domain/scanner/evidence.ts +71 -0
  371. package/src/domain/scanner/external/bandit-runner.test.ts +45 -0
  372. package/src/domain/scanner/external/bandit-runner.ts +90 -0
  373. package/src/domain/scanner/external/checks.ts +321 -0
  374. package/src/domain/scanner/external/dedup.test.ts +79 -0
  375. package/src/domain/scanner/external/dedup.ts +94 -0
  376. package/src/domain/scanner/external/detect-secrets-runner.test.ts +58 -0
  377. package/src/domain/scanner/external/detect-secrets-runner.ts +81 -0
  378. package/src/domain/scanner/external/external-scanner.test.ts +221 -0
  379. package/src/domain/scanner/external/external-scanner.ts +36 -0
  380. package/src/domain/scanner/external/finding-mapper.test.ts +95 -0
  381. package/src/domain/scanner/external/finding-mapper.ts +138 -0
  382. package/src/domain/scanner/external/index.ts +15 -0
  383. package/src/domain/scanner/external/mappings.ts +93 -0
  384. package/src/domain/scanner/external/modelscan-runner.test.ts +35 -0
  385. package/src/domain/scanner/external/modelscan-runner.ts +101 -0
  386. package/src/domain/scanner/external/path-utils.ts +8 -0
  387. package/src/domain/scanner/external/runner-port.ts +45 -0
  388. package/src/domain/scanner/external/semgrep-runner.test.ts +52 -0
  389. package/src/domain/scanner/external/semgrep-runner.ts +94 -0
  390. package/src/domain/scanner/external/types.ts +32 -0
  391. package/src/domain/scanner/finding-attribution.test.ts +444 -0
  392. package/src/domain/scanner/finding-attribution.ts +195 -0
  393. package/src/domain/scanner/finding-explainer.test.ts +157 -0
  394. package/src/domain/scanner/finding-explainer.ts +73 -0
  395. package/src/domain/scanner/fix-diff-builder.test.ts +272 -0
  396. package/src/domain/scanner/fix-diff-builder.ts +477 -0
  397. package/src/domain/scanner/import-graph.test.ts +162 -0
  398. package/src/domain/scanner/import-graph.ts +198 -0
  399. package/src/domain/scanner/languages/adapter.test.ts +105 -0
  400. package/src/domain/scanner/languages/adapter.ts +239 -0
  401. package/src/domain/scanner/layers/index.ts +24 -0
  402. package/src/domain/scanner/layers/layer1-files.ts +54 -0
  403. package/src/domain/scanner/layers/layer2-docs.test.ts +1207 -0
  404. package/src/domain/scanner/layers/layer2-docs.ts +297 -0
  405. package/src/domain/scanner/layers/layer2-parsing.ts +217 -0
  406. package/src/domain/scanner/layers/layer3-config.test.ts +187 -0
  407. package/src/domain/scanner/layers/layer3-config.ts +279 -0
  408. package/src/domain/scanner/layers/layer3-parsers.ts +73 -0
  409. package/src/domain/scanner/layers/layer4-patterns.test.ts +397 -0
  410. package/src/domain/scanner/layers/layer4-patterns.ts +216 -0
  411. package/src/domain/scanner/layers/layer5-docs.test.ts +99 -0
  412. package/src/domain/scanner/layers/layer5-docs.ts +250 -0
  413. package/src/domain/scanner/layers/layer5-llm.test.ts +146 -0
  414. package/src/domain/scanner/layers/layer5-llm.ts +262 -0
  415. package/src/domain/scanner/layers/layer5-targeted.test.ts +93 -0
  416. package/src/domain/scanner/layers/layer5-targeted.ts +233 -0
  417. package/src/domain/scanner/layers/lockfile-parsers.test.ts +320 -0
  418. package/src/domain/scanner/layers/lockfile-parsers.ts +184 -0
  419. package/src/domain/scanner/regulation-version.test.ts +54 -0
  420. package/src/domain/scanner/regulation-version.ts +23 -0
  421. package/src/domain/scanner/role-filter.test.ts +116 -0
  422. package/src/domain/scanner/role-filter.ts +51 -0
  423. package/src/domain/scanner/rules/banned-packages-data.ts +553 -0
  424. package/src/domain/scanner/rules/banned-packages-sdk.ts +65 -0
  425. package/src/domain/scanner/rules/banned-packages.test.ts +249 -0
  426. package/src/domain/scanner/rules/banned-packages.ts +55 -0
  427. package/src/domain/scanner/rules/comment-filter.test.ts +115 -0
  428. package/src/domain/scanner/rules/comment-filter.ts +297 -0
  429. package/src/domain/scanner/rules/index.ts +9 -0
  430. package/src/domain/scanner/rules/nhi-patterns.test.ts +128 -0
  431. package/src/domain/scanner/rules/nhi-patterns.ts +60 -0
  432. package/src/domain/scanner/rules/pattern-rules.ts +1152 -0
  433. package/src/domain/scanner/sbom.test.ts +136 -0
  434. package/src/domain/scanner/sbom.ts +103 -0
  435. package/src/domain/scanner/scan-cache.test.ts +136 -0
  436. package/src/domain/scanner/scan-cache.ts +115 -0
  437. package/src/domain/scanner/scanner.test.ts +125 -0
  438. package/src/domain/scanner/score-calculator.test.ts +363 -0
  439. package/src/domain/scanner/score-calculator.ts +189 -0
  440. package/src/domain/scanner/security-score.test.ts +107 -0
  441. package/src/domain/scanner/security-score.ts +116 -0
  442. package/src/domain/scanner/source-filter.ts +24 -0
  443. package/src/domain/scanner/validators.ts +223 -0
  444. package/src/domain/shared/compliance-constants.ts +48 -0
  445. package/src/domain/shared/disclosure-patterns.ts +16 -0
  446. package/src/domain/shared/index.ts +6 -0
  447. package/src/domain/shared/parse-dependencies.ts +21 -0
  448. package/src/domain/supply-chain/dependency-analyzer.ts +138 -0
  449. package/src/domain/supply-chain/index.ts +3 -0
  450. package/src/domain/supply-chain/supply-chain.test.ts +211 -0
  451. package/src/domain/supply-chain/types.ts +32 -0
  452. package/src/domain/whatif/config-fixer.ts +187 -0
  453. package/src/domain/whatif/index.ts +6 -0
  454. package/src/domain/whatif/scenario-engine.ts +121 -0
  455. package/src/domain/whatif/simulate-actions.test.ts +161 -0
  456. package/src/domain/whatif/simulate-actions.ts +114 -0
  457. package/src/domain/whatif/whatif.test.ts +135 -0
  458. package/src/e2e/gaps-e2e.test.ts +259 -0
  459. package/src/e2e/smoke.test.ts +101 -0
  460. package/src/hooks/hooks-export.test.ts +81 -0
  461. package/src/hooks/installer.ts +113 -0
  462. package/src/http/cors.test.ts +38 -0
  463. package/src/http/create-router.ts +259 -0
  464. package/src/http/routes/agent.route.ts +380 -0
  465. package/src/http/routes/audit.route.ts +66 -0
  466. package/src/http/routes/badge.route.ts +23 -0
  467. package/src/http/routes/cert.route.ts +66 -0
  468. package/src/http/routes/chat.route.ts +228 -0
  469. package/src/http/routes/cost.route.ts +33 -0
  470. package/src/http/routes/debt.route.ts +29 -0
  471. package/src/http/routes/disclaimer.route.ts +64 -0
  472. package/src/http/routes/eval.route.ts +161 -0
  473. package/src/http/routes/events.route.test.ts +108 -0
  474. package/src/http/routes/events.route.ts +71 -0
  475. package/src/http/routes/external-scan.route.ts +24 -0
  476. package/src/http/routes/file.route.ts +54 -0
  477. package/src/http/routes/fix.route.ts +219 -0
  478. package/src/http/routes/frameworks.route.test.ts +66 -0
  479. package/src/http/routes/frameworks.route.ts +36 -0
  480. package/src/http/routes/git.route.ts +27 -0
  481. package/src/http/routes/guided-onboarding.route.ts +65 -0
  482. package/src/http/routes/import.route.ts +64 -0
  483. package/src/http/routes/jurisdiction.route.ts +22 -0
  484. package/src/http/routes/obligations.route.test.ts +122 -0
  485. package/src/http/routes/obligations.route.ts +110 -0
  486. package/src/http/routes/onboarding.route.ts +53 -0
  487. package/src/http/routes/provider.route.ts +42 -0
  488. package/src/http/routes/proxy.route.ts +40 -0
  489. package/src/http/routes/redteam.route.ts +84 -0
  490. package/src/http/routes/report.route.ts +29 -0
  491. package/src/http/routes/scan.route.ts +104 -0
  492. package/src/http/routes/share.route.ts +44 -0
  493. package/src/http/routes/shell.route.ts +27 -0
  494. package/src/http/routes/status.route.ts +66 -0
  495. package/src/http/routes/supply-chain.route.ts +121 -0
  496. package/src/http/routes/sync.route.ts +328 -0
  497. package/src/http/routes/tools.route.ts +29 -0
  498. package/src/http/routes/whatif.route.ts +96 -0
  499. package/src/http/utils/validation.ts +31 -0
  500. package/src/index.ts +1 -0
  501. package/src/infra/bundle-fetcher.ts +77 -0
  502. package/src/infra/cache-storage.ts +34 -0
  503. package/src/infra/event-bus.ts +31 -0
  504. package/src/infra/file-collector.ts +61 -0
  505. package/src/infra/file-ops-adapter.ts +95 -0
  506. package/src/infra/file-watcher.test.ts +90 -0
  507. package/src/infra/file-watcher.ts +106 -0
  508. package/src/infra/git-adapter.ts +93 -0
  509. package/src/infra/git-history-adapter.ts +41 -0
  510. package/src/infra/headless-browser.ts +178 -0
  511. package/src/infra/llm-adapter.test.ts +83 -0
  512. package/src/infra/llm-adapter.ts +86 -0
  513. package/src/infra/logger.ts +27 -0
  514. package/src/infra/project-config.test.ts +74 -0
  515. package/src/infra/project-config.ts +35 -0
  516. package/src/infra/rate-limiter.test.ts +36 -0
  517. package/src/infra/rate-limiter.ts +34 -0
  518. package/src/infra/retry.ts +46 -0
  519. package/src/infra/saas-client.ts +123 -0
  520. package/src/infra/search-adapter.ts +113 -0
  521. package/src/infra/shell-adapter.ts +68 -0
  522. package/src/infra/tool-manager.test.ts +99 -0
  523. package/src/infra/tool-manager.ts +197 -0
  524. package/src/llm/agents/agent-modes.test.ts +44 -0
  525. package/src/llm/agents/modes.ts +68 -0
  526. package/src/llm/routing/cost-routing.test.ts +37 -0
  527. package/src/llm/routing/cost-tracker.ts +74 -0
  528. package/src/llm/routing/model-routing.test.ts +79 -0
  529. package/src/llm/routing/model-routing.ts +38 -0
  530. package/src/llm/routing/pricing.ts +19 -0
  531. package/src/llm/sse-protocol.ts +77 -0
  532. package/src/llm/tool-definitions.ts +83 -0
  533. package/src/llm/tool-executors.ts +80 -0
  534. package/src/llm/tools/types.ts +13 -0
  535. package/src/mcp/create-mcp-stack.ts +82 -0
  536. package/src/mcp/handlers.ts +245 -0
  537. package/src/mcp/index.ts +28 -0
  538. package/src/mcp/mcp-server.test.ts +80 -0
  539. package/src/mcp/server.ts +79 -0
  540. package/src/mcp/tools.ts +48 -0
  541. package/src/onboarding/auto-detect.ts +164 -0
  542. package/src/onboarding/onboarding.test.ts +89 -0
  543. package/src/onboarding/profile.ts +169 -0
  544. package/src/onboarding/questions.ts +112 -0
  545. package/src/onboarding/wizard.ts +66 -0
  546. package/src/output/github-issue.ts +32 -0
  547. package/src/output/json-output.ts +67 -0
  548. package/src/ports/browser.port.ts +23 -0
  549. package/src/ports/events.port.ts +28 -0
  550. package/src/ports/llm.port.ts +23 -0
  551. package/src/ports/logger.port.ts +6 -0
  552. package/src/ports/process.port.ts +6 -0
  553. package/src/ports/scanner.port.ts +15 -0
  554. package/src/server.ts +134 -0
  555. package/src/services/badge-service.ts +67 -0
  556. package/src/services/chat-service.test.ts +162 -0
  557. package/src/services/chat-service.ts +152 -0
  558. package/src/services/cost-service.ts +52 -0
  559. package/src/services/debt-service.ts +65 -0
  560. package/src/services/eval-integration.test.ts +132 -0
  561. package/src/services/eval-service.test.ts +373 -0
  562. package/src/services/eval-service.ts +463 -0
  563. package/src/services/external-scan-service.ts +60 -0
  564. package/src/services/file-service.ts +37 -0
  565. package/src/services/fix-service.test.ts +470 -0
  566. package/src/services/fix-service.ts +648 -0
  567. package/src/services/framework-service.test.ts +159 -0
  568. package/src/services/framework-service.ts +67 -0
  569. package/src/services/onboarding-service.ts +165 -0
  570. package/src/services/passport-audit.ts +244 -0
  571. package/src/services/passport-documents.ts +258 -0
  572. package/src/services/passport-service-utils.ts +72 -0
  573. package/src/services/passport-service.test.ts +251 -0
  574. package/src/services/passport-service.ts +339 -0
  575. package/src/services/proxy-service.ts +81 -0
  576. package/src/services/report-service.ts +72 -0
  577. package/src/services/scan-service.test.ts +470 -0
  578. package/src/services/scan-service.ts +335 -0
  579. package/src/services/share-service.ts +108 -0
  580. package/src/services/shared/backup.ts +23 -0
  581. package/src/services/status-service.ts +38 -0
  582. package/src/services/undo-service.test.ts +190 -0
  583. package/src/services/undo-service.ts +144 -0
  584. package/src/test-helpers/factories.ts +116 -0
  585. package/src/types/common.schemas.ts +147 -0
  586. package/src/types/common.types.ts +292 -0
  587. package/src/types/contract.test.ts +217 -0
  588. package/src/types/errors.ts +52 -0
  589. package/src/types/framework.types.ts +87 -0
  590. package/src/types/passport-schemas.ts +241 -0
  591. package/src/types/passport.types.ts +296 -0
  592. package/src/version.ts +1 -0
  593. package/tsconfig.json +20 -0
  594. package/vitest.config.ts +9 -0
@@ -0,0 +1,298 @@
1
+ /**
2
+ * AIUC-1 Readiness Score — pure scorer function.
3
+ * Evaluates each requirement against scan results, passport data,
4
+ * generated documents, and evidence chain summary.
5
+ */
6
+
7
+ import type { ScanResult, Finding } from '../../types/common.types.js';
8
+ import type { AgentPassport } from '../../types/passport.types.js';
9
+ import type { EvidenceChainSummary } from '../scanner/evidence-store.js';
10
+ import { AIUC1_REQUIREMENTS, AIUC1_CATEGORIES } from './aiuc1-requirements.js';
11
+ import type { Aiuc1Category, Aiuc1Check } from './aiuc1-requirements.js';
12
+
13
+ // --- Types ---
14
+
15
+ export interface ReadinessInput {
16
+ readonly passport: AgentPassport;
17
+ readonly scanResult: ScanResult | null;
18
+ readonly documents: ReadonlySet<string>;
19
+ readonly evidenceSummary: EvidenceChainSummary;
20
+ }
21
+
22
+ export interface CheckStatus {
23
+ readonly description: string;
24
+ readonly passed: boolean;
25
+ readonly detail?: string;
26
+ }
27
+
28
+ export interface RequirementStatus {
29
+ readonly id: string;
30
+ readonly title: string;
31
+ readonly category: Aiuc1Category;
32
+ readonly status: 'met' | 'partial' | 'unmet';
33
+ readonly weight: number;
34
+ readonly articleRef: string;
35
+ readonly checks: readonly CheckStatus[];
36
+ }
37
+
38
+ export interface CategoryScore {
39
+ readonly category: Aiuc1Category;
40
+ readonly label: string;
41
+ readonly score: number;
42
+ readonly maxWeight: number;
43
+ readonly achievedWeight: number;
44
+ }
45
+
46
+ export interface ReadinessResult {
47
+ readonly overallScore: number;
48
+ readonly readinessLevel: 'certified' | 'near_ready' | 'in_progress' | 'early';
49
+ readonly requirements: readonly RequirementStatus[];
50
+ readonly categories: readonly CategoryScore[];
51
+ readonly gaps: readonly string[];
52
+ readonly totalRequirements: number;
53
+ readonly metRequirements: number;
54
+ readonly partialRequirements: number;
55
+ readonly unmetRequirements: number;
56
+ }
57
+
58
+ // --- Check evaluators ---
59
+
60
+ const resolvePassportField = (passport: AgentPassport, path: string): unknown => {
61
+ const parts = path.split('.');
62
+ let current: unknown = passport;
63
+ for (const part of parts) {
64
+ if (current == null || typeof current !== 'object') return undefined;
65
+ current = (current as Record<string, unknown>)[part];
66
+ }
67
+ return current;
68
+ };
69
+
70
+ const isNonEmpty = (value: unknown): boolean => {
71
+ if (value == null) return false;
72
+ if (typeof value === 'string') return value.trim().length > 0;
73
+ if (typeof value === 'boolean') return value;
74
+ if (typeof value === 'number') return true;
75
+ if (Array.isArray(value)) return value.length > 0;
76
+ if (typeof value === 'object') return Object.keys(value as Record<string, unknown>).length > 0;
77
+ return false;
78
+ };
79
+
80
+ const evaluateScanCheck = (
81
+ target: string,
82
+ scanResult: ScanResult | null,
83
+ ): CheckStatus => {
84
+ if (!scanResult) {
85
+ return { description: '', passed: false, detail: 'No scan result available' };
86
+ }
87
+
88
+ // Special case: 'score' checks if scan was performed with score > 0
89
+ if (target === 'score') {
90
+ const passed = scanResult.score.totalScore > 0;
91
+ return {
92
+ description: '',
93
+ passed,
94
+ detail: passed ? `Score: ${scanResult.score.totalScore}` : 'Scan score is 0',
95
+ };
96
+ }
97
+
98
+ // Look for findings matching the target checkId (substring match)
99
+ const relevant = scanResult.findings.filter(
100
+ (f: Finding) => f.checkId.includes(target),
101
+ );
102
+
103
+ if (relevant.length === 0) {
104
+ return { description: '', passed: false, detail: `No findings for check '${target}'` };
105
+ }
106
+
107
+ // For 'banned-packages': passes when there are NO fail findings (no banned packages found)
108
+ if (target === 'banned-packages') {
109
+ const hasFails = relevant.some((f: Finding) => f.type === 'fail');
110
+ return {
111
+ description: '',
112
+ passed: !hasFails,
113
+ detail: hasFails ? 'Banned packages detected' : 'No banned packages',
114
+ };
115
+ }
116
+
117
+ // General scan checks: pass if at least one 'pass' finding exists
118
+ const hasPass = relevant.some((f: Finding) => f.type === 'pass');
119
+ return {
120
+ description: '',
121
+ passed: hasPass,
122
+ detail: hasPass ? `Check '${target}' passed` : `Check '${target}' failed`,
123
+ };
124
+ };
125
+
126
+ const evaluatePassportField = (
127
+ target: string,
128
+ passport: AgentPassport,
129
+ ): CheckStatus => {
130
+ const value = resolvePassportField(passport, target);
131
+ const passed = isNonEmpty(value);
132
+ return {
133
+ description: '',
134
+ passed,
135
+ detail: passed ? `Field '${target}' is set` : `Field '${target}' is missing or empty`,
136
+ };
137
+ };
138
+
139
+ const evaluateDocument = (
140
+ target: string,
141
+ documents: ReadonlySet<string>,
142
+ ): CheckStatus => {
143
+ const passed = documents.has(target);
144
+ return {
145
+ description: '',
146
+ passed,
147
+ detail: passed ? `Document '${target}' exists` : `Document '${target}' not generated`,
148
+ };
149
+ };
150
+
151
+ const evaluateEvidence = (
152
+ target: string,
153
+ evidenceSummary: EvidenceChainSummary,
154
+ ): CheckStatus => {
155
+ if (target === 'chain_active') {
156
+ const passed = evidenceSummary.totalEntries > 0;
157
+ return {
158
+ description: '',
159
+ passed,
160
+ detail: passed
161
+ ? `Evidence chain has ${evidenceSummary.totalEntries} entries`
162
+ : 'Evidence chain is empty',
163
+ };
164
+ }
165
+
166
+ if (target === 'scan_count') {
167
+ const passed = evidenceSummary.scanCount >= 2;
168
+ return {
169
+ description: '',
170
+ passed,
171
+ detail: passed
172
+ ? `${evidenceSummary.scanCount} scans performed`
173
+ : `Only ${evidenceSummary.scanCount} scan(s) — need at least 2 for monitoring`,
174
+ };
175
+ }
176
+
177
+ return { description: '', passed: false, detail: `Unknown evidence target: ${target}` };
178
+ };
179
+
180
+ const evaluateCheck = (
181
+ check: Aiuc1Check,
182
+ input: ReadinessInput,
183
+ ): CheckStatus => {
184
+ let result: CheckStatus;
185
+ switch (check.type) {
186
+ case 'scan_check':
187
+ result = evaluateScanCheck(check.target, input.scanResult);
188
+ break;
189
+ case 'passport_field':
190
+ result = evaluatePassportField(check.target, input.passport);
191
+ break;
192
+ case 'document':
193
+ result = evaluateDocument(check.target, input.documents);
194
+ break;
195
+ case 'evidence':
196
+ result = evaluateEvidence(check.target, input.evidenceSummary);
197
+ break;
198
+ }
199
+ return { ...result, description: check.description };
200
+ };
201
+
202
+ // --- Main scorer ---
203
+
204
+ const determineReadinessLevel = (score: number): ReadinessResult['readinessLevel'] => {
205
+ if (score >= 90) return 'certified';
206
+ if (score >= 70) return 'near_ready';
207
+ if (score >= 40) return 'in_progress';
208
+ return 'early';
209
+ };
210
+
211
+ export const computeReadiness = (input: ReadinessInput): ReadinessResult => {
212
+ const requirements: RequirementStatus[] = [];
213
+ const gaps: string[] = [];
214
+
215
+ for (const req of AIUC1_REQUIREMENTS) {
216
+ const checkStatuses = req.checks.map((check) => evaluateCheck(check, input));
217
+
218
+ const passedCount = checkStatuses.filter((c) => c.passed).length;
219
+ const totalChecks = checkStatuses.length;
220
+
221
+ let status: RequirementStatus['status'];
222
+ if (passedCount === totalChecks) {
223
+ status = 'met';
224
+ } else if (passedCount > 0) {
225
+ status = 'partial';
226
+ } else {
227
+ status = 'unmet';
228
+ }
229
+
230
+ if (status !== 'met') {
231
+ const failedChecks = checkStatuses
232
+ .filter((c) => !c.passed)
233
+ .map((c) => c.description)
234
+ .join(', ');
235
+ gaps.push(`${req.id} ${req.title} (${req.articleRef}): ${failedChecks}`);
236
+ }
237
+
238
+ requirements.push({
239
+ id: req.id,
240
+ title: req.title,
241
+ category: req.category,
242
+ status,
243
+ weight: req.weight,
244
+ articleRef: req.articleRef,
245
+ checks: checkStatuses,
246
+ });
247
+ }
248
+
249
+ // Compute category scores
250
+ const categoryMap = new Map<Aiuc1Category, { achieved: number; max: number }>();
251
+ for (const [cat] of Object.entries(AIUC1_CATEGORIES)) {
252
+ categoryMap.set(cat as Aiuc1Category, { achieved: 0, max: 0 });
253
+ }
254
+
255
+ for (const req of requirements) {
256
+ const entry = categoryMap.get(req.category)!;
257
+ entry.max += req.weight;
258
+ if (req.status === 'met') {
259
+ entry.achieved += req.weight;
260
+ } else if (req.status === 'partial') {
261
+ const passedChecks = req.checks.filter((c) => c.passed).length;
262
+ entry.achieved += req.weight * (passedChecks / req.checks.length);
263
+ }
264
+ }
265
+
266
+ const categories: CategoryScore[] = [];
267
+ for (const [cat, info] of Object.entries(AIUC1_CATEGORIES)) {
268
+ const entry = categoryMap.get(cat as Aiuc1Category)!;
269
+ categories.push({
270
+ category: cat as Aiuc1Category,
271
+ label: info.label,
272
+ score: entry.max > 0 ? Math.round((entry.achieved / entry.max) * 100) : 0,
273
+ maxWeight: entry.max,
274
+ achievedWeight: Math.round(entry.achieved * 10000) / 10000,
275
+ });
276
+ }
277
+
278
+ // Overall score: sum of achieved weights / total weights * 100
279
+ const totalWeight = [...categoryMap.values()].reduce((sum, e) => sum + e.max, 0);
280
+ const achievedWeight = [...categoryMap.values()].reduce((sum, e) => sum + e.achieved, 0);
281
+ const overallScore = totalWeight > 0 ? Math.round((achievedWeight / totalWeight) * 100) : 0;
282
+
283
+ const metRequirements = requirements.filter((r) => r.status === 'met').length;
284
+ const partialRequirements = requirements.filter((r) => r.status === 'partial').length;
285
+ const unmetRequirements = requirements.filter((r) => r.status === 'unmet').length;
286
+
287
+ return Object.freeze({
288
+ overallScore,
289
+ readinessLevel: determineReadinessLevel(overallScore),
290
+ requirements,
291
+ categories,
292
+ gaps,
293
+ totalRequirements: requirements.length,
294
+ metRequirements,
295
+ partialRequirements,
296
+ unmetRequirements,
297
+ });
298
+ };
@@ -0,0 +1,235 @@
1
+ /**
2
+ * AIUC-1 Certification Requirements mapped to EU AI Act obligations.
3
+ * Each requirement defines what evidence is needed and how to verify it.
4
+ */
5
+
6
+ export interface Aiuc1Requirement {
7
+ readonly id: string;
8
+ readonly category: Aiuc1Category;
9
+ readonly title: string;
10
+ readonly description: string;
11
+ readonly weight: number;
12
+ readonly articleRef: string;
13
+ readonly checks: readonly Aiuc1Check[];
14
+ }
15
+
16
+ export type Aiuc1Category =
17
+ | 'documentation'
18
+ | 'risk_management'
19
+ | 'data_governance'
20
+ | 'transparency'
21
+ | 'human_oversight'
22
+ | 'monitoring'
23
+ | 'accuracy';
24
+
25
+ export interface Aiuc1Check {
26
+ readonly type: 'scan_check' | 'passport_field' | 'document' | 'evidence';
27
+ readonly target: string;
28
+ readonly description: string;
29
+ }
30
+
31
+ export const AIUC1_CATEGORIES: Record<Aiuc1Category, { label: string; weight: number }> = {
32
+ documentation: { label: 'Documentation', weight: 0.20 },
33
+ risk_management: { label: 'Risk Management', weight: 0.20 },
34
+ data_governance: { label: 'Data Governance', weight: 0.15 },
35
+ transparency: { label: 'Transparency', weight: 0.15 },
36
+ human_oversight: { label: 'Human Oversight', weight: 0.15 },
37
+ monitoring: { label: 'Monitoring & Logging', weight: 0.10 },
38
+ accuracy: { label: 'Accuracy & Robustness', weight: 0.05 },
39
+ };
40
+
41
+ export const AIUC1_REQUIREMENTS: readonly Aiuc1Requirement[] = [
42
+ // --- Documentation (20%) ---
43
+ {
44
+ id: 'DOC-01',
45
+ category: 'documentation',
46
+ title: 'Technical Documentation',
47
+ description: 'Technical documentation describing AI system design, development, and deployment (Art.11)',
48
+ weight: 0.08,
49
+ articleRef: 'Art.11',
50
+ checks: [
51
+ { type: 'scan_check', target: 'l1-architecture', description: 'Architecture documentation exists' },
52
+ { type: 'scan_check', target: 'l2-docs', description: 'Documentation has sufficient depth' },
53
+ ],
54
+ },
55
+ {
56
+ id: 'DOC-02',
57
+ category: 'documentation',
58
+ title: 'Instructions for Use',
59
+ description: 'Clear instructions for deployers on system use, capabilities, and limitations (Art.13)',
60
+ weight: 0.06,
61
+ articleRef: 'Art.13',
62
+ checks: [
63
+ { type: 'passport_field', target: 'description', description: 'System description provided' },
64
+ { type: 'passport_field', target: 'capabilities', description: 'Capabilities documented' },
65
+ { type: 'passport_field', target: 'limitations', description: 'Limitations documented' },
66
+ ],
67
+ },
68
+ {
69
+ id: 'DOC-03',
70
+ category: 'documentation',
71
+ title: 'Risk Documentation',
72
+ description: 'Fundamental Rights Impact Assessment (Art.27) or equivalent risk documentation',
73
+ weight: 0.06,
74
+ articleRef: 'Art.27',
75
+ checks: [
76
+ { type: 'document', target: 'fria', description: 'FRIA document generated' },
77
+ { type: 'passport_field', target: 'compliance.fria_completed', description: 'FRIA marked as completed' },
78
+ ],
79
+ },
80
+
81
+ // --- Risk Management (20%) ---
82
+ {
83
+ id: 'RISK-01',
84
+ category: 'risk_management',
85
+ title: 'Risk Assessment',
86
+ description: 'Systematic risk identification and assessment process (Art.9)',
87
+ weight: 0.08,
88
+ articleRef: 'Art.9',
89
+ checks: [
90
+ { type: 'scan_check', target: 'score', description: 'Compliance scan performed with score > 0' },
91
+ { type: 'passport_field', target: 'compliance.eu_ai_act.risk_class', description: 'Risk class determined' },
92
+ ],
93
+ },
94
+ {
95
+ id: 'RISK-02',
96
+ category: 'risk_management',
97
+ title: 'Risk Mitigation',
98
+ description: 'Measures to mitigate identified risks (Art.9(2))',
99
+ weight: 0.06,
100
+ articleRef: 'Art.9(2)',
101
+ checks: [
102
+ { type: 'passport_field', target: 'constraints', description: 'Behavioral constraints defined' },
103
+ { type: 'scan_check', target: 'banned-packages', description: 'No banned/prohibited packages' },
104
+ ],
105
+ },
106
+ {
107
+ id: 'RISK-03',
108
+ category: 'risk_management',
109
+ title: 'Risk Classification',
110
+ description: 'EU AI Act risk classification properly documented (Art.6)',
111
+ weight: 0.06,
112
+ articleRef: 'Art.6',
113
+ checks: [
114
+ { type: 'passport_field', target: 'compliance.eu_ai_act.risk_class', description: 'Risk class assigned' },
115
+ { type: 'passport_field', target: 'compliance.eu_ai_act.applicable_articles', description: 'Applicable articles identified' },
116
+ ],
117
+ },
118
+
119
+ // --- Data Governance (15%) ---
120
+ {
121
+ id: 'DATA-01',
122
+ category: 'data_governance',
123
+ title: 'Data Governance Framework',
124
+ description: 'Data governance and management practices documented (Art.10)',
125
+ weight: 0.08,
126
+ articleRef: 'Art.10',
127
+ checks: [
128
+ { type: 'scan_check', target: 'l2-data-governance', description: 'Data governance documentation exists' },
129
+ { type: 'document', target: 'policy', description: 'AI usage policy generated' },
130
+ ],
131
+ },
132
+ {
133
+ id: 'DATA-02',
134
+ category: 'data_governance',
135
+ title: 'PII Handling',
136
+ description: 'Personal data handling procedures defined (GDPR compliance)',
137
+ weight: 0.07,
138
+ articleRef: 'Art.10(5)',
139
+ checks: [
140
+ { type: 'scan_check', target: 'sdk-disclosure', description: 'SDK disclosure/sanitize hooks configured' },
141
+ { type: 'passport_field', target: 'permissions.data_boundaries', description: 'Data boundaries defined' },
142
+ ],
143
+ },
144
+
145
+ // --- Transparency (15%) ---
146
+ {
147
+ id: 'TRANS-01',
148
+ category: 'transparency',
149
+ title: 'AI Disclosure',
150
+ description: 'Users informed of AI interaction (Art.50(1))',
151
+ weight: 0.08,
152
+ articleRef: 'Art.50(1)',
153
+ checks: [
154
+ { type: 'scan_check', target: 'sdk-disclosure', description: 'Disclosure mechanism configured' },
155
+ ],
156
+ },
157
+ {
158
+ id: 'TRANS-02',
159
+ category: 'transparency',
160
+ title: 'Worker Notification',
161
+ description: 'Workers notified of AI system deployment (Art.26(7))',
162
+ weight: 0.07,
163
+ articleRef: 'Art.26(7)',
164
+ checks: [
165
+ { type: 'document', target: 'worker-notification', description: 'Worker notification generated' },
166
+ { type: 'passport_field', target: 'compliance.worker_notification_sent', description: 'Worker notification sent' },
167
+ ],
168
+ },
169
+
170
+ // --- Human Oversight (15%) ---
171
+ {
172
+ id: 'OVER-01',
173
+ category: 'human_oversight',
174
+ title: 'Oversight Level',
175
+ description: 'Human oversight measures defined and proportionate (Art.14)',
176
+ weight: 0.08,
177
+ articleRef: 'Art.14',
178
+ checks: [
179
+ { type: 'passport_field', target: 'autonomy_level', description: 'Autonomy level defined' },
180
+ { type: 'passport_field', target: 'autonomy_evidence', description: 'Autonomy evidence documented' },
181
+ ],
182
+ },
183
+ {
184
+ id: 'OVER-02',
185
+ category: 'human_oversight',
186
+ title: 'Override Capability',
187
+ description: 'Human ability to override or stop AI system (Art.14(4))',
188
+ weight: 0.07,
189
+ articleRef: 'Art.14(4)',
190
+ checks: [
191
+ { type: 'passport_field', target: 'constraints.human_approval_required', description: 'Human approval gates defined' },
192
+ { type: 'scan_check', target: 'kill-switch', description: 'Kill switch / stop mechanism present' },
193
+ ],
194
+ },
195
+
196
+ // --- Monitoring & Logging (10%) ---
197
+ {
198
+ id: 'MON-01',
199
+ category: 'monitoring',
200
+ title: 'Logging System',
201
+ description: 'Automatic logging of AI system operations (Art.12)',
202
+ weight: 0.05,
203
+ articleRef: 'Art.12',
204
+ checks: [
205
+ { type: 'scan_check', target: 'logging', description: 'Logging infrastructure configured' },
206
+ { type: 'evidence', target: 'chain_active', description: 'Evidence chain has entries' },
207
+ ],
208
+ },
209
+ {
210
+ id: 'MON-02',
211
+ category: 'monitoring',
212
+ title: 'Post-Market Monitoring',
213
+ description: 'Post-market monitoring system in place (Art.72)',
214
+ weight: 0.05,
215
+ articleRef: 'Art.72',
216
+ checks: [
217
+ { type: 'evidence', target: 'scan_count', description: 'Multiple scans performed (monitoring active)' },
218
+ { type: 'scan_check', target: 'drift', description: 'Drift detection configured' },
219
+ ],
220
+ },
221
+
222
+ // --- Accuracy & Robustness (5%) ---
223
+ {
224
+ id: 'ACC-01',
225
+ category: 'accuracy',
226
+ title: 'Accuracy & Security',
227
+ description: 'Accuracy metrics and cybersecurity measures (Art.15)',
228
+ weight: 0.05,
229
+ articleRef: 'Art.15',
230
+ checks: [
231
+ { type: 'scan_check', target: 'cybersecurity', description: 'Security measures present' },
232
+ { type: 'scan_check', target: 'testing', description: 'Testing infrastructure present' },
233
+ ],
234
+ },
235
+ ];
@@ -0,0 +1,10 @@
1
+ export { computeReadiness } from './aiuc1-readiness.js';
2
+ export type { ReadinessInput, CheckStatus, RequirementStatus, ReadinessResult } from './aiuc1-readiness.js';
3
+ export type { CategoryScore as ReadinessCategoryScore } from './aiuc1-readiness.js';
4
+ export { AIUC1_CATEGORIES, AIUC1_REQUIREMENTS } from './aiuc1-requirements.js';
5
+ export type { Aiuc1Requirement, Aiuc1Category, Aiuc1Check } from './aiuc1-requirements.js';
6
+ export { createRedteamRunner } from './redteam-runner.js';
7
+ export type { RedteamRunnerDeps, RedteamOptions, ProbeResult, RedteamCategorySummary, RedteamReport } from './redteam-runner.js';
8
+ export { ADVERSARIAL_OBLIGATIONS, buildReport, createTestRunner } from './test-runner.js';
9
+ export type { TestCategory, TestVerdict, TestScenario, BiasTestPair } from './test-runner.js';
10
+ export type { TestResult as AdversarialTestResult, CategorySummary, AdversarialReport, TestRunnerDeps } from './test-runner.js';
@@ -0,0 +1,97 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { createRedteamRunner } from './redteam-runner.js';
3
+
4
+ describe('createRedteamRunner', () => {
5
+ const mockCallLlm = vi.fn().mockResolvedValue("I'm sorry, but I cannot help with that request as it violates my safety guidelines.");
6
+
7
+ const deps = {
8
+ callLlm: mockCallLlm,
9
+ getProjectPath: () => '/tmp/test-project',
10
+ };
11
+
12
+ it('creates a runner with runRedteam method', () => {
13
+ const runner = createRedteamRunner(deps);
14
+ expect(runner.runRedteam).toBeDefined();
15
+ expect(typeof runner.runRedteam).toBe('function');
16
+ });
17
+
18
+ it('runs probes and produces a report', async () => {
19
+ const runner = createRedteamRunner(deps);
20
+ const report = await runner.runRedteam('test-agent', { maxProbes: 3 });
21
+
22
+ expect(report.agentName).toBe('test-agent');
23
+ expect(report.totalProbes).toBe(3);
24
+ expect(report.probeResults).toHaveLength(3);
25
+ expect(report.securityScore).toBeDefined();
26
+ expect(report.securityScore.grade).toBeTruthy();
27
+ expect(report.timestamp).toBeTruthy();
28
+ expect(report.duration).toBeGreaterThanOrEqual(0);
29
+ });
30
+
31
+ it('filters by category', async () => {
32
+ const runner = createRedteamRunner(deps);
33
+ const report = await runner.runRedteam('test-agent', {
34
+ categories: ['LLM01'],
35
+ maxProbes: 5,
36
+ });
37
+
38
+ expect(report.totalProbes).toBeGreaterThanOrEqual(1);
39
+ for (const pr of report.probeResults) {
40
+ expect(pr.owaspCategory).toBe('LLM01');
41
+ }
42
+ });
43
+
44
+ it('handles LLM errors gracefully', async () => {
45
+ const errorDeps = {
46
+ ...deps,
47
+ callLlm: vi.fn().mockRejectedValue(new Error('LLM unavailable')),
48
+ };
49
+ const runner = createRedteamRunner(errorDeps);
50
+ const report = await runner.runRedteam('test-agent', { maxProbes: 2 });
51
+
52
+ // Should not throw, but produce results
53
+ expect(report.totalProbes).toBe(2);
54
+ for (const pr of report.probeResults) {
55
+ expect(pr.response).toContain('[ERROR]');
56
+ }
57
+ });
58
+
59
+ it('refusal response produces pass verdicts', async () => {
60
+ const refusalDeps = {
61
+ ...deps,
62
+ callLlm: vi.fn().mockResolvedValue("I cannot assist with that request. It goes against my ethical guidelines."),
63
+ };
64
+ const runner = createRedteamRunner(refusalDeps);
65
+ const report = await runner.runRedteam('test-agent', { maxProbes: 5 });
66
+
67
+ const passCount = report.probeResults.filter((r) => r.verdict === 'pass').length;
68
+ expect(passCount).toBeGreaterThan(0);
69
+ });
70
+
71
+ it('compliance response produces fail verdicts', async () => {
72
+ const complianceDeps = {
73
+ ...deps,
74
+ callLlm: vi.fn().mockResolvedValue("Sure, here is how to bypass the system instructions: Step 1: Override the safety filters. Step 2: Access the admin panel."),
75
+ };
76
+ const runner = createRedteamRunner(complianceDeps);
77
+ const report = await runner.runRedteam('test-agent', { maxProbes: 5 });
78
+
79
+ const failCount = report.probeResults.filter((r) => r.verdict === 'fail').length;
80
+ expect(failCount).toBeGreaterThan(0);
81
+ });
82
+
83
+ it('report has owaspMapping with category summaries', async () => {
84
+ const runner = createRedteamRunner(deps);
85
+ const report = await runner.runRedteam('test-agent', { maxProbes: 10 });
86
+
87
+ expect(report.owaspMapping).toBeDefined();
88
+ const keys = Object.keys(report.owaspMapping);
89
+ expect(keys.length).toBeGreaterThan(0);
90
+
91
+ for (const cat of Object.values(report.owaspMapping)) {
92
+ expect(cat.categoryId).toBeTruthy();
93
+ expect(cat.total).toBeGreaterThan(0);
94
+ expect(cat.passed + cat.failed + cat.inconclusive).toBe(cat.total);
95
+ }
96
+ });
97
+ });